Bug 1479793. Throw when someone tries to define an accessor property with an integer name on a DOM proxy with an indexed setter. r=qdot,jorendorff
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 10 Aug 2018 17:04:58 +0000
changeset 431011 5d5bb48ca0b9dc79f6f0c62f3f11b97c6f25cd2d
parent 431010 ce455e421b0b4656a66dca47b004ba61669ba022
child 431012 c5109843829d5758ac7e5ad618b826141396ad59
push id67634
push userbzbarsky@mozilla.com
push dateFri, 10 Aug 2018 17:06:35 +0000
treeherderautoland@5d5bb48ca0b9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot, jorendorff
bugs1479793
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1479793. Throw when someone tries to define an accessor property with an integer name on a DOM proxy with an indexed setter. r=qdot,jorendorff Differential Revision: https://phabricator.services.mozilla.com/D2571
dom/bindings/Codegen.py
js/public/Class.h
js/src/js.msg
js/src/jsapi.cpp
testing/web-platform/meta/WebIDL/ecmascript-binding/legacy-platform-object.html.ini
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -11431,16 +11431,22 @@ class CGDOMJSProxyHandler_defineProperty
 
         indexedSetter = self.descriptor.operations['IndexedSetter']
         if indexedSetter:
             set += fill(
                 """
                 uint32_t index = GetArrayIndexFromId(cx, id);
                 if (IsArrayIndex(index)) {
                   *defined = true;
+                  // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty
+                  // Step 1.1.  The no-indexed-setter case is handled by step 1.2.
+                  if (!desc.isDataDescriptor()) {
+                    return opresult.failNotDataDescriptor();
+                  }
+
                   $*{callSetter}
                   return opresult.succeed();
                 }
                 """,
                 callSetter=CGProxyIndexedSetter(self.descriptor).define())
         elif self.descriptor.supportsIndexedProperties():
             # We allow untrusted content to prevent Xrays from setting a
             # property if that property is an indexed property and we have no
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -197,16 +197,17 @@ class ObjectOpResult
     JS_PUBLIC_API(bool) failCantSetInterposed();
     JS_PUBLIC_API(bool) failCantDefineWindowElement();
     JS_PUBLIC_API(bool) failCantDeleteWindowElement();
     JS_PUBLIC_API(bool) failCantDeleteWindowNamedProperty();
     JS_PUBLIC_API(bool) failCantPreventExtensions();
     JS_PUBLIC_API(bool) failCantSetProto();
     JS_PUBLIC_API(bool) failNoNamedSetter();
     JS_PUBLIC_API(bool) failNoIndexedSetter();
+    JS_PUBLIC_API(bool) failNotDataDescriptor();
 
     uint32_t failureCode() const {
         MOZ_ASSERT(!ok());
         return uint32_t(code_);
     }
 
     /*
      * Report an error or warning if necessary; return true to proceed and
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -583,16 +583,17 @@ MSG_DEF(JSMSG_ATOMICS_WAIT_NOT_ALLOWED, 
 // XPConnect wrappers and DOM bindings
 MSG_DEF(JSMSG_CANT_SET_INTERPOSED,       1, JSEXN_TYPEERR, "unable to set interposed data property '{0}'")
 MSG_DEF(JSMSG_CANT_DEFINE_WINDOW_ELEMENT, 0, JSEXN_TYPEERR, "can't define elements on a Window object")
 MSG_DEF(JSMSG_CANT_DELETE_WINDOW_ELEMENT, 0, JSEXN_TYPEERR, "can't delete elements from a Window object")
 MSG_DEF(JSMSG_CANT_DELETE_WINDOW_NAMED_PROPERTY, 1, JSEXN_TYPEERR, "can't delete property {0} from window's named properties object")
 MSG_DEF(JSMSG_CANT_PREVENT_EXTENSIONS,   0, JSEXN_TYPEERR, "can't prevent extensions on this proxy object")
 MSG_DEF(JSMSG_NO_NAMED_SETTER,           2, JSEXN_TYPEERR, "{0} doesn't have a named property setter for '{1}'")
 MSG_DEF(JSMSG_NO_INDEXED_SETTER,         2, JSEXN_TYPEERR, "{0} doesn't have an indexed property setter for '{1}'")
+MSG_DEF(JSMSG_NOT_DATA_DESCRIPTOR,       2, JSEXN_TYPEERR, "can't define a getter/setter for element '{1}' of {0} object")
 
 // Super
 MSG_DEF(JSMSG_CANT_DELETE_SUPER, 0, JSEXN_REFERENCEERR, "invalid delete involving 'super'")
 MSG_DEF(JSMSG_REINIT_THIS,       0, JSEXN_REFERENCEERR, "super() called twice in derived class constructor")
 
 // Modules
 MSG_DEF(JSMSG_BAD_DEFAULT_EXPORT,        0, JSEXN_SYNTAXERR, "default export cannot be provided by export *")
 MSG_DEF(JSMSG_MISSING_INDIRECT_EXPORT,   0, JSEXN_SYNTAXERR, "indirect export not found")
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -274,16 +274,22 @@ JS::ObjectOpResult::failNoNamedSetter()
 }
 
 JS_PUBLIC_API(bool)
 JS::ObjectOpResult::failNoIndexedSetter()
 {
     return fail(JSMSG_NO_INDEXED_SETTER);
 }
 
+JS_PUBLIC_API(bool)
+JS::ObjectOpResult::failNotDataDescriptor()
+{
+    return fail(JSMSG_NOT_DATA_DESCRIPTOR);
+}
+
 JS_PUBLIC_API(int64_t)
 JS_Now()
 {
     return PRMJ_Now();
 }
 
 JS_PUBLIC_API(Value)
 JS_GetNaNValue(JSContext* cx)
deleted file mode 100644
--- a/testing/web-platform/meta/WebIDL/ecmascript-binding/legacy-platform-object.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[legacy-platform-object.html]
-  [Test [[DefineOwnProperty\]\] with indexed property setter support.]
-    expected: FAIL
-