PropertyAttribute needs a CustomValue bit.
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Dec 2018 02:42:27 +0000 (02:42 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Dec 2018 02:42:27 +0000 (02:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191993
<rdar://problem/46264467>

Reviewed by Saam Barati.

JSTests:

* stress/regress-191993.js: Added.

Source/JavaScriptCore:

This is because GetByIdStatus needs to distinguish CustomValue properties from
other types, and its only means of doing so is via the property's attributes.
Previously, there's nothing in the property's attributes that can indicate that
the property is a CustomValue.

We fix this by doing the following:

1. Added a PropertyAttribute::CustomValue bit.
2. Added a PropertyAttribute::CustomAccessorOrValue convenience bit mask that is
   CustomAccessor | CustomValue.

3. Since CustomGetterSetter properties are only set via JSObject::putDirectCustomAccessor(),
   we added a check in JSObject::putDirectCustomAccessor() to see if the attributes
   bits include PropertyAttribute::CustomAccessor.  If not, then the property
   must be a CustomValue, and we'll add the PropertyAttribute::CustomValue bit
   to the attributes bits.

   This ensures that the property attributes is sufficient to tell us if the
   property contains a CustomGetterSetter.

4. Updated all checks for PropertyAttribute::CustomAccessor to check for
   PropertyAttribute::CustomAccessorOrValue instead if their intent is to check
   for the presence of a CustomGetterSetter as opposed to checking specifically
   for one that is used as a CustomAccessor.

   This includes all the Structure transition code that needs to capture the
   attributes change when a CustomValue has been added.

5. Filtered out the PropertyAttribute::CustomValue bit in PropertyDescriptor.
   The fact that we're using a CustomGetterSetter as a CustomValue should remain
   invisible to the descriptor.  This is because the descriptor should describe
   a CustomValue no differently from a plain value.

6. Added some asserts to ensure that property attributes are as expected, and to
   document some invariants.

* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFromLLInt):
(JSC::GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback):
(JSC::GetByIdStatus::computeFor):
* bytecode/InByIdStatus.cpp:
(JSC::InByIdStatus::computeForStubInfoWithoutExitSiteFeedback):
* bytecode/PropertyCondition.cpp:
(JSC::PropertyCondition::isStillValidAssumingImpurePropertyWatchpoint const):
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFor):
* runtime/JSFunction.cpp:
(JSC::getCalculatedDisplayName):
* runtime/JSObject.cpp:
(JSC::JSObject::putDirectCustomAccessor):
(JSC::JSObject::putDirectNonIndexAccessor):
(JSC::JSObject::putDirectIndexSlowOrBeyondVectorLength):
* runtime/JSObject.h:
(JSC::JSObject::putDirectIndex):
(JSC::JSObject::fillCustomGetterPropertySlot):
(JSC::JSObject::putDirect):
* runtime/JSObjectInlines.h:
(JSC::JSObject::putDirectInternal):
* runtime/PropertyDescriptor.cpp:
(JSC::PropertyDescriptor::setDescriptor):
(JSC::PropertyDescriptor::setCustomDescriptor):
(JSC::PropertyDescriptor::setAccessorDescriptor):
* runtime/PropertySlot.h:
(JSC::PropertySlot::setCustomGetterSetter):

Source/WebCore:

This patch revealed a bug in the CodeGenerator where a constructor property is
set with a ReadOnly attribute.  This conflicts with the WebIDL link (see clause
12 in https://heycam.github.io/webidl/#interface-prototype-object) which states
that it should be [Writable].  The ReadOnly attribute is now removed.

On the WebCore side, this change is covered by existing tests.

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateImplementation):
* bindings/scripts/test/JS/JSTestCustomConstructorWithNoInterfaceObject.cpp:
(WebCore::jsTestCustomConstructorWithNoInterfaceObjectConstructor):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239062 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
JSTests/ChangeLog
JSTests/stress/regress-191993.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
Source/JavaScriptCore/bytecode/InByIdStatus.cpp
Source/JavaScriptCore/bytecode/PropertyCondition.cpp
Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/JSObjectInlines.h
Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
Source/JavaScriptCore/runtime/PropertySlot.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/test/JS/JSTestCustomConstructorWithNoInterfaceObject.cpp

index caa0a56..c6b86c9 100644 (file)
@@ -1,3 +1,13 @@
+2018-12-10  Mark Lam  <mark.lam@apple.com>
+
+        PropertyAttribute needs a CustomValue bit.
+        https://bugs.webkit.org/show_bug.cgi?id=191993
+        <rdar://problem/46264467>
+
+        Reviewed by Saam Barati.
+
+        * stress/regress-191993.js: Added.
+
 2018-12-10  Caio Lima  <ticaiolima@gmail.com>
 
         [BigInt] Add ValueMul into DFG
diff --git a/JSTests/stress/regress-191993.js b/JSTests/stress/regress-191993.js
new file mode 100644 (file)
index 0000000..bb62569
--- /dev/null
@@ -0,0 +1,13 @@
+function foo(o) {
+    return o.r.input;
+}
+noInline(foo);
+
+Object.assign({}, RegExp);
+
+for (let i = 0; i < 10000; i++)
+    foo({r: RegExp});
+
+let input = foo({r: RegExp});
+if (typeof input !== "string")
+    throw "FAILED";
index 327678e..cddcb65 100644 (file)
@@ -1,5 +1,78 @@
 2018-12-10  Mark Lam  <mark.lam@apple.com>
 
+        PropertyAttribute needs a CustomValue bit.
+        https://bugs.webkit.org/show_bug.cgi?id=191993
+        <rdar://problem/46264467>
+
+        Reviewed by Saam Barati.
+
+        This is because GetByIdStatus needs to distinguish CustomValue properties from
+        other types, and its only means of doing so is via the property's attributes.
+        Previously, there's nothing in the property's attributes that can indicate that
+        the property is a CustomValue.
+
+        We fix this by doing the following:
+
+        1. Added a PropertyAttribute::CustomValue bit.
+        2. Added a PropertyAttribute::CustomAccessorOrValue convenience bit mask that is
+           CustomAccessor | CustomValue.
+
+        3. Since CustomGetterSetter properties are only set via JSObject::putDirectCustomAccessor(),
+           we added a check in JSObject::putDirectCustomAccessor() to see if the attributes
+           bits include PropertyAttribute::CustomAccessor.  If not, then the property
+           must be a CustomValue, and we'll add the PropertyAttribute::CustomValue bit
+           to the attributes bits.
+
+           This ensures that the property attributes is sufficient to tell us if the
+           property contains a CustomGetterSetter.
+
+        4. Updated all checks for PropertyAttribute::CustomAccessor to check for
+           PropertyAttribute::CustomAccessorOrValue instead if their intent is to check
+           for the presence of a CustomGetterSetter as opposed to checking specifically
+           for one that is used as a CustomAccessor.
+
+           This includes all the Structure transition code that needs to capture the
+           attributes change when a CustomValue has been added.
+
+        5. Filtered out the PropertyAttribute::CustomValue bit in PropertyDescriptor.
+           The fact that we're using a CustomGetterSetter as a CustomValue should remain
+           invisible to the descriptor.  This is because the descriptor should describe
+           a CustomValue no differently from a plain value.
+
+        6. Added some asserts to ensure that property attributes are as expected, and to
+           document some invariants.
+
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::computeFromLLInt):
+        (JSC::GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback):
+        (JSC::GetByIdStatus::computeFor):
+        * bytecode/InByIdStatus.cpp:
+        (JSC::InByIdStatus::computeForStubInfoWithoutExitSiteFeedback):
+        * bytecode/PropertyCondition.cpp:
+        (JSC::PropertyCondition::isStillValidAssumingImpurePropertyWatchpoint const):
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::computeFor):
+        * runtime/JSFunction.cpp:
+        (JSC::getCalculatedDisplayName):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::putDirectCustomAccessor):
+        (JSC::JSObject::putDirectNonIndexAccessor):
+        (JSC::JSObject::putDirectIndexSlowOrBeyondVectorLength):
+        * runtime/JSObject.h:
+        (JSC::JSObject::putDirectIndex):
+        (JSC::JSObject::fillCustomGetterPropertySlot):
+        (JSC::JSObject::putDirect):
+        * runtime/JSObjectInlines.h:
+        (JSC::JSObject::putDirectInternal):
+        * runtime/PropertyDescriptor.cpp:
+        (JSC::PropertyDescriptor::setDescriptor):
+        (JSC::PropertyDescriptor::setCustomDescriptor):
+        (JSC::PropertyDescriptor::setAccessorDescriptor):
+        * runtime/PropertySlot.h:
+        (JSC::PropertySlot::setCustomGetterSetter):
+
+2018-12-10  Mark Lam  <mark.lam@apple.com>
+
         LinkBuffer::copyCompactAndLinkCode() needs to be aware of ENABLE(SEPARATED_WX_HEAP).
         https://bugs.webkit.org/show_bug.cgi?id=192569
         <rdar://problem/45615617>
index 97cc113..6769ba0 100644 (file)
@@ -96,7 +96,7 @@ GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned
     PropertyOffset offset = structure->getConcurrently(uid, attributes);
     if (!isValidOffset(offset))
         return GetByIdStatus(NoInformation, false);
-    if (attributes & PropertyAttribute::CustomAccessor)
+    if (attributes & PropertyAttribute::CustomAccessorOrValue)
         return GetByIdStatus(NoInformation, false);
 
     return GetByIdStatus(Simple, false, GetByIdVariant(StructureSet(structure), offset));
@@ -175,7 +175,7 @@ GetByIdStatus GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback(
         variant.m_offset = structure->getConcurrently(uid, attributes);
         if (!isValidOffset(variant.m_offset))
             return GetByIdStatus(JSC::slowVersion(summary));
-        if (attributes & PropertyAttribute::CustomAccessor)
+        if (attributes & PropertyAttribute::CustomAccessorOrValue)
             return GetByIdStatus(JSC::slowVersion(summary));
         
         variant.m_structureSet.add(structure);
@@ -374,7 +374,7 @@ GetByIdStatus GetByIdStatus::computeFor(const StructureSet& set, UniquedStringIm
             return GetByIdStatus(TakesSlowPath); // It's probably a prototype lookup. Give up on life for now, even though we could totally be way smarter about it.
         if (attributes & PropertyAttribute::Accessor)
             return GetByIdStatus(MakesCalls); // We could be smarter here, like strength-reducing this to a Call.
-        if (attributes & PropertyAttribute::CustomAccessor)
+        if (attributes & PropertyAttribute::CustomAccessorOrValue)
             return GetByIdStatus(TakesSlowPath);
         
         if (!result.appendVariant(GetByIdVariant(structure, offset)))
index 3460bed..98e8a9b 100644 (file)
@@ -141,7 +141,7 @@ InByIdStatus InByIdStatus::computeForStubInfoWithoutExitSiteFeedback(const Concu
         variant.m_offset = structure->getConcurrently(uid, attributes);
         if (!isValidOffset(variant.m_offset))
             return InByIdStatus(TakesSlowPath);
-        if (attributes & PropertyAttribute::CustomAccessor)
+        if (attributes & PropertyAttribute::CustomAccessorOrValue)
             return InByIdStatus(TakesSlowPath);
 
         variant.m_structureSet.add(structure);
index 3deb44c..8b1a4cc 100644 (file)
@@ -161,7 +161,7 @@ bool PropertyCondition::isStillValidAssumingImpurePropertyWatchpoint(
         unsigned currentAttributes;
         PropertyOffset currentOffset = structure->getConcurrently(uid(), currentAttributes);
         if (currentOffset != invalidOffset) {
-            if (currentAttributes & (PropertyAttribute::ReadOnly | PropertyAttribute::Accessor | PropertyAttribute::CustomAccessor)) {
+            if (currentAttributes & (PropertyAttribute::ReadOnly | PropertyAttribute::Accessor | PropertyAttribute::CustomAccessorOrValue)) {
                 if (PropertyConditionInternal::verbose) {
                     dataLog(
                         "Invalid because we expected not to have a setter, but we have one at offset ",
index ff7da8d..02f5231 100644 (file)
@@ -298,7 +298,7 @@ PutByIdStatus PutByIdStatus::computeFor(JSGlobalObject* globalObject, const Stru
         unsigned attributes;
         PropertyOffset offset = structure->getConcurrently(uid, attributes);
         if (isValidOffset(offset)) {
-            if (attributes & PropertyAttribute::CustomAccessor)
+            if (attributes & PropertyAttribute::CustomAccessorOrValue)
                 return PutByIdStatus(MakesCalls);
 
             if (attributes & (PropertyAttribute::Accessor | PropertyAttribute::ReadOnly))
index e809a57..50568e8 100644 (file)
@@ -635,7 +635,7 @@ String getCalculatedDisplayName(VM& vm, JSObject* object)
     unsigned attributes;
     // This function may be called when the mutator isn't running and we are lazily generating a stack trace.
     PropertyOffset offset = structure->getConcurrently(vm.propertyNames->displayName.impl(), attributes);
-    if (offset != invalidOffset && !(attributes & (PropertyAttribute::Accessor | PropertyAttribute::CustomAccessor))) {
+    if (offset != invalidOffset && !(attributes & (PropertyAttribute::Accessor | PropertyAttribute::CustomAccessorOrValue))) {
         JSValue displayName = object->getDirect(offset);
         if (displayName && displayName.isString())
             return asString(displayName)->tryGetValue();
index 48be232..b7fa795 100644 (file)
@@ -1860,9 +1860,15 @@ bool JSObject::putDirectAccessor(ExecState* exec, PropertyName propertyName, Get
     return putDirectNonIndexAccessor(exec->vm(), propertyName, accessor, attributes);
 }
 
+// FIXME: Introduce a JSObject::putDirectCustomValue() method instead of using
+// JSObject::putDirectCustomAccessor() to put CustomValues.
+// https://bugs.webkit.org/show_bug.cgi?id=192576
 bool JSObject::putDirectCustomAccessor(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes)
 {
     ASSERT(!parseIndex(propertyName));
+    ASSERT(value.isCustomGetterSetter());
+    if (!(attributes & PropertyAttribute::CustomAccessor))
+        attributes |= PropertyAttribute::CustomValue;
 
     PutPropertySlot slot(this);
     bool result = putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot);
@@ -1878,6 +1884,7 @@ bool JSObject::putDirectCustomAccessor(VM& vm, PropertyName propertyName, JSValu
 
 bool JSObject::putDirectNonIndexAccessor(VM& vm, PropertyName propertyName, GetterSetter* accessor, unsigned attributes)
 {
+    ASSERT(attributes & PropertyAttribute::Accessor);
     PutPropertySlot slot(this);
     bool result = putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, accessor, attributes, slot);
 
@@ -2982,7 +2989,8 @@ bool JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState* exec,
 bool JSObject::putDirectIndexSlowOrBeyondVectorLength(ExecState* exec, unsigned i, JSValue value, unsigned attributes, PutDirectIndexMode mode)
 {
     VM& vm = exec->vm();
-    
+    ASSERT(!value.isCustomGetterSetter());
+
     if (!canDoFastPutDirectIndex(vm, this)) {
         PropertyDescriptor descriptor;
         descriptor.setDescriptor(value, attributes);
index 12745e0..148b1b1 100644 (file)
@@ -217,6 +217,7 @@ public:
     // otherwise, it creates a property with the provided attributes. Semantically, this is performing defineOwnProperty.
     bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value, unsigned attributes, PutDirectIndexMode mode)
     {
+        ASSERT(!value.isCustomGetterSetter());
         auto canSetIndexQuicklyForPutDirect = [&] () -> bool {
             switch (indexingMode()) {
             case ALL_BLANK_INDEXING_TYPES:
@@ -1374,6 +1375,7 @@ ALWAYS_INLINE bool JSObject::getOwnNonIndexPropertySlot(VM& vm, Structure* struc
 
 ALWAYS_INLINE void JSObject::fillCustomGetterPropertySlot(VM& vm, PropertySlot& slot, CustomGetterSetter* customGetterSetter, unsigned attributes, Structure* structure)
 {
+    ASSERT(attributes & PropertyAttribute::CustomAccessorOrValue);
     if (customGetterSetter->inherits<DOMAttributeGetterSetter>(vm)) {
         auto* domAttribute = jsCast<DOMAttributeGetterSetter*>(customGetterSetter);
         if (structure->isUncacheableDictionary())
@@ -1497,7 +1499,7 @@ inline bool JSObject::putOwnDataPropertyMayBeIndex(ExecState* exec, PropertyName
 inline bool JSObject::putDirect(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes)
 {
     ASSERT(!value.isGetterSetter() && !(attributes & PropertyAttribute::Accessor));
-    ASSERT(!value.isCustomGetterSetter());
+    ASSERT(!value.isCustomGetterSetter() && !(attributes & PropertyAttribute::CustomAccessorOrValue));
     PutPropertySlot slot(this);
     return putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot);
 }
index 1948479..7222283 100644 (file)
@@ -273,6 +273,7 @@ ALWAYS_INLINE bool JSObject::putDirectInternal(VM& vm, PropertyName propertyName
 {
     ASSERT(value);
     ASSERT(value.isGetterSetter() == !!(attributes & PropertyAttribute::Accessor));
+    ASSERT(value.isCustomGetterSetter() == !!(attributes & PropertyAttribute::CustomAccessorOrValue));
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
     ASSERT(!parseIndex(propertyName));
 
@@ -291,7 +292,7 @@ ALWAYS_INLINE bool JSObject::putDirectInternal(VM& vm, PropertyName propertyName
             putDirect(vm, offset, value);
             structure->didReplaceProperty(offset);
 
-            if ((attributes & PropertyAttribute::Accessor) != (currentAttributes & PropertyAttribute::Accessor) || (attributes & PropertyAttribute::CustomAccessor) != (currentAttributes & PropertyAttribute::CustomAccessor)) {
+            if ((attributes & PropertyAttribute::Accessor) != (currentAttributes & PropertyAttribute::Accessor) || (attributes & PropertyAttribute::CustomAccessorOrValue) != (currentAttributes & PropertyAttribute::CustomAccessorOrValue)) {
                 ASSERT(!(attributes & PropertyAttribute::ReadOnly));
                 setStructure(vm, Structure::attributeChangeTransition(vm, structure, propertyName, attributes));
             } else
@@ -354,7 +355,7 @@ ALWAYS_INLINE bool JSObject::putDirectInternal(VM& vm, PropertyName propertyName
 
         putDirect(vm, offset, value);
 
-        if ((attributes & PropertyAttribute::Accessor) != (currentAttributes & PropertyAttribute::Accessor) || (attributes & PropertyAttribute::CustomAccessor) != (currentAttributes & PropertyAttribute::CustomAccessor)) {
+        if ((attributes & PropertyAttribute::Accessor) != (currentAttributes & PropertyAttribute::Accessor) || (attributes & PropertyAttribute::CustomAccessorOrValue) != (currentAttributes & PropertyAttribute::CustomAccessorOrValue)) {
             ASSERT(!(attributes & PropertyAttribute::ReadOnly));
             setStructure(vm, Structure::attributeChangeTransition(vm, structure, propertyName, attributes));
         } else
index 67aeedb..1b4f5e6 100644 (file)
@@ -109,7 +109,13 @@ void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes)
 {
     ASSERT(value);
 
-    m_attributes = attributes;
+    // We need to mask off the PropertyAttribute::CustomValue bit because
+    // PropertyDescriptor::attributesEqual() does an equivalent test on
+    // m_attributes, and a property that has a CustomValue should be indistinguishable
+    // from a property that has a normal value as far as JS code is concerned.
+    // PropertyAttribute does not need knowledge of the underlying implementation
+    // actually being a CustomValue. So, we'll just mask it off up front here.
+    m_attributes = attributes & ~PropertyAttribute::CustomValue;
     if (value.isGetterSetter()) {
         m_attributes &= ~PropertyAttribute::ReadOnly; // FIXME: we should be able to ASSERT this!
 
@@ -125,6 +131,7 @@ void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes)
 
 void PropertyDescriptor::setCustomDescriptor(unsigned attributes)
 {
+    ASSERT(!(attributes & PropertyAttribute::CustomValue));
     m_attributes = attributes | PropertyAttribute::Accessor | PropertyAttribute::CustomAccessor;
     m_attributes &= ~PropertyAttribute::ReadOnly;
     m_seenAttributes = EnumerablePresent | ConfigurablePresent;
@@ -136,6 +143,7 @@ void PropertyDescriptor::setCustomDescriptor(unsigned attributes)
 void PropertyDescriptor::setAccessorDescriptor(GetterSetter* accessor, unsigned attributes)
 {
     ASSERT(attributes & PropertyAttribute::Accessor);
+    ASSERT(!(attributes & PropertyAttribute::CustomValue));
     attributes &= ~PropertyAttribute::ReadOnly; // FIXME: we should be able to ASSERT this!
 
     m_attributes = attributes;
index 142a124..e0e6904 100644 (file)
@@ -43,6 +43,8 @@ enum class PropertyAttribute : unsigned {
     DontDelete        = 1 << 3,  // property can't be deleted
     Accessor          = 1 << 4,  // property is a getter/setter
     CustomAccessor    = 1 << 5,
+    CustomValue       = 1 << 6,
+    CustomAccessorOrValue = CustomAccessor | CustomValue,
 
     // Things that are used by static hashtables are not in the attributes byte in PropertyMapEntry.
     Function          = 1 << 8,  // property is a function - only used by static hashtables
@@ -299,6 +301,7 @@ public:
     void setCustomGetterSetter(JSObject* slotBase, unsigned attributes, CustomGetterSetter* getterSetter)
     {
         ASSERT(attributes == attributesForStructure(attributes));
+        ASSERT(attributes & PropertyAttribute::CustomAccessor);
 
         disableCaching();
 
index 477c69d..7d19692 100644 (file)
@@ -1,3 +1,23 @@
+2018-12-10  Mark Lam  <mark.lam@apple.com>
+
+        PropertyAttribute needs a CustomValue bit.
+        https://bugs.webkit.org/show_bug.cgi?id=191993
+        <rdar://problem/46264467>
+
+        Reviewed by Saam Barati.
+
+        This patch revealed a bug in the CodeGenerator where a constructor property is
+        set with a ReadOnly attribute.  This conflicts with the WebIDL link (see clause
+        12 in https://heycam.github.io/webidl/#interface-prototype-object) which states
+        that it should be [Writable].  The ReadOnly attribute is now removed.
+
+        On the WebCore side, this change is covered by existing tests.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateImplementation):
+        * bindings/scripts/test/JS/JSTestCustomConstructorWithNoInterfaceObject.cpp:
+        (WebCore::jsTestCustomConstructorWithNoInterfaceObjectConstructor):
+
 2018-12-10  Antti Koivisto  <antti@apple.com>
 
         Rename "forced style recalc" to "full style rebuild"
index 65e4536..4917c14 100644 (file)
@@ -4472,7 +4472,7 @@ sub GenerateImplementation
         } else {
             push(@implContent, "    JSValue constructor = ${className}Constructor::create(state->vm(), ${className}Constructor::createStructure(state->vm(), *prototype->globalObject(), prototype->globalObject()->objectPrototype()), *jsCast<JSDOMGlobalObject*>(prototype->globalObject()));\n");
             push(@implContent, "    // Shadowing constructor property to ensure reusing the same constructor object\n");
-            push(@implContent, "    prototype->putDirect(vm, vm.propertyNames->constructor, constructor, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly);\n");
+            push(@implContent, "    prototype->putDirect(vm, vm.propertyNames->constructor, constructor, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum));\n");
             push(@implContent, "    return JSValue::encode(constructor);\n");
         }
         push(@implContent, "}\n\n");
index a9454e9..5fe76c8 100644 (file)
@@ -144,7 +144,7 @@ EncodedJSValue jsTestCustomConstructorWithNoInterfaceObjectConstructor(ExecState
         return throwVMTypeError(state, throwScope);
     JSValue constructor = JSTestCustomConstructorWithNoInterfaceObjectConstructor::create(state->vm(), JSTestCustomConstructorWithNoInterfaceObjectConstructor::createStructure(state->vm(), *prototype->globalObject(), prototype->globalObject()->objectPrototype()), *jsCast<JSDOMGlobalObject*>(prototype->globalObject()));
     // Shadowing constructor property to ensure reusing the same constructor object
-    prototype->putDirect(vm, vm.propertyNames->constructor, constructor, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly);
+    prototype->putDirect(vm, vm.propertyNames->constructor, constructor, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum));
     return JSValue::encode(constructor);
 }