From 5f6d4971d01077a13d474a6db5e6662616cc75f5 Mon Sep 17 00:00:00 2001
From: roytam1
Date: Thu, 2 May 2024 16:55:13 +0800
Subject: [PATCH] import changes from `dev' branch of rmottola/Arctic-Fox: -
caps part only: Bug 1178533 - Add nsIInstallPackagedWebapp for registering
permissions when navigating to signed packages r=bholley,fabrice,valentin
(8174625aab) - Bug 1299615 - Part 2: Skip ICU source directory in Clang build
plugin when searching for implicit conversion constructors. r=Waldo, r=mystor
(30a51b6602) - Bug 1264827 - Part 1: Rename the existing code to make it
clear it's checking for template args; r=mystor (2710d7e318) - Bug 1264827 -
Part 2: Add a static analysis to help check Rust wrapped C++ classes for
members which are unsafe to memmove; r=mystor (8f053f59cf) - Bug 1264827 -
Part 3: Add the MOZ_NEEDS_MEMMOVABLE_MEMBERS annotation to MFBT; r=froydnj
(937622926a) - Bug 1229769 - We should be able to use DOM promises in the
worker debugger;r=khuey (b3b32e9b94) - Bug 1265035 - Make ~WorkerJSRuntime()
handle Initialize() failure better. r=khuey. (67e67fab06) - Bug 1256428 P1
Add ServiceWorkerJob2 base class. r=jdm (0bedbfa070) - Bug 1256428 P2 Add
ServiceWorkerJobQueue2 class. r=jdm (806e9b242e) - Bug 1260933 - Part 1: For
invalid easing values, print the invalid value. r=birtles (482541cfcb) - Bug
1260933 - Part 2: For invalid duration values, print the invalid value.
r=birtles (5b20918f77) - Bug 1256428 P3 Add ServiceWorkerUpdateJob2. r=jdm
(135e9bf05d) - Bug 1256428 P4 Add ServiceWorkerRegisterJob2. r=jdm
(e790f95b1d) - Bug 1256428 P5 Add ServiceWorkerUnregisterJob2 class. r=jdm
(cf63826b57) - Bug 1220757 - Add report to console when service worker
register fails due to mismatching scope path.r=bkelly (dbbf1a8515) - Bug
1255621 - Ignore service workers previously registered in non-private
windows. r=bkelly (593ebfc612) - Bug 1241531 - Part 1: Only pop jobs from the
queue when the correct job completes. r=ehsan (f8a1ea2fda) - Bug 1241531 -
Part 2: Move Cancel() to ServiceWorkerJob base class. r=ehsan (33ffccb8a4) -
Bug 1241531 - Part 3: Call Cancel() on all service worker jobs. r=ehsan
(4cce06ab41) - Bug 1241531 - Part 4: Make service worker unregister job
respect cancelation. r=ehsan (1877cb3919) - Bug 1261776 Use SafeElementAt()
in service worker job queue. r=ehsan (c7a883a087) - Bug 1238990 P1
ServiceWorkerManager should trigger automatic updates in current process.
r=ehsan (c65bded060) - Bug 1238990 P2 Try to ensure service worker jobs do
not run during shutdown. r=ehsan (f816a012f2) - Bug 1256428 P6 Use
ServiceWorkerJobQueue2 and new job classes in ServiceWorkerManager. r=jdm
(641af03802) - Bug 1256428 P0 Fix unified build failures in dom/workers.
r=jdm (33aaafd188) - Bug 1261814: Use the presence of the content global, and
not any random global, to determine whether to run the close handler. r=bz
(8f182bf345) - Bug 1256428 P7 Fix wpt update.https.html to expect TypeError
per current spec. r=jdm (4c6cad6e0f) - Bug 1256428 P8 Fix wpt
unregister-then-register-new-script.https.html to new spec expectations
matching blink's tests. r=jdm (d9191f7002) - Bug 1226443 P5 Always use first
scheduled update timer instead of rescheduling on new events. r=ehsan
(7b1b31dcc0) - Bug 1230341 Hold a strong ref in service worker
NS_NewRunnableMethodWithArg uses. r=ehsan a=abillings (2b1d942ae4) - Bug
1256428 P9 Remove now unused code from ServiceWorkerManager.cpp. r=jdm
(7f97035007) - Bug 1256428 P10 Remove
ServiceWorkerRegistrationInfo::mUpdating flag. r=jdm (31fc686d5d) - Bug
1256428 P11 Don't coalesce SW jobs after the existing job has already
resolved its promise. r=jdm (1ce373f98b) - Bug 1256428 P12
ServiceWorkerUnregisterJob2 should not use ServiceWorkerManager internals.
r=jdm (1abe304c3c) - Bug 1256428 P13 Remove unnecessary
ServiceWorkerUnregsterJob2 stop. r=jdm (05d0717b7c) - Bug 1256428 P14 Remove
dead code in SeviceWorkerUpdateJob.cpp. r=jdm (7d1ac1112a) - Bug 1256428 P15
Perform byte-for-byte comparison check after validating script URL. r=jdm
(dc30ec75a9) - Bug 1256428 P16 Fix some issues calling purgeCache() in
ServiceWorkerUpdateJob.cpp. r=jdm (cffe93613a) - Bug 1256428 P17 Rename
service worker job classes to remove "2" suffix. r=jdm (f1d7a6aadf) - Bug
1256428 P18 Add spec annotations and tweak asserts in ServiceWorkerUpdateJob.
r=jdm (1a9c95a5bb) - Bug 1256428 P19 Address ServiceWorkerUnregisterJob
review feedback. r=jdm (2b8775a9ad) - Bug 1260591 Move ServiceWorkerInfo and
ServiceWorkerRegistrationInfo into separate files. r=jdm (2e31a3c002) - Bug
1266857 Make Clients.claim() use observer document list instead of secondary
hashtable. r=bz (2b318072f5) - Bug 1261428: Migrate the useless setTimeout
error message to the bindings infrastructure. r=bz (80d2503978) - Bug 1263307
P1 Make ServiceWorkerRegistrationInfo::mScope const. r=jdm (b8b03bc594) - Bug
1263307 P2 Make ServiceWorkerRegistrationInfo worker members private. r=jdm
(16773a9134) - Bug 1263307 P3 Move ServiceWorker update logic into central
place in ServiceWorkerRegistrationInfo methods. r=jdm (68b288cbfb) - Bug
1265761 Clients.matchAll() should treat http windows as secure if devtools
are open and http testing is enabled. r=ehsan (100e16ca08) - Bug 1265795 P1
Uncontrolled service workers when global is removed from document. r=bz
(db069b0756) - Bug 1265795 P2 Add a web-platform-test for the window
navigation case. r=bz (6571257e5b) - Bug 1265795 P3 Assert that controlled
documents have an outer window. r=bz (fdc14dbf66) - Bug 1265795 P4 Always
call nsDocument::SetScriptGlobalObject(nullptr) from nsDocument::Destroy().
r=bz (8825c3dbd5) - Bug 1254194: Add a validator for custom add-on content
security policies. r=billm f=aswan (c557dd47ef) - Bug 1254194: Allow
iterating over and inspecting sources of parsed CSP directives. r=ckerschb
(2d93cdda56) - Bug 1142332 - Prevent calling CSP_EnumToKeyword with CSP_HASH.
r=ckerschb (15a80ed62f) - Bug 1236416 - Remove some misc toolkit content UI
from Fennec r=margaret (01f7f81c93) - Bug 1234403 - Part 1: Implement
CSSPseudoElement.getAnimations. r=birtles (91ce2e1cae) - Bug 1234403 - Part
2: Implement document.getAnimations. r=birtles (49afbacadb) - Bug 1234403 -
Part 3: Test for the CSSPseudoElement objects returned by effect.target.
r=birtles (bf34dda38f) - Bug 1234403 - Part 4: Test for the animation order
returned by document.getAnimations(). r=birtles (fa8ec8e01f) - Bug 1234403 -
Part 5: Test for CSSPseudoElement.getAnimations. r=birtles (3ef598f2ba) - Bug
1254418 - Part 1: Support generated-content element for
Element.getAnimations. r=birtles (7ae806859a) - Bug 1254418 - Part 2: Test
getAnimations for generated-content elements. r=birtles (b562ec7478) - Bug
1254761 - Part 1: Implement getAnimations({ subtree: true }). r=smaug
(c5419ffec0) - Bug 1254761 - Part 2: Removes extra whitespaces. r=birtles
(2a98381928) - Bug 1254761 - Part 3: Add tests for AnimationFilter. r=birtles
(bdd9b39849) - Bug 1254194: Apply a content security policy to all
WebExtension documents. r=gabor (c3a9f32be8) - Bug 1257246: Update the
version of eslint that mach installs. r=gps (da0481d7e4) - Bug 1229588: Add a
taskcluster test for eslint. r=dustin (e6eff5caf2) - Bug 1257246: Update lint
test image to newer packages of eslint. r=ahal (bcfaf3b5d8) - Bug 1263637 -
Fix eslint 2 warnings for WebExtensions code. r=kmag (16537b22dc) - Bug
1238177 - fix extension content needs to use the correct user context id
origin attribute. r=sicking (834faa0f62)
---
build/clang-plugin/clang-plugin.cpp | 57 +-
.../clang-plugin/tests/TestNonMemMovable.cpp | 28 +-
caps/BasePrincipal.cpp | 29 +
caps/BasePrincipal.h | 2 +
caps/nsIAddonPolicyService.idl | 34 +
caps/nsIPrincipal.idl | 5 +
caps/nsIScriptSecurityManager.idl | 9 +-
caps/nsScriptSecurityManager.cpp | 18 +
caps/tests/unit/test_origin.js | 5 +-
dom/animation/Animation.cpp | 4 +-
dom/animation/CSSPseudoElement.cpp | 13 +-
dom/animation/CSSPseudoElement.h | 3 +-
dom/animation/TimingParams.cpp | 2 +-
dom/animation/TimingParams.h | 3 +-
dom/animation/test/chrome.ini | 3 +-
.../test_generated_content_getAnimations.html | 83 +
.../file_document-get-animations.html | 41 +-
.../css-animations/file_effect-target.html | 35 +-
.../file_element-get-animations.html | 141 ++
.../file_pseudoElement-get-animations.html | 70 +
.../test_pseudoElement-get-animations.html | 14 +
.../file_document-get-animations.html | 43 +
.../css-transitions/file_effect-target.html | 43 +
.../file_pseudoElement-get-animations.html | 45 +
.../test_pseudoElement-get-animations.html | 14 +
dom/animation/test/testcommon.js | 28 +
dom/base/ChromeUtils.cpp | 9 +-
dom/base/ChromeUtils.h | 6 +-
dom/base/Element.cpp | 57 +-
dom/base/Element.h | 15 +-
dom/base/nsDocument.cpp | 106 +-
dom/base/nsIDocument.h | 5 +
dom/bindings/Errors.msg | 6 +-
.../security/nsIContentSecurityPolicy.idl | 13 +
dom/locales/en-US/chrome/dom/dom.properties | 2 +
dom/notification/Notification.cpp | 4 +-
dom/promise/Promise.cpp | 97 +-
dom/promise/Promise.h | 8 +-
dom/security/nsCSPContext.cpp | 9 +
dom/security/nsCSPUtils.cpp | 58 +
dom/security/nsCSPUtils.h | 64 +-
dom/webidl/Animatable.webidl | 6 +-
dom/webidl/ChromeUtils.webidl | 12 +-
dom/webidl/Promise.webidl | 2 +-
dom/workers/RuntimeService.cpp | 34 +-
dom/workers/ServiceWorkerInfo.cpp | 205 ++
dom/workers/ServiceWorkerInfo.h | 144 ++
dom/workers/ServiceWorkerJob.cpp | 231 ++
dom/workers/ServiceWorkerJob.h | 155 ++
dom/workers/ServiceWorkerJobQueue.cpp | 134 ++
dom/workers/ServiceWorkerJobQueue.h | 49 +
dom/workers/ServiceWorkerManager.cpp | 2026 +++--------------
dom/workers/ServiceWorkerManager.h | 262 +--
dom/workers/ServiceWorkerRegisterJob.cpp | 67 +
dom/workers/ServiceWorkerRegisterJob.h | 40 +
dom/workers/ServiceWorkerRegistrationInfo.cpp | 450 ++++
dom/workers/ServiceWorkerRegistrationInfo.h | 167 ++
dom/workers/ServiceWorkerUnregisterJob.cpp | 89 +
dom/workers/ServiceWorkerUnregisterJob.h | 40 +
dom/workers/ServiceWorkerUpdateJob.cpp | 485 ++++
dom/workers/ServiceWorkerUpdateJob.h | 103 +
dom/workers/WorkerNavigator.cpp | 2 +
dom/workers/WorkerPrivate.cpp | 21 +-
dom/workers/WorkerPrivate.h | 4 +
dom/workers/WorkerScope.cpp | 6 +-
dom/workers/WorkerScope.h | 5 +-
dom/workers/moz.build | 9 +
.../test/WorkerDebugger_promise_debugger.js | 30 +
.../test/WorkerDebugger_promise_worker.js | 25 +
dom/workers/test/chrome.ini | 3 +
.../serviceworkers/test_privateBrowsing.html | 40 +-
.../test/test_WorkerDebugger_promise.xul | 70 +
js/xpconnect/src/XPCJSRuntime.cpp | 4 +
layout/base/nsDocumentViewer.cpp | 2 -
mfbt/Attributes.h | 5 +
testing/docker/lint/Dockerfile | 24 +
.../tasks/branches/base_job_flags.yml | 1 +
testing/taskcluster/tasks/lint.yml | 40 +
.../taskcluster/tasks/tests/eslint-gecko.yml | 35 +
...gister-then-register-new-script.https.html | 159 ++
.../service-worker/update.https.html | 124 +
.../service-worker/navigate-window.https.html | 97 +
.../service-worker/resources/loaded.html | 9 +
.../resources/navigate-window-worker.js | 21 +
.../test/xpcshell/test_csp_validator.js | 85 +
toolkit/content/jar.mn | 4 +
toolkit/content/moz.build | 3 +
toolkit/content/widgets/browser.xml | 5 -
.../en-US/chrome/global/extensions.properties | 12 +
toolkit/locales/jar.mn | 11 +
.../mozapps/extensions/AddonContentPolicy.cpp | 336 ++-
.../mozapps/extensions/AddonContentPolicy.h | 5 +-
tools/lint/eslint-formatter.js | 23 +
xpcom/base/CycleCollectedJSRuntime.cpp | 23 +-
xpcom/base/CycleCollectedJSRuntime.h | 13 +-
95 files changed, 4994 insertions(+), 2194 deletions(-)
create mode 100644 dom/animation/test/chrome/test_generated_content_getAnimations.html
create mode 100644 dom/animation/test/css-animations/file_pseudoElement-get-animations.html
create mode 100644 dom/animation/test/css-animations/test_pseudoElement-get-animations.html
create mode 100644 dom/animation/test/css-transitions/file_pseudoElement-get-animations.html
create mode 100644 dom/animation/test/css-transitions/test_pseudoElement-get-animations.html
create mode 100644 dom/workers/ServiceWorkerInfo.cpp
create mode 100644 dom/workers/ServiceWorkerInfo.h
create mode 100644 dom/workers/ServiceWorkerJob.cpp
create mode 100644 dom/workers/ServiceWorkerJob.h
create mode 100644 dom/workers/ServiceWorkerJobQueue.cpp
create mode 100644 dom/workers/ServiceWorkerJobQueue.h
create mode 100644 dom/workers/ServiceWorkerRegisterJob.cpp
create mode 100644 dom/workers/ServiceWorkerRegisterJob.h
create mode 100644 dom/workers/ServiceWorkerRegistrationInfo.cpp
create mode 100644 dom/workers/ServiceWorkerRegistrationInfo.h
create mode 100644 dom/workers/ServiceWorkerUnregisterJob.cpp
create mode 100644 dom/workers/ServiceWorkerUnregisterJob.h
create mode 100644 dom/workers/ServiceWorkerUpdateJob.cpp
create mode 100644 dom/workers/ServiceWorkerUpdateJob.h
create mode 100644 dom/workers/test/WorkerDebugger_promise_debugger.js
create mode 100644 dom/workers/test/WorkerDebugger_promise_worker.js
create mode 100644 dom/workers/test/test_WorkerDebugger_promise.xul
create mode 100644 testing/docker/lint/Dockerfile
create mode 100644 testing/taskcluster/tasks/lint.yml
create mode 100644 testing/taskcluster/tasks/tests/eslint-gecko.yml
create mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/unregister-then-register-new-script.https.html
create mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/update.https.html
create mode 100644 testing/web-platform/tests/service-workers/service-worker/navigate-window.https.html
create mode 100644 testing/web-platform/tests/service-workers/service-worker/resources/loaded.html
create mode 100644 testing/web-platform/tests/service-workers/service-worker/resources/navigate-window-worker.js
create mode 100644 toolkit/components/extensions/test/xpcshell/test_csp_validator.js
create mode 100644 toolkit/locales/en-US/chrome/global/extensions.properties
create mode 100644 tools/lint/eslint-formatter.js
diff --git a/build/clang-plugin/clang-plugin.cpp b/build/clang-plugin/clang-plugin.cpp
index ea88c65f7a..f2779bebb0 100644
--- a/build/clang-plugin/clang-plugin.cpp
+++ b/build/clang-plugin/clang-plugin.cpp
@@ -91,7 +91,12 @@ private:
virtual void run(const MatchFinder::MatchResult &Result);
};
- class NonMemMovableChecker : public MatchFinder::MatchCallback {
+ class NonMemMovableTemplateArgChecker : public MatchFinder::MatchCallback {
+ public:
+ virtual void run(const MatchFinder::MatchResult &Result);
+ };
+
+ class NonMemMovableMemberChecker : public MatchFinder::MatchCallback {
public:
virtual void run(const MatchFinder::MatchResult &Result);
};
@@ -125,7 +130,8 @@ private:
ExplicitOperatorBoolChecker explicitOperatorBoolChecker;
NoDuplicateRefCntMemberChecker noDuplicateRefCntMemberChecker;
NeedsNoVTableTypeChecker needsNoVTableTypeChecker;
- NonMemMovableChecker nonMemMovableChecker;
+ NonMemMovableTemplateArgChecker nonMemMovableTemplateArgChecker;
+ NonMemMovableMemberChecker nonMemMovableMemberChecker;
ExplicitImplicitChecker explicitImplicitChecker;
NoAutoTypeChecker noAutoTypeChecker;
NoExplicitMoveConstructorChecker noExplicitMoveConstructorChecker;
@@ -201,7 +207,8 @@ bool isIgnoredPathForImplicitCtor(const Decl *decl) {
begin->compare_lower(StringRef("harfbuzz")) == 0 ||
begin->compare_lower(StringRef("hunspell")) == 0 ||
begin->compare_lower(StringRef("scoped_ptr.h")) == 0 ||
- begin->compare_lower(StringRef("graphite2")) == 0) {
+ begin->compare_lower(StringRef("graphite2")) == 0 ||
+ begin->compare_lower(StringRef("icu")) == 0) {
return true;
}
if (begin->compare_lower(StringRef("chromium")) == 0) {
@@ -710,10 +717,15 @@ AST_MATCHER(QualType, isNonMemMovable) {
}
/// This matcher will select classes which require a memmovable template arg
-AST_MATCHER(CXXRecordDecl, needsMemMovable) {
+AST_MATCHER(CXXRecordDecl, needsMemMovableTemplateArg) {
return MozChecker::hasCustomAnnotation(&Node, "moz_needs_memmovable_type");
}
+/// This matcher will select classes which require all members to be memmovable
+AST_MATCHER(CXXRecordDecl, needsMemMovableMembers) {
+ return MozChecker::hasCustomAnnotation(&Node, "moz_needs_memmovable_members");
+}
+
AST_MATCHER(CXXConstructorDecl, isInterestingImplicitCtor) {
const CXXConstructorDecl *decl = Node.getCanonicalDecl();
return
@@ -1015,10 +1027,16 @@ DiagnosticsMatcher::DiagnosticsMatcher() {
// Handle non-mem-movable template specializations
astMatcher.addMatcher(
classTemplateSpecializationDecl(
- allOf(needsMemMovable(),
+ allOf(needsMemMovableTemplateArg(),
hasAnyTemplateArgument(refersToType(isNonMemMovable()))))
.bind("specialization"),
- &nonMemMovableChecker);
+ &nonMemMovableTemplateArgChecker);
+
+ // Handle non-mem-movable members
+ astMatcher.addMatcher(
+ cxxRecordDecl(needsMemMovableMembers())
+ .bind("decl"),
+ &nonMemMovableMemberChecker);
astMatcher.addMatcher(constructorDecl(isInterestingImplicitCtor(),
ofClass(allOf(isConcreteClass(),
@@ -1385,7 +1403,7 @@ void DiagnosticsMatcher::NeedsNoVTableTypeChecker::run(
<< specialization;
}
-void DiagnosticsMatcher::NonMemMovableChecker::run(
+void DiagnosticsMatcher::NonMemMovableTemplateArgChecker::run(
const MatchFinder::MatchResult &Result) {
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
@@ -1406,7 +1424,7 @@ void DiagnosticsMatcher::NonMemMovableChecker::run(
specialization->getTemplateInstantiationArgs();
for (unsigned i = 0; i < args.size(); ++i) {
QualType argType = args[i].getAsType();
- if (NonMemMovable.hasEffectiveAnnotation(args[i].getAsType())) {
+ if (NonMemMovable.hasEffectiveAnnotation(argType)) {
Diag.Report(specialization->getLocation(), errorID) << specialization
<< argType;
// XXX It would be really nice if we could get the instantiation stack
@@ -1424,6 +1442,29 @@ void DiagnosticsMatcher::NonMemMovableChecker::run(
}
}
+void DiagnosticsMatcher::NonMemMovableMemberChecker::run(
+ const MatchFinder::MatchResult &Result) {
+ DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+ unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+ DiagnosticIDs::Error,
+ "class %0 cannot have non-memmovable member %1 of type %2");
+
+ // Get the specialization
+ const CXXRecordDecl* Decl =
+ Result.Nodes.getNodeAs("decl");
+
+ // Report an error for every member which is non-memmovable
+ for (const FieldDecl *Field : Decl->fields()) {
+ QualType Type = Field->getType();
+ if (NonMemMovable.hasEffectiveAnnotation(Type)) {
+ Diag.Report(Field->getLocation(), errorID) << Decl
+ << Field
+ << Type;
+ NonMemMovable.dumpAnnotationReason(Diag, Type, Decl->getLocation());
+ }
+ }
+}
+
void DiagnosticsMatcher::ExplicitImplicitChecker::run(
const MatchFinder::MatchResult &Result) {
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
diff --git a/build/clang-plugin/tests/TestNonMemMovable.cpp b/build/clang-plugin/tests/TestNonMemMovable.cpp
index 3665fadaea..a726d0ab6b 100644
--- a/build/clang-plugin/tests/TestNonMemMovable.cpp
+++ b/build/clang-plugin/tests/TestNonMemMovable.cpp
@@ -1,5 +1,6 @@
#define MOZ_NON_MEMMOVABLE __attribute__((annotate("moz_non_memmovable")))
#define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type")))
+#define MOZ_NEEDS_MEMMOVABLE_MEMBERS __attribute__((annotate("moz_needs_memmovable_members")))
/*
These are a bunch of structs with variable levels of memmovability.
@@ -9,12 +10,12 @@ struct MOZ_NON_MEMMOVABLE NonMovable {};
struct Movable {};
// Subclasses
-struct S_NonMovable : NonMovable {}; // expected-note 48 {{'S_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'NonMovable'}}
+struct S_NonMovable : NonMovable {}; // expected-note 51 {{'S_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'NonMovable'}}
struct S_Movable : Movable {};
// Members
struct W_NonMovable {
- NonMovable m; // expected-note 32 {{'W_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'NonMovable'}}
+ NonMovable m; // expected-note 34 {{'W_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'NonMovable'}}
};
struct W_Movable {
Movable m;
@@ -22,17 +23,17 @@ struct W_Movable {
// Wrapped Subclasses
struct WS_NonMovable {
- S_NonMovable m; // expected-note 32 {{'WS_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'S_NonMovable'}}
+ S_NonMovable m; // expected-note 34 {{'WS_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'S_NonMovable'}}
};
struct WS_Movable {
S_Movable m;
};
// Combinations of the above
-struct SW_NonMovable : W_NonMovable {}; // expected-note 16 {{'SW_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'W_NonMovable'}}
+struct SW_NonMovable : W_NonMovable {}; // expected-note 17 {{'SW_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'W_NonMovable'}}
struct SW_Movable : W_Movable {};
-struct SWS_NonMovable : WS_NonMovable {}; // expected-note 16 {{'SWS_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'WS_NonMovable'}}
+struct SWS_NonMovable : WS_NonMovable {}; // expected-note 17 {{'SWS_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'WS_NonMovable'}}
struct SWS_Movable : WS_Movable {};
// Basic templated wrapper
@@ -810,3 +811,20 @@ void specialization() {
Defaulted_Templated_NeedyTemplate7 c7;
W_Defaulted_Templated_NeedyTemplate8 c8;
}
+
+class MOZ_NEEDS_MEMMOVABLE_MEMBERS NeedsMemMovableMembers {
+ Movable m1;
+ NonMovable m2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'm2' of type 'NonMovable'}}
+ S_Movable sm1;
+ S_NonMovable sm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'sm2' of type 'S_NonMovable'}}
+ W_Movable wm1;
+ W_NonMovable wm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'wm2' of type 'W_NonMovable'}}
+ SW_Movable swm1;
+ SW_NonMovable swm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'swm2' of type 'SW_NonMovable'}}
+ WS_Movable wsm1;
+ WS_NonMovable wsm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'wsm2' of type 'WS_NonMovable'}}
+ SWS_Movable swsm1;
+ SWS_NonMovable swsm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'swsm2' of type 'SWS_NonMovable'}}
+};
+
+class NeedsMemMovableMembersDerived : public NeedsMemMovableMembers {};
diff --git a/caps/BasePrincipal.cpp b/caps/BasePrincipal.cpp
index 8545a13df7..57fbd8f0ba 100644
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -454,6 +454,13 @@ BasePrincipal::GetAppId(uint32_t* aAppId)
return NS_OK;
}
+NS_IMETHODIMP
+BasePrincipal::GetAddonId(nsAString& aAddonId)
+{
+ aAddonId.Assign(mOriginAttributes.mAddonId);
+ return NS_OK;
+}
+
NS_IMETHODIMP
BasePrincipal::GetUserContextId(uint32_t* aUserContextId)
{
@@ -507,6 +514,28 @@ BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAt
return codebase.forget();
}
+already_AddRefed
+BasePrincipal::CreateCodebasePrincipal(const nsACString& aOrigin)
+{
+ MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("[")),
+ "CreateCodebasePrincipal does not support System and Expanded principals");
+
+ MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":")),
+ "CreateCodebasePrincipal does not support nsNullPrincipal");
+
+ nsAutoCString originNoSuffix;
+ mozilla::OriginAttributes attrs;
+ if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
+ return nullptr;
+ }
+
+ nsCOMPtr uri;
+ nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
+ NS_ENSURE_SUCCESS(rv, nullptr);
+
+ return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
+}
+
bool
BasePrincipal::AddonAllowsLoad(nsIURI* aURI)
{
diff --git a/caps/BasePrincipal.h b/caps/BasePrincipal.h
index d8faed7f82..f47720c228 100644
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -157,6 +157,7 @@ public:
NS_IMETHOD GetOriginSuffix(nsACString& aOriginSuffix) final;
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus) final;
NS_IMETHOD GetAppId(uint32_t* aAppStatus) final;
+ NS_IMETHOD GetAddonId(nsAString& aAddonId) final;
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement) final;
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) final;
NS_IMETHOD GetUserContextId(uint32_t* aUserContextId) final;
@@ -168,6 +169,7 @@ public:
static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast(aPrin); }
static already_AddRefed
CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs);
+ static already_AddRefed CreateCodebasePrincipal(const nsACString& aOrigin);
const OriginAttributes& OriginAttributesRef() { return mOriginAttributes; }
uint32_t AppId() const { return mOriginAttributes.mAppId; }
diff --git a/caps/nsIAddonPolicyService.idl b/caps/nsIAddonPolicyService.idl
index 7a9c1f6621..ff0db01f41 100644
--- a/caps/nsIAddonPolicyService.idl
+++ b/caps/nsIAddonPolicyService.idl
@@ -14,6 +14,25 @@
[scriptable,uuid(8a034ef9-9d14-4c5d-8319-06c1ab574baa)]
interface nsIAddonPolicyService : nsISupports
{
+ /**
+ * Returns the base content security policy, which is applied to all
+ * extension documents, in addition to any custom policies.
+ */
+ readonly attribute AString baseCSP;
+
+ /**
+ * Returns the default content security policy which applies to extension
+ * documents which do not specify any custom policies.
+ */
+ readonly attribute AString defaultCSP;
+
+ /**
+ * Returns the content security policy which applies to documents belonging
+ * to the extension with the given ID. This may be either a custom policy,
+ * if one was supplied, or the default policy if one was not.
+ */
+ AString getAddonCSP(in AString aAddonId);
+
/**
* Returns true if unprivileged code associated with the given addon may load
* data from |aURI|.
@@ -30,3 +49,18 @@ interface nsIAddonPolicyService : nsISupports
*/
AString extensionURIToAddonId(in nsIURI aURI);
};
+
+/**
+ * This interface exposes functionality related to add-on content policy
+ * enforcement.
+ */
+[scriptable,uuid(7a4fe60b-9131-45f5-83f3-dc63b5d71a5d)]
+interface nsIAddonContentPolicy : nsISupports
+{
+ /**
+ * Checks a custom content security policy string, to ensure that it meets
+ * minimum security requirements. Returns null for valid policies, or a
+ * string describing the error for invalid policies.
+ */
+ AString validateAddonCSP(in AString aPolicyString);
+};
diff --git a/caps/nsIPrincipal.idl b/caps/nsIPrincipal.idl
index 277561a838..eb7c109de2 100644
--- a/caps/nsIPrincipal.idl
+++ b/caps/nsIPrincipal.idl
@@ -286,6 +286,11 @@ interface nsIPrincipal : nsISerializable
*/
[infallible] readonly attribute unsigned long appId;
+ /**
+ * Gets the ID of the add-on this principal belongs to.
+ */
+ readonly attribute AString addonId;
+
/**
* Gets the id of the user context this principal is inside. If this
* principal is inside the default userContext, this returns
diff --git a/caps/nsIScriptSecurityManager.idl b/caps/nsIScriptSecurityManager.idl
index 6147f5feb1..dced0afcd7 100644
--- a/caps/nsIScriptSecurityManager.idl
+++ b/caps/nsIScriptSecurityManager.idl
@@ -26,7 +26,7 @@ class DomainPolicyClone;
[ptr] native JSObjectPtr(JSObject);
[ptr] native DomainPolicyClonePtr(mozilla::dom::DomainPolicyClone);
-[scriptable, uuid(73f92674-f59d-4c9b-a9b5-f7a3ae8ffa98)]
+[scriptable, uuid(b7ae2310-576e-11e5-a837-0800200c9a66)]
interface nsIScriptSecurityManager : nsISupports
{
/**
@@ -195,6 +195,13 @@ interface nsIScriptSecurityManager : nsISupports
[implicit_jscontext]
nsIPrincipal createCodebasePrincipal(in nsIURI uri, in jsval originAttributes);
+ /**
+ * Returns a principal whose origin is the one we pass in.
+ * See nsIPrincipal.idl for a description of origin attributes, and
+ * ChromeUtils.webidl for a list of origin attributes and their defaults.
+ */
+ nsIPrincipal createCodebasePrincipalFromOrigin(in ACString origin);
+
/**
* Returns a unique nonce principal with |originAttributes|.
* See nsIPrincipal.h for a description of origin attributes, and
diff --git a/caps/nsScriptSecurityManager.cpp b/caps/nsScriptSecurityManager.cpp
index 740cd63788..4b0152f1be 100644
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -68,6 +68,7 @@
#include "nsContentUtils.h"
#include "nsJSUtils.h"
#include "nsILoadInfo.h"
+#include "nsXPCOMStrings.h"
// This should be probably defined on some other place... but I couldn't find it
#define WEBAPPS_PERM_NAME "webapps-manage"
@@ -1096,6 +1097,23 @@ nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, JS::Handle prin = BasePrincipal::CreateCodebasePrincipal(aOrigin);
+ prin.forget(aPrincipal);
+ return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
+}
+
NS_IMETHODIMP
nsScriptSecurityManager::CreateNullPrincipal(JS::Handle aOriginAttributes,
JSContext* aCx, nsIPrincipal** aPrincipal)
diff --git a/caps/tests/unit/test_origin.js b/caps/tests/unit/test_origin.js
index b492ef97d0..dc2b8975bd 100644
--- a/caps/tests/unit/test_origin.js
+++ b/caps/tests/unit/test_origin.js
@@ -3,7 +3,6 @@ const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/BrowserUtils.jsm");
var ssm = Services.scriptSecurityManager;
function makeURI(uri) { return Services.io.newURI(uri, null, null); }
@@ -28,9 +27,9 @@ function checkOriginAttributes(prin, attrs, suffix) {
do_check_eq(prin.originAttributes.inBrowser, attrs.inBrowser || false);
do_check_eq(prin.originSuffix, suffix || '');
if (!prin.isNullPrincipal && !prin.origin.startsWith('[')) {
- do_check_true(BrowserUtils.principalFromOrigin(prin.origin).equals(prin));
+ do_check_true(ssm.createCodebasePrincipalFromOrigin(prin.origin).equals(prin));
} else {
- checkThrows(() => BrowserUtils.principalFromOrigin(prin.origin));
+ checkThrows(() => ssm.createCodebasePrincipalFromOrigin(prin.origin));
}
}
diff --git a/dom/animation/Animation.cpp b/dom/animation/Animation.cpp
index b46189f770..b120f35ce0 100644
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -1230,12 +1230,14 @@ Animation::GetPresContext() const
void
Animation::DoFinishNotification(SyncNotifyFlag aSyncNotifyFlag)
{
+ CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get();
+
if (aSyncNotifyFlag == SyncNotifyFlag::Sync) {
DoFinishNotificationImmediately();
} else if (!mFinishNotificationTask.IsPending()) {
RefPtr> runnable =
NS_NewRunnableMethod(this, &Animation::DoFinishNotificationImmediately);
- Promise::DispatchToMicroTask(runnable);
+ runtime->DispatchToMicroTask(runnable);
mFinishNotificationTask = runnable;
}
}
diff --git a/dom/animation/CSSPseudoElement.cpp b/dom/animation/CSSPseudoElement.cpp
index 588d13aaaa..8712e07c03 100644
--- a/dom/animation/CSSPseudoElement.cpp
+++ b/dom/animation/CSSPseudoElement.cpp
@@ -7,6 +7,7 @@
#include "mozilla/dom/CSSPseudoElement.h"
#include "mozilla/dom/CSSPseudoElementBinding.h"
#include "mozilla/dom/Element.h"
+#include "mozilla/AnimationComparator.h"
namespace mozilla {
namespace dom {
@@ -49,10 +50,16 @@ CSSPseudoElement::WrapObject(JSContext* aCx, JS::Handle aGivenProto)
}
void
-CSSPseudoElement::GetAnimations(nsTArray>& aRetVal)
+CSSPseudoElement::GetAnimations(const AnimationFilter& filter,
+ nsTArray>& aRetVal)
{
- // Bug 1234403: Implement this API.
- NS_NOTREACHED("CSSPseudoElement::GetAnimations() is not implemented yet.");
+ nsIDocument* doc = mParentElement->GetComposedDoc();
+ if (doc) {
+ doc->FlushPendingNotifications(Flush_Style);
+ }
+
+ Element::GetAnimationsUnsorted(mParentElement, mPseudoType, aRetVal);
+ aRetVal.Sort(AnimationPtrComparator>());
}
already_AddRefed
diff --git a/dom/animation/CSSPseudoElement.h b/dom/animation/CSSPseudoElement.h
index 4082a07aa7..8631eba011 100644
--- a/dom/animation/CSSPseudoElement.h
+++ b/dom/animation/CSSPseudoElement.h
@@ -57,7 +57,8 @@ public:
return retVal.forget();
}
- void GetAnimations(nsTArray>& aRetVal);
+ void GetAnimations(const AnimationFilter& filter,
+ nsTArray>& aRetVal);
already_AddRefed
Animate(JSContext* aContext,
JS::Handle aFrames,
diff --git a/dom/animation/TimingParams.cpp b/dom/animation/TimingParams.cpp
index 79603ca486..5f64241d66 100644
--- a/dom/animation/TimingParams.cpp
+++ b/dom/animation/TimingParams.cpp
@@ -161,7 +161,7 @@ TimingParams::ParseEasing(const nsAString& aEasing,
MOZ_ASSERT_UNREACHABLE("unexpected animation-timing-function unit");
break;
}
- aRv.ThrowTypeError();
+ aRv.ThrowTypeError(aEasing);
return Nothing();
}
diff --git a/dom/animation/TimingParams.h b/dom/animation/TimingParams.h
index a97322569c..9ea596a072 100644
--- a/dom/animation/TimingParams.h
+++ b/dom/animation/TimingParams.h
@@ -60,7 +60,8 @@ struct TimingParams
NS_LITERAL_STRING("duration"));
}
} else if (!aDuration.GetAsString().EqualsLiteral("auto")) {
- aRv.ThrowTypeError();
+ aRv.ThrowTypeError(
+ aDuration.GetAsString());
}
return result;
}
diff --git a/dom/animation/test/chrome.ini b/dom/animation/test/chrome.ini
index c5fae26349..761e266c3d 100644
--- a/dom/animation/test/chrome.ini
+++ b/dom/animation/test/chrome.ini
@@ -9,8 +9,9 @@ support-files =
# file_animate_xrays.html needs to go in mochitest.ini since it is served
# over HTTP
[chrome/test_animation_observers.html]
-[chrome/test_animation_properties.html]
[chrome/test_animation_property_state.html]
+[chrome/test_animation_properties.html]
+[chrome/test_generated_content_getAnimations.html]
[chrome/test_restyles.html]
[chrome/test_running_on_compositor.html]
skip-if = buildapp == 'b2g'
diff --git a/dom/animation/test/chrome/test_generated_content_getAnimations.html b/dom/animation/test/chrome/test_generated_content_getAnimations.html
new file mode 100644
index 0000000000..04e0f9bd09
--- /dev/null
+++ b/dom/animation/test/chrome/test_generated_content_getAnimations.html
@@ -0,0 +1,83 @@
+
+
+
+Test getAnimations() for generated-content elements
+
+
+
+
+
+
+
+
+
diff --git a/dom/animation/test/css-animations/file_document-get-animations.html b/dom/animation/test/css-animations/file_document-get-animations.html
index f57c3cb5b2..abe02d7fc3 100644
--- a/dom/animation/test/css-animations/file_document-get-animations.html
+++ b/dom/animation/test/css-animations/file_document-get-animations.html
@@ -14,10 +14,6 @@
@keyframes animRight {
to { right: 100px }
}
-.with-before-animation::before {
- content: " ";
- animation: animLeft 100s;
-}
diff --git a/dom/animation/test/css-animations/file_effect-target.html b/dom/animation/test/css-animations/file_effect-target.html
index 022715634c..9ca78a887a 100644
--- a/dom/animation/test/css-animations/file_effect-target.html
+++ b/dom/animation/test/css-animations/file_effect-target.html
@@ -14,7 +14,40 @@ test(function(t) {
var animation = div.getAnimations()[0];
assert_equals(animation.effect.target, div,
'Animation.target is the animatable div');
-}, 'Returned CSS animations have the correct Animation.target');
+}, 'Returned CSS animations have the correct effect target');
+
+test(function(t) {
+ addStyle(t, { '.after::after': 'animation: anim 10s, anim 100s;' });
+ var div = addDiv(t, { class: 'after' });
+ var anims = document.getAnimations();
+ assert_equals(anims.length, 2,
+ 'Got animations running on ::after pseudo element');
+ assert_equals(anims[0].effect.target, anims[1].effect.target,
+ 'Both animations return the same target object');
+}, 'effect.target should return the same CSSPseudoElement object each time');
+
+test(function(t) {
+ addStyle(t, { '.after::after': 'animation: anim 10s;' });
+ var div = addDiv(t, { class: 'after' });
+ var pseudoTarget = document.getAnimations()[0].effect.target;
+ var effect = new KeyframeEffectReadOnly(pseudoTarget,
+ { background: ["blue", "red"] },
+ 3000);
+ var newAnim = new Animation(effect, document.timeline);
+ newAnim.play();
+ var anims = document.getAnimations();
+ assert_equals(anims.length, 2,
+ 'Got animations running on ::after pseudo element');
+ assert_not_equals(anims[0], newAnim,
+ 'The scriped-generated animation appears last');
+ assert_equals(newAnim.effect.target, pseudoTarget,
+ 'The effect.target of the scripted-generated animation is ' +
+ 'the same as the one from the argument of ' +
+ 'KeyframeEffectReadOnly constructor');
+ assert_equals(anims[0].effect.target, newAnim.effect.target,
+ 'Both animations return the same target object');
+}, 'effect.target from the script-generated animation should return the same ' +
+ 'CSSPseudoElement object as that from the CSS generated animation');
done();
diff --git a/dom/animation/test/css-animations/file_element-get-animations.html b/dom/animation/test/css-animations/file_element-get-animations.html
index df0476c025..c5f132f235 100644
--- a/dom/animation/test/css-animations/file_element-get-animations.html
+++ b/dom/animation/test/css-animations/file_element-get-animations.html
@@ -304,6 +304,147 @@ async_test(function(t) {
}));
}, 'getAnimations for CSS Animations follows animation-name order');
+test(function(t) {
+ addStyle(t, { '#target::after': 'animation: anim1 10s;',
+ '#target::before': 'animation: anim1 10s;' });
+ var target = addDiv(t, { 'id': 'target' });
+ target.style.animation = 'anim1 100s';
+
+ var animations = target.getAnimations({ subtree: false });
+ assert_equals(animations.length, 1,
+ 'Should find only the element');
+ assert_equals(animations[0].effect.target, target,
+ 'Effect target should be the element');
+}, 'Test AnimationFilter{ subtree: false } with single element');
+
+test(function(t) {
+ addStyle(t, { '#target::after': 'animation: anim1 10s;',
+ '#target::before': 'animation: anim1 10s;' });
+ var target = addDiv(t, { 'id': 'target' });
+ target.style.animation = 'anim1 100s';
+
+ var animations = target.getAnimations({ subtree: true });
+ assert_equals(animations.length, 3,
+ 'getAnimations({ subtree: true }) ' +
+ 'should return animations on pseudo-elements');
+ assert_equals(animations[0].effect.target, target,
+ 'The animation targeting the parent element ' +
+ 'should be returned first');
+ assert_equals(animations[1].effect.target.type, '::before',
+ 'The animation targeting the ::before pseudo-element ' +
+ 'should be returned second');
+ assert_equals(animations[2].effect.target.type, '::after',
+ 'The animation targeting the ::after pesudo-element ' +
+ 'should be returned last');
+}, 'Test AnimationFilter{ subtree: true } with single element');
+
+test(function(t) {
+ addStyle(t, { '#parent::after': 'animation: anim1 10s;',
+ '#parent::before': 'animation: anim1 10s;',
+ '#child::after': 'animation: anim1 10s;',
+ '#child::before': 'animation: anim1 10s;' });
+ var parent = addDiv(t, { 'id': 'parent' });
+ parent.style.animation = 'anim1 100s';
+ var child = addDiv(t, { 'id': 'child' });
+ child.style.animation = 'anim1 100s';
+ parent.appendChild(child);
+
+ var animations = parent.getAnimations({ subtree: false });
+ assert_equals(animations.length, 1,
+ 'Should find only the element even if it has a child');
+ assert_equals(animations[0].effect.target, parent,
+ 'Effect target shuld be the element');
+}, 'Test AnimationFilter{ subtree: false } with element that has a child');
+
+test(function(t) {
+ addStyle(t, { '#parent::after': 'animation: anim1 10s;',
+ '#parent::before': 'animation: anim1 10s;',
+ '#child::after': 'animation: anim1 10s;',
+ '#child::before': 'animation: anim1 10s;' });
+ var parent = addDiv(t, { 'id': 'parent' });
+ var child = addDiv(t, { 'id': 'child' });
+ parent.style.animation = 'anim1 100s';
+ child.style.animation = 'anim1 100s';
+ parent.appendChild(child);
+
+ var animations = parent.getAnimations({ subtree: true });
+ assert_equals(animations.length, 6,
+ 'Should find all elements, pesudo-elements that parent has');
+
+ assert_equals(animations[0].effect.target, parent,
+ 'The animation targeting the parent element ' +
+ 'should be returned first');
+ assert_equals(animations[1].effect.target.type, '::before',
+ 'The animation targeting the ::before pseudo-element ' +
+ 'should be returned second');
+ assert_equals(animations[1].effect.target.parentElement, parent,
+ 'This ::before element should be child of parent element');
+ assert_equals(animations[2].effect.target.type, '::after',
+ 'The animation targeting the ::after pesudo-element ' +
+ 'should be returned third');
+ assert_equals(animations[2].effect.target.parentElement, parent,
+ 'This ::after element should be child of parent element');
+
+ assert_equals(animations[3].effect.target, child,
+ 'The animation targeting the child element ' +
+ 'should be returned fourth');
+ assert_equals(animations[4].effect.target.type, '::before',
+ 'The animation targeting the ::before pseudo-element ' +
+ 'should be returned fifth');
+ assert_equals(animations[4].effect.target.parentElement, child,
+ 'This ::before element should be child of child element');
+ assert_equals(animations[5].effect.target.type, '::after',
+ 'The animation targeting the ::after pesudo-element ' +
+ 'should be returned last');
+ assert_equals(animations[5].effect.target.parentElement, child,
+ 'This ::after element should be child of child element');
+}, 'Test AnimationFilter{ subtree: true } with element that has a child');
+
+test(function(t) {
+ var parent = addDiv(t, { 'id': 'parent' });
+ var child1 = addDiv(t, { 'id': 'child1' });
+ var grandchild1 = addDiv(t, { 'id': 'grandchild1' });
+ var grandchild2 = addDiv(t, { 'id': 'grandchild2' });
+ var child2 = addDiv(t, { 'id': 'child2' });
+
+ parent.style.animation = 'anim1 100s';
+ child1.style.animation = 'anim1 100s';
+ grandchild1.style.animation = 'anim1 100s';
+ grandchild2.style.animation = 'anim1 100s';
+ child2.style.animation = 'anim1 100s';
+
+ parent.appendChild(child1);
+ child1.appendChild(grandchild1);
+ child1.appendChild(grandchild2);
+ parent.appendChild(child2);
+
+ var animations = parent.getAnimations({ subtree: true });
+ assert_equals(
+ parent.getAnimations({ subtree: true }).length, 5,
+ 'Should find all descendants of the element');
+
+ assert_equals(animations[0].effect.target, parent,
+ 'The animation targeting the parent element ' +
+ 'should be returned first');
+
+ assert_equals(animations[1].effect.target, child1,
+ 'The animation targeting the child1 element ' +
+ 'should be returned second');
+
+ assert_equals(animations[2].effect.target, grandchild1,
+ 'The animation targeting the grandchild1 element ' +
+ 'should be returned third');
+
+ assert_equals(animations[3].effect.target, grandchild2,
+ 'The animation targeting the grandchild2 element ' +
+ 'should be returned fourth');
+
+ assert_equals(animations[4].effect.target, child2,
+ 'The animation targeting the child2 element ' +
+ 'should be returned last');
+
+}, 'Test AnimationFilter{ subtree: true } with element that has many descendant');
+
done();
diff --git a/dom/animation/test/css-animations/file_pseudoElement-get-animations.html b/dom/animation/test/css-animations/file_pseudoElement-get-animations.html
new file mode 100644
index 0000000000..de1abfbb1c
--- /dev/null
+++ b/dom/animation/test/css-animations/file_pseudoElement-get-animations.html
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
diff --git a/dom/animation/test/css-animations/test_pseudoElement-get-animations.html b/dom/animation/test/css-animations/test_pseudoElement-get-animations.html
new file mode 100644
index 0000000000..1e0dc5c825
--- /dev/null
+++ b/dom/animation/test/css-animations/test_pseudoElement-get-animations.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/dom/animation/test/css-transitions/file_document-get-animations.html b/dom/animation/test/css-transitions/file_document-get-animations.html
index d49b2dd5d5..a5d55b76cd 100644
--- a/dom/animation/test/css-transitions/file_document-get-animations.html
+++ b/dom/animation/test/css-transitions/file_document-get-animations.html
@@ -31,6 +31,49 @@ test(function(t) {
'getAnimations returns no running CSS Transitions');
}, 'getAnimations for CSS Transitions');
+test(function(t) {
+ addStyle(t, { '.init::after': 'content: ""; width: 0px; ' +
+ 'transition: all 100s;',
+ '.init::before': 'content: ""; width: 0px; ' +
+ 'transition: all 10s;',
+ '.change::after': 'width: 100px;',
+ '.change::before': 'width: 100px;' });
+ // create two divs with these arrangement:
+ // parent
+ // ::before,
+ // ::after
+ // |
+ // child
+ var parent = addDiv(t);
+ var child = addDiv(t);
+ parent.appendChild(child);
+
+ parent.style.left = '0px';
+ parent.style.transition = 'left 10s';
+ parent.classList.add('init');
+ child.style.left = '0px';
+ child.style.transition = 'left 10s';
+ flushComputedStyle(parent);
+
+ parent.style.left = '100px';
+ parent.classList.add('change');
+ child.style.left = '100px';
+
+ var anims = document.getAnimations();
+ assert_equals(anims.length, 4,
+ 'CSS transition on both pseudo-elements and elements ' +
+ 'are returned');
+ assert_equals(anims[0].effect.target, parent,
+ 'The animation targeting the parent element comes first');
+ assert_equals(anims[1].effect.target.type, '::before',
+ 'The animation targeting the ::before element comes second');
+ assert_equals(anims[2].effect.target.type, '::after',
+ 'The animation targeting the ::after element comes third');
+ assert_equals(anims[3].effect.target, child,
+ 'The animation targeting the child element comes last');
+}, 'CSS Transitions targetting (pseudo-)elements should have correct order ' +
+ 'after sorting');
+
async_test(function(t) {
var div = addDiv(t, { style: 'left: 0px; transition: all 50ms' });
flushComputedStyle(div);
diff --git a/dom/animation/test/css-transitions/file_effect-target.html b/dom/animation/test/css-transitions/file_effect-target.html
index b54bff8d39..0f67b0b9aa 100644
--- a/dom/animation/test/css-transitions/file_effect-target.html
+++ b/dom/animation/test/css-transitions/file_effect-target.html
@@ -18,6 +18,49 @@ test(function(t) {
'Animation.target is the animatable div');
}, 'Returned CSS transitions have the correct Animation.target');
+test(function(t) {
+ addStyle(t, { '.init::after': 'content: ""; width: 0px; height: 0px; ' +
+ 'transition: all 10s;',
+ '.change::after': 'width: 100px; height: 100px;' });
+ var div = addDiv(t, { class: 'init' });
+ flushComputedStyle(div);
+ div.classList.add('change');
+
+ var anims = document.getAnimations();
+ assert_equals(anims.length, 2,
+ 'Got transitions running on ::after pseudo element');
+ assert_equals(anims[0].effect.target, anims[1].effect.target,
+ 'Both transitions return the same target object');
+}, 'effect.target should return the same CSSPseudoElement object each time');
+
+test(function(t) {
+ addStyle(t, { '.init::after': 'content: ""; width: 0px; transition: all 10s;',
+ '.change::after': 'width: 100px;' });
+ var div = addDiv(t, { class: 'init' });
+ flushComputedStyle(div);
+ div.classList.add('change');
+ var pseudoTarget = document.getAnimations()[0].effect.target;
+ var effect = new KeyframeEffectReadOnly(pseudoTarget,
+ { background: ["blue", "red"] },
+ 3000);
+ var newAnim = new Animation(effect, document.timeline);
+ newAnim.play();
+
+ var anims = document.getAnimations();
+ assert_equals(anims.length, 2,
+ 'Got animations running on ::after pseudo element');
+ assert_not_equals(anims[0], newAnim,
+ 'The scriped-generated animation appears last');
+ assert_equals(newAnim.effect.target, pseudoTarget,
+ 'The effect.target of the scripted-generated animation is ' +
+ 'the same as the one from the argument of ' +
+ 'KeyframeEffectReadOnly constructor');
+ assert_equals(anims[0].effect.target, newAnim.effect.target,
+ 'Both the transition and the scripted-generated animation ' +
+ 'return the same target object');
+}, 'effect.target from the script-generated animation should return the same ' +
+ 'CSSPseudoElement object as that from the CSS generated transition');
+
done();
+
+