Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (197411 => 197412)
--- trunk/Source/_javascript_Core/ChangeLog 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-03-01 21:45:16 UTC (rev 197412)
@@ -1,3 +1,61 @@
+2016-03-01 Saam barati <[email protected]>
+
+ [[IsExtensible]] should be a virtual method in the method table
+ https://bugs.webkit.org/show_bug.cgi?id=154799
+
+ Reviewed by Mark Lam.
+
+ This patch makes us more consistent with how the ES6 specification models the
+ [[IsExtensible]] trap. Moving this method into ClassInfo::methodTable
+ is a prerequisite for implementing Proxy.[[IsExtensible]].
+
+ * runtime/ClassInfo.h:
+ * runtime/JSCell.cpp:
+ (JSC::JSCell::preventExtensions):
+ (JSC::JSCell::isExtensible):
+ * runtime/JSCell.h:
+ * runtime/JSGlobalObjectFunctions.cpp:
+ (JSC::globalFuncProtoSetter):
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::preventExtensions):
+ (JSC::JSObject::isExtensible):
+ (JSC::JSObject::reifyAllStaticProperties):
+ (JSC::JSObject::defineOwnIndexedProperty):
+ (JSC::JSObject::putByIndexBeyondVectorLengthWithArrayStorage):
+ (JSC::JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage):
+ (JSC::JSObject::defineOwnNonIndexProperty):
+ (JSC::JSObject::defineOwnProperty):
+ * runtime/JSObject.h:
+ (JSC::JSObject::isSealed):
+ (JSC::JSObject::isFrozen):
+ (JSC::JSObject::isExtensibleImpl):
+ (JSC::JSObject::isStructureExtensible):
+ (JSC::JSObject::isExtensibleInline):
+ (JSC::JSObject::indexingShouldBeSparse):
+ (JSC::JSObject::putDirectInternal):
+ (JSC::JSObject::isExtensible): Deleted.
+ * runtime/ObjectConstructor.cpp:
+ (JSC::objectConstructorSetPrototypeOf):
+ (JSC::objectConstructorIsSealed):
+ (JSC::objectConstructorIsFrozen):
+ (JSC::objectConstructorIsExtensible):
+ (JSC::objectConstructorIs):
+ * runtime/ProxyObject.cpp:
+ (JSC::ProxyObject::performInternalMethodGetOwnProperty):
+ (JSC::ProxyObject::performHasProperty):
+ * runtime/ReflectObject.cpp:
+ (JSC::reflectObjectIsExtensible):
+ (JSC::reflectObjectSetPrototypeOf):
+ * runtime/SparseArrayValueMap.cpp:
+ (JSC::SparseArrayValueMap::putEntry):
+ (JSC::SparseArrayValueMap::putDirect):
+ * runtime/StringObject.cpp:
+ (JSC::StringObject::defineOwnProperty):
+ * runtime/Structure.cpp:
+ (JSC::Structure::isSealed):
+ (JSC::Structure::isFrozen):
+ * runtime/Structure.h:
+
2016-03-01 Filip Pizlo <[email protected]>
Unreviewed, fix CLOOP build.
Modified: trunk/Source/_javascript_Core/runtime/ClassInfo.h (197411 => 197412)
--- trunk/Source/_javascript_Core/runtime/ClassInfo.h 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/runtime/ClassInfo.h 2016-03-01 21:45:16 UTC (rev 197412)
@@ -106,6 +106,9 @@
typedef bool (*PreventExtensionsFunctionPtr)(JSObject*, ExecState*);
PreventExtensionsFunctionPtr preventExtensions;
+ typedef bool (*IsExtensibleFunctionPtr)(JSObject*, ExecState*);
+ IsExtensibleFunctionPtr isExtensible;
+
typedef void (*DumpToStreamFunctionPtr)(const JSCell*, PrintStream&);
DumpToStreamFunctionPtr dumpToStream;
@@ -158,6 +161,7 @@
&ClassName::slowDownAndWasteMemory, \
&ClassName::getTypedArrayImpl, \
&ClassName::preventExtensions, \
+ &ClassName::isExtensible, \
&ClassName::dumpToStream, \
&ClassName::estimatedSize \
}, \
Modified: trunk/Source/_javascript_Core/runtime/JSCell.cpp (197411 => 197412)
--- trunk/Source/_javascript_Core/runtime/JSCell.cpp 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/runtime/JSCell.cpp 2016-03-01 21:45:16 UTC (rev 197412)
@@ -275,4 +275,9 @@
RELEASE_ASSERT_NOT_REACHED();
}
+bool JSCell::isExtensible(JSObject*, ExecState*)
+{
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSCell.h (197411 => 197412)
--- trunk/Source/_javascript_Core/runtime/JSCell.h 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/runtime/JSCell.h 2016-03-01 21:45:16 UTC (rev 197412)
@@ -207,6 +207,7 @@
static NO_RETURN_DUE_TO_CRASH void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
static NO_RETURN_DUE_TO_CRASH void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
static NO_RETURN_DUE_TO_CRASH bool preventExtensions(JSObject*, ExecState*);
+ static NO_RETURN_DUE_TO_CRASH bool isExtensible(JSObject*, ExecState*);
static String className(const JSObject*);
JS_EXPORT_PRIVATE static bool customHasInstance(JSObject*, ExecState*, JSValue);
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (197411 => 197412)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp 2016-03-01 21:45:16 UTC (rev 197412)
@@ -885,7 +885,10 @@
if (thisObject->prototype() == value)
return JSValue::encode(jsUndefined());
- if (!thisObject->isExtensible())
+ bool isExtensible = thisObject->isExtensibleInline(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ if (!isExtensible)
return throwVMError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
if (!thisObject->setPrototypeWithCycleCheck(exec, value))
Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (197411 => 197412)
--- trunk/Source/_javascript_Core/runtime/JSObject.cpp 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp 2016-03-01 21:45:16 UTC (rev 197412)
@@ -1677,8 +1677,12 @@
bool JSObject::preventExtensions(JSObject* object, ExecState* exec)
{
- if (!object->isExtensible())
+ if (!object->isStructureExtensible()) {
+ // We've already set the internal [[PreventExtensions]] field to false.
+ // We don't call the methodTable isExtensible here because it's not defined
+ // that way in the specification. We are just doing an optimization here.
return true;
+ }
VM& vm = exec->vm();
object->enterDictionaryIndexingMode(vm);
@@ -1686,6 +1690,11 @@
return true;
}
+bool JSObject::isExtensible(JSObject* obj, ExecState*)
+{
+ return obj->isExtensibleImpl();
+}
+
void JSObject::reifyAllStaticProperties(ExecState* exec)
{
ASSERT(!staticFunctionsReified());
@@ -1821,7 +1830,7 @@
// 3. If current is undefined and extensible is false, then Reject.
// 4. If current is undefined and extensible is true, then
if (result.isNewEntry) {
- if (!isExtensible()) {
+ if (!isStructureExtensible()) {
map->remove(result.iterator);
return reject(exec, throwException, "Attempting to define property on object that is not extensible.");
}
@@ -2037,7 +2046,7 @@
// First, handle cases where we don't currently have a sparse map.
if (LIKELY(!map)) {
// If the array is not extensible, we should have entered dictionary mode, and created the sparse map.
- ASSERT(isExtensible());
+ ASSERT(isStructureExtensible());
// Update m_length if necessary.
if (i >= storage->length())
@@ -2063,7 +2072,7 @@
unsigned length = storage->length();
if (i >= length) {
// Prohibit growing the array if length is not writable.
- if (map->lengthIsReadOnly() || !isExtensible()) {
+ if (map->lengthIsReadOnly() || !isStructureExtensible()) {
if (shouldThrow)
throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
return;
@@ -2183,7 +2192,7 @@
// First, handle cases where we don't currently have a sparse map.
if (LIKELY(!map)) {
// If the array is not extensible, we should have entered dictionary mode, and created the spare map.
- ASSERT(isExtensible());
+ ASSERT(isStructureExtensible());
// Update m_length if necessary.
if (i >= storage->length())
@@ -2213,7 +2222,7 @@
// Prohibit growing the array if length is not writable.
if (map->lengthIsReadOnly())
return reject(exec, mode == PutDirectIndexShouldThrow, StrictModeReadonlyPropertyWriteError);
- if (!isExtensible())
+ if (!isStructureExtensible())
return reject(exec, mode == PutDirectIndexShouldThrow, "Attempting to define property on object that is not extensible.");
}
length = i + 1;
@@ -2848,7 +2857,10 @@
DefineOwnPropertyScope scope(exec);
PropertyDescriptor current;
bool isCurrentDefined = getOwnPropertyDescriptor(exec, propertyName, current);
- return validateAndApplyPropertyDescriptor(exec, this, propertyName, isExtensible(), descriptor, isCurrentDefined, current, throwException);
+ bool isExtensible = isExtensibleInline(exec);
+ if (UNLIKELY(exec->hadException()))
+ return false;
+ return validateAndApplyPropertyDescriptor(exec, this, propertyName, isExtensible, descriptor, isCurrentDefined, current, throwException);
}
bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException)
Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (197411 => 197412)
--- trunk/Source/_javascript_Core/runtime/JSObject.h 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h 2016-03-01 21:45:16 UTC (rev 197412)
@@ -615,12 +615,33 @@
JS_EXPORT_PRIVATE void seal(VM&);
JS_EXPORT_PRIVATE void freeze(VM&);
JS_EXPORT_PRIVATE static bool preventExtensions(JSObject*, ExecState*);
+ JS_EXPORT_PRIVATE static bool isExtensible(JSObject*, ExecState*);
bool isSealed(VM& vm) { return structure(vm)->isSealed(vm); }
bool isFrozen(VM& vm) { return structure(vm)->isFrozen(vm); }
- bool isExtensible() { return structure()->isExtensible(); }
+private:
+ ALWAYS_INLINE bool isExtensibleImpl() { return isStructureExtensible(); }
+public:
+ // You should only call isStructureExtensible() when:
+ // - Performing this check in a way that isn't described in the specification
+ // as calling the virtual [[IsExtensible]] trap.
+ // - When you're guaranteed that object->methodTable()->isExtensible isn't
+ // overridden.
+ ALWAYS_INLINE bool isStructureExtensible() { return structure()->isStructureExtensible(); }
+ // You should call this when performing [[IsExtensible]] trap in a place
+ // that is described in the specification. This performs the fully virtual
+ // [[IsExtensible]] trap.
+ ALWAYS_INLINE bool isExtensibleInline(ExecState* exec)
+ {
+ VM& vm = exec->vm();
+ auto isExtensibleMethod = methodTable(vm)->isExtensible;
+ if (LIKELY(isExtensibleMethod == JSObject::isExtensible))
+ return isExtensibleImpl();
+
+ return isExtensibleMethod(this, exec);
+ }
bool indexingShouldBeSparse()
{
- return !isExtensible()
+ return !isStructureExtensible()
|| structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero();
}
@@ -1272,7 +1293,7 @@
return true;
}
- if ((mode == PutModePut) && !isExtensible())
+ if ((mode == PutModePut) && !isStructureExtensible())
return false;
DeferGC deferGC(vm.heap);
@@ -1337,7 +1358,7 @@
return true;
}
- if ((mode == PutModePut) && !isExtensible())
+ if ((mode == PutModePut) && !isStructureExtensible())
return false;
// We want the structure transition watchpoint to fire after this object has switched
Modified: trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp (197411 => 197412)
--- trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2016-03-01 21:45:16 UTC (rev 197412)
@@ -212,7 +212,10 @@
if (object->prototype() == protoValue)
return JSValue::encode(objectValue);
- if (!object->isExtensible())
+ bool isExtensible = object->isExtensibleInline(exec);
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
+ if (!isExtensible)
return throwVMError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
if (!object->setPrototypeWithCycleCheck(exec, protoValue)) {
@@ -616,7 +619,10 @@
// 3. If the [[Extensible]] internal property of O is false, then return true.
// 4. Otherwise, return false.
- return JSValue::encode(jsBoolean(!object->isExtensible()));
+ bool isExtensible = object->isExtensibleInline(exec);
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
+ return JSValue::encode(jsBoolean(!isExtensible));
}
EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState* exec)
@@ -650,7 +656,10 @@
// 3. If the [[Extensible]] internal property of O is false, then return true.
// 4. Otherwise, return false.
- return JSValue::encode(jsBoolean(!object->isExtensible()));
+ bool isExtensible = object->isExtensibleInline(exec);
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
+ return JSValue::encode(jsBoolean(!isExtensible));
}
EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState* exec)
@@ -658,7 +667,11 @@
JSValue obj = exec->argument(0);
if (!obj.isObject())
return JSValue::encode(jsBoolean(false));
- return JSValue::encode(jsBoolean(asObject(obj)->isExtensible()));
+ JSObject* object = asObject(obj);
+ bool isExtensible = object->isExtensibleInline(exec);
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
+ return JSValue::encode(jsBoolean(isExtensible));
}
EncodedJSValue JSC_HOST_CALL objectConstructorIs(ExecState* exec)
Modified: trunk/Source/_javascript_Core/runtime/ProxyObject.cpp (197411 => 197412)
--- trunk/Source/_javascript_Core/runtime/ProxyObject.cpp 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/runtime/ProxyObject.cpp 2016-03-01 21:45:16 UTC (rev 197412)
@@ -196,7 +196,10 @@
}
// FIXME: this doesn't work if 'target' is another Proxy. We don't have isExtensible implemented in a way that fits w/ Proxys.
// https://bugs.webkit.org/show_bug.cgi?id=154375
- if (!target->isExtensible()) {
+ bool isExtensible = target->isExtensibleInline(exec);
+ if (exec->hadException())
+ return false;
+ if (!isExtensible) {
// FIXME: Come up with a test for this error. I'm not sure how to because
// Object.seal(o) will make all fields [[Configurable]] false.
// https://bugs.webkit.org/show_bug.cgi?id=154376
@@ -207,12 +210,15 @@
return false;
}
+ bool isExtensible = target->isExtensibleInline(exec);
+ if (exec->hadException())
+ return false;
PropertyDescriptor trapResultAsDescriptor;
toPropertyDescriptor(exec, trapResult, trapResultAsDescriptor);
if (exec->hadException())
return false;
bool throwException = false;
- bool valid = validateAndApplyPropertyDescriptor(exec, nullptr, propertyName, target->isExtensible(),
+ bool valid = validateAndApplyPropertyDescriptor(exec, nullptr, propertyName, isExtensible,
trapResultAsDescriptor, isTargetPropertyDescriptorDefined, targetPropertyDescriptor, throwException);
if (!valid) {
throwVMTypeError(exec, ASCIILiteral("Result from 'getOwnPropertyDescriptor' fails the IsCompatiblePropertyDescriptor test."));
@@ -288,7 +294,10 @@
throwVMTypeError(exec, ASCIILiteral("Proxy 'has' must return 'true' for non-configurable properties."));
return false;
}
- if (!target->isExtensible()) {
+ bool isExtensible = target->isExtensibleInline(exec);
+ if (exec->hadException())
+ return false;
+ if (!isExtensible) {
throwVMTypeError(exec, ASCIILiteral("Proxy 'has' must return 'true' for a non-extensible 'target' object with a configurable property."));
return false;
}
Modified: trunk/Source/_javascript_Core/runtime/ReflectObject.cpp (197411 => 197412)
--- trunk/Source/_javascript_Core/runtime/ReflectObject.cpp 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/runtime/ReflectObject.cpp 2016-03-01 21:45:16 UTC (rev 197412)
@@ -168,7 +168,11 @@
JSValue target = exec->argument(0);
if (!target.isObject())
return JSValue::encode(throwTypeError(exec, ASCIILiteral("Reflect.isExtensible requires the first argument be an object")));
- return JSValue::encode(jsBoolean(asObject(target)->isExtensible()));
+
+ bool isExtensible = asObject(target)->isExtensibleInline(exec);
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
+ return JSValue::encode(jsBoolean(isExtensible));
}
// http://www.ecma-international.org/ecma-262/6.0/#sec-reflect.ownkeys
@@ -211,7 +215,10 @@
if (object->prototype() == proto)
return JSValue::encode(jsBoolean(true));
- if (!object->isExtensible())
+ bool isExtensible = object->isExtensibleInline(exec);
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
+ if (!isExtensible)
return JSValue::encode(jsBoolean(false));
return JSValue::encode(jsBoolean(object->setPrototypeWithCycleCheck(exec, proto)));
Modified: trunk/Source/_javascript_Core/runtime/SparseArrayValueMap.cpp (197411 => 197412)
--- trunk/Source/_javascript_Core/runtime/SparseArrayValueMap.cpp 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/runtime/SparseArrayValueMap.cpp 2016-03-01 21:45:16 UTC (rev 197412)
@@ -98,7 +98,7 @@
// To save a separate find & add, we first always add to the sparse map.
// In the uncommon case that this is a new property, and the array is not
// extensible, this is not the right thing to have done - so remove again.
- if (result.isNewEntry && !array->isExtensible()) {
+ if (result.isNewEntry && !array->isStructureExtensible()) {
remove(result.iterator);
if (shouldThrow)
throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
@@ -118,7 +118,7 @@
// To save a separate find & add, we first always add to the sparse map.
// In the uncommon case that this is a new property, and the array is not
// extensible, this is not the right thing to have done - so remove again.
- if (mode != PutDirectIndexLikePutDirect && result.isNewEntry && !array->isExtensible()) {
+ if (mode != PutDirectIndexLikePutDirect && result.isNewEntry && !array->isStructureExtensible()) {
remove(result.iterator);
return reject(exec, mode == PutDirectIndexShouldThrow, "Attempting to define property on object that is not extensible.");
}
Modified: trunk/Source/_javascript_Core/runtime/StringObject.cpp (197411 => 197412)
--- trunk/Source/_javascript_Core/runtime/StringObject.cpp 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/runtime/StringObject.cpp 2016-03-01 21:45:16 UTC (rev 197412)
@@ -86,7 +86,10 @@
StringObject* thisObject = jsCast<StringObject*>(object);
if (propertyName == exec->propertyNames().length) {
- if (!object->isExtensible()) {
+ bool isExtensible = object->isExtensibleInline(exec);
+ if (exec->hadException())
+ return false;
+ if (!isExtensible) {
if (throwException)
exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to define property on object that is not extensible.")));
return false;
Modified: trunk/Source/_javascript_Core/runtime/Structure.cpp (197411 => 197412)
--- trunk/Source/_javascript_Core/runtime/Structure.cpp 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/runtime/Structure.cpp 2016-03-01 21:45:16 UTC (rev 197412)
@@ -691,7 +691,7 @@
// In future we may want to cache this property.
bool Structure::isSealed(VM& vm)
{
- if (isExtensible())
+ if (isStructureExtensible())
return false;
DeferGC deferGC(vm.heap);
@@ -710,7 +710,7 @@
// In future we may want to cache this property.
bool Structure::isFrozen(VM& vm)
{
- if (isExtensible())
+ if (isStructureExtensible())
return false;
DeferGC deferGC(vm.heap);
Modified: trunk/Source/_javascript_Core/runtime/Structure.h (197411 => 197412)
--- trunk/Source/_javascript_Core/runtime/Structure.h 2016-03-01 21:40:38 UTC (rev 197411)
+++ trunk/Source/_javascript_Core/runtime/Structure.h 2016-03-01 21:45:16 UTC (rev 197412)
@@ -183,7 +183,7 @@
JS_EXPORT_PRIVATE bool isSealed(VM&);
JS_EXPORT_PRIVATE bool isFrozen(VM&);
- bool isExtensible() const { return !didPreventExtensions(); }
+ bool isStructureExtensible() const { return !didPreventExtensions(); }
bool putWillGrowOutOfLineStorage();
size_t suggestedNewOutOfLineStorageCapacity();