Diff
Modified: branches/safari-609-branch/JSTests/ChangeLog (258160 => 258161)
--- branches/safari-609-branch/JSTests/ChangeLog 2020-03-09 20:23:45 UTC (rev 258160)
+++ branches/safari-609-branch/JSTests/ChangeLog 2020-03-09 21:14:46 UTC (rev 258161)
@@ -1,5 +1,22 @@
2020-03-09 Alan Coon <[email protected]>
+ Apply patch. rdar://problem/60183769
+
+ 2020-03-09 Yusuke Suzuki <[email protected]>
+
+ [JSC] @hasOwnLengthProperty returns wrong value if "length" is attempted to be modified
+ https://bugs.webkit.org/show_bug.cgi?id=208497
+ <rdar://problem/59913544>
+
+ Reviewed by Mark Lam.
+
+ * stress/function-length-update.js: Added.
+ (shouldBe):
+ (userFunction):
+ (userFunction2):
+
+2020-03-09 Alan Coon <[email protected]>
+
Cherry-pick r257605. rdar://problem/59870340
Poly proto should work with property delete transitions
Added: branches/safari-609-branch/JSTests/stress/function-length-update.js (0 => 258161)
--- branches/safari-609-branch/JSTests/stress/function-length-update.js (rev 0)
+++ branches/safari-609-branch/JSTests/stress/function-length-update.js 2020-03-09 21:14:46 UTC (rev 258161)
@@ -0,0 +1,55 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+function userFunction(a, b, c) { }
+
+shouldBe(userFunction.length, 3);
+shouldBe(userFunction.bind().length, 3);
+userFunction.length = 4;
+shouldBe(userFunction.length, 3); // Because it is ReadOnly
+shouldBe(userFunction.bind().length, 3);
+delete userFunction.length;
+shouldBe(userFunction.length, 0);
+Object.defineProperty(userFunction, "length", {
+ writable: true,
+ configurable: true,
+ value: 4
+});
+shouldBe(userFunction.length, 4);
+shouldBe(userFunction.bind().length, 4);
+
+var hostFunction = String.prototype.replace;
+shouldBe(hostFunction.length, 2);
+shouldBe(hostFunction.bind().length, 2);
+hostFunction.length = 4;
+shouldBe(hostFunction.length, 2); // Because it is ReadOnly
+shouldBe(hostFunction.bind().length, 2);
+delete hostFunction.length;
+shouldBe(hostFunction.length, 0);
+Object.defineProperty(hostFunction, "length", {
+ writable: true,
+ configurable: true,
+ value: 4
+});
+shouldBe(hostFunction.length, 4);
+shouldBe(hostFunction.bind().length, 4);
+
+function userFunction2(a, b, c) { }
+
+var boundFunction = userFunction2.bind();
+shouldBe(boundFunction.length, 3);
+shouldBe(boundFunction.bind().length, 3);
+boundFunction.length = 4;
+shouldBe(boundFunction.length, 3); // Because it is ReadOnly
+shouldBe(boundFunction.bind().length, 3);
+delete boundFunction.length;
+shouldBe(boundFunction.length, 0);
+Object.defineProperty(boundFunction, "length", {
+ writable: true,
+ configurable: true,
+ value: 4
+});
+shouldBe(boundFunction.length, 4);
+shouldBe(boundFunction.bind().length, 4);
Modified: branches/safari-609-branch/Source/_javascript_Core/ChangeLog (258160 => 258161)
--- branches/safari-609-branch/Source/_javascript_Core/ChangeLog 2020-03-09 20:23:45 UTC (rev 258160)
+++ branches/safari-609-branch/Source/_javascript_Core/ChangeLog 2020-03-09 21:14:46 UTC (rev 258161)
@@ -1,5 +1,48 @@
2020-03-09 Alan Coon <[email protected]>
+ Apply patch. rdar://problem/60183769
+
+ 2020-03-09 Yusuke Suzuki <[email protected]>
+
+ [JSC] @hasOwnLengthProperty returns wrong value if "length" is attempted to be modified
+ https://bugs.webkit.org/show_bug.cgi?id=208497
+ <rdar://problem/59913544>
+
+ Reviewed by Mark Lam.
+
+ When "length" of JSFunction is attempted to be modified, we put a flag. And @hasOwnLengthProperty
+ does not correctly use this flag to return a value for the fast path. This affects on "length"
+ property of bound functions. For example,
+
+ function userFunction(a) { }
+ userFunction.length = 20; // This field is read-only. So, it is not changed.
+ userFunction.bind().length; // Should be 1, but it returns 0.
+
+ 1. We rename m_hasModifiedLength to m_hasModifiedLengthForNonHostFunction and m_hasModifiedName
+ to m_hasModifiedNameForNonHostFunction since we are not tracking these states for host-functions
+ which can eagerly initialize them.
+ 2. We rename areNameAndLengthOriginal to canAssumeNameAndLengthAreOriginal to allow it to return
+ "false" for host functions. If it returns true, we go to the fast path.
+ 3. Correctly use canAssumeNameAndLengthAreOriginal information in @hasOwnLengthProperty.
+
+ * runtime/FunctionRareData.cpp:
+ (JSC::FunctionRareData::FunctionRareData):
+ * runtime/FunctionRareData.h:
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::put):
+ (JSC::JSFunction::deleteProperty):
+ (JSC::JSFunction::defineOwnProperty):
+ * runtime/JSFunction.h:
+ * runtime/JSFunctionInlines.h:
+ (JSC::JSFunction::canAssumeNameAndLengthAreOriginal):
+ (JSC::JSFunction::areNameAndLengthOriginal): Deleted.
+ * runtime/JSGlobalObject.cpp:
+ (JSC::hasOwnLengthProperty):
+ * tools/JSDollarVM.cpp:
+ (JSC::functionHasOwnLengthProperty):
+
+2020-03-09 Alan Coon <[email protected]>
+
Cherry-pick r257605. rdar://problem/59870340
Poly proto should work with property delete transitions
Modified: branches/safari-609-branch/Source/_javascript_Core/runtime/FunctionRareData.cpp (258160 => 258161)
--- branches/safari-609-branch/Source/_javascript_Core/runtime/FunctionRareData.cpp 2020-03-09 20:23:45 UTC (rev 258160)
+++ branches/safari-609-branch/Source/_javascript_Core/runtime/FunctionRareData.cpp 2020-03-09 21:14:46 UTC (rev 258161)
@@ -73,8 +73,8 @@
, m_executable(vm, this, executable)
, m_hasReifiedLength(false)
, m_hasReifiedName(false)
- , m_hasModifiedLength(false)
- , m_hasModifiedName(false)
+ , m_hasModifiedLengthForNonHostFunction(false)
+ , m_hasModifiedNameForNonHostFunction(false)
{
}
Modified: branches/safari-609-branch/Source/_javascript_Core/runtime/FunctionRareData.h (258160 => 258161)
--- branches/safari-609-branch/Source/_javascript_Core/runtime/FunctionRareData.h 2020-03-09 20:23:45 UTC (rev 258160)
+++ branches/safari-609-branch/Source/_javascript_Core/runtime/FunctionRareData.h 2020-03-09 21:14:46 UTC (rev 258161)
@@ -123,15 +123,15 @@
bool hasReifiedName() const { return m_hasReifiedName; }
void setHasReifiedName() { m_hasReifiedName = true; }
- bool hasModifiedLength() const { return m_hasModifiedLength; }
- void setHasModifiedLength()
+ bool hasModifiedLengthForNonHostFunction() const { return m_hasModifiedLengthForNonHostFunction; }
+ void setHasModifiedLengthForNonHostFunction()
{
- m_hasModifiedLength = true;
+ m_hasModifiedLengthForNonHostFunction = true;
}
- bool hasModifiedName() const { return m_hasModifiedName; }
- void setHasModifiedName()
+ bool hasModifiedNameForNonHostFunction() const { return m_hasModifiedNameForNonHostFunction; }
+ void setHasModifiedNameForNonHostFunction()
{
- m_hasModifiedName = true;
+ m_hasModifiedNameForNonHostFunction = true;
}
bool hasAllocationProfileClearingWatchpoint() const { return !!m_allocationProfileClearingWatchpoint; }
@@ -166,8 +166,8 @@
std::unique_ptr<AllocationProfileClearingWatchpoint> m_allocationProfileClearingWatchpoint;
bool m_hasReifiedLength : 1;
bool m_hasReifiedName : 1;
- bool m_hasModifiedLength : 1;
- bool m_hasModifiedName : 1;
+ bool m_hasModifiedLengthForNonHostFunction : 1;
+ bool m_hasModifiedNameForNonHostFunction : 1;
};
class FunctionRareData::AllocationProfileClearingWatchpoint final : public Watchpoint {
Modified: branches/safari-609-branch/Source/_javascript_Core/runtime/JSFunction.cpp (258160 => 258161)
--- branches/safari-609-branch/Source/_javascript_Core/runtime/JSFunction.cpp 2020-03-09 20:23:45 UTC (rev 258160)
+++ branches/safari-609-branch/Source/_javascript_Core/runtime/JSFunction.cpp 2020-03-09 21:14:46 UTC (rev 258161)
@@ -543,9 +543,9 @@
if (propertyName == vm.propertyNames->length || propertyName == vm.propertyNames->name) {
FunctionRareData* rareData = thisObject->ensureRareData(vm);
if (propertyName == vm.propertyNames->length)
- rareData->setHasModifiedLength();
+ rareData->setHasModifiedLengthForNonHostFunction();
else
- rareData->setHasModifiedName();
+ rareData->setHasModifiedNameForNonHostFunction();
}
if (UNLIKELY(isThisValueAltered(slot, thisObject)))
@@ -594,9 +594,9 @@
if (propertyName == vm.propertyNames->length || propertyName == vm.propertyNames->name) {
FunctionRareData* rareData = thisObject->ensureRareData(vm);
if (propertyName == vm.propertyNames->length)
- rareData->setHasModifiedLength();
+ rareData->setHasModifiedLengthForNonHostFunction();
else
- rareData->setHasModifiedName();
+ rareData->setHasModifiedNameForNonHostFunction();
}
if (thisObject->isHostOrBuiltinFunction()) {
@@ -629,9 +629,9 @@
if (propertyName == vm.propertyNames->length || propertyName == vm.propertyNames->name) {
FunctionRareData* rareData = thisObject->ensureRareData(vm);
if (propertyName == vm.propertyNames->length)
- rareData->setHasModifiedLength();
+ rareData->setHasModifiedLengthForNonHostFunction();
else
- rareData->setHasModifiedName();
+ rareData->setHasModifiedNameForNonHostFunction();
}
if (thisObject->isHostOrBuiltinFunction()) {
Modified: branches/safari-609-branch/Source/_javascript_Core/runtime/JSFunction.h (258160 => 258161)
--- branches/safari-609-branch/Source/_javascript_Core/runtime/JSFunction.h 2020-03-09 20:23:45 UTC (rev 258160)
+++ branches/safari-609-branch/Source/_javascript_Core/runtime/JSFunction.h 2020-03-09 21:14:46 UTC (rev 258161)
@@ -164,7 +164,7 @@
};
PropertyStatus reifyLazyPropertyIfNeeded(VM&, JSGlobalObject*, PropertyName);
- bool areNameAndLengthOriginal(VM&);
+ bool canAssumeNameAndLengthAreOriginal(VM&);
protected:
JS_EXPORT_PRIVATE JSFunction(VM&, NativeExecutable*, JSGlobalObject*, Structure*);
Modified: branches/safari-609-branch/Source/_javascript_Core/runtime/JSFunctionInlines.h (258160 => 258161)
--- branches/safari-609-branch/Source/_javascript_Core/runtime/JSFunctionInlines.h 2020-03-09 20:23:45 UTC (rev 258160)
+++ branches/safari-609-branch/Source/_javascript_Core/runtime/JSFunctionInlines.h 2020-03-09 21:14:46 UTC (rev 258161)
@@ -111,14 +111,16 @@
return false;
}
-inline bool JSFunction::areNameAndLengthOriginal(VM&)
+inline bool JSFunction::canAssumeNameAndLengthAreOriginal(VM&)
{
+ if (isHostFunction())
+ return false;
FunctionRareData* rareData = this->rareData();
if (!rareData)
return true;
- if (rareData->hasModifiedName())
+ if (rareData->hasModifiedNameForNonHostFunction())
return false;
- if (rareData->hasModifiedLength())
+ if (rareData->hasModifiedLengthForNonHostFunction())
return false;
return true;
}
Modified: branches/safari-609-branch/Source/_javascript_Core/runtime/JSGlobalObject.cpp (258160 => 258161)
--- branches/safari-609-branch/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2020-03-09 20:23:45 UTC (rev 258160)
+++ branches/safari-609-branch/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2020-03-09 21:14:46 UTC (rev 258161)
@@ -288,12 +288,19 @@
static EncodedJSValue JSC_HOST_CALL hasOwnLengthProperty(JSGlobalObject* globalObject, CallFrame* callFrame)
{
VM& vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
JSObject* target = asObject(callFrame->uncheckedArgument(0));
JSFunction* function = jsDynamicCast<JSFunction*>(vm, target);
- if (function)
- return JSValue::encode(jsBoolean(function->areNameAndLengthOriginal(vm)));
- return JSValue::encode(jsBoolean(target->hasOwnProperty(globalObject, vm.propertyNames->length)));
+ if (function && function->canAssumeNameAndLengthAreOriginal(vm)) {
+#if ASSERT_ENABLED
+ bool result = target->hasOwnProperty(globalObject, vm.propertyNames->length);
+ RETURN_IF_EXCEPTION(scope, { });
+ ASSERT(result);
+#endif
+ return JSValue::encode(jsBoolean(true));
+ }
+ RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(target->hasOwnProperty(globalObject, vm.propertyNames->length))));
}
#if !ASSERT_DISABLED