- Revision
- 267029
- Author
- [email protected]
- Date
- 2020-09-14 12:49:01 -0700 (Mon, 14 Sep 2020)
Log Message
Make a few built-in methods throw if called as top-level functions
https://bugs.webkit.org/show_bug.cgi?id=216467
Reviewed by Darin Adler.
JSTests:
* test262/expectations.yaml: Mark 10 test cases as passing.
Source/_javascript_Core:
Non-strict userland functions substitute undefined & null `this` values
with the global object [1], while built-in functions do not [2].
This patch adds 5 missing toThis(globalObject, ECMAMode::strict()) calls,
preventing built-in methods from being called as top-level functions:
```
let {toString} = Error.prototype;
toString(); // now throws TypeError
```
Aligns JSC with V8 and SpiderMonkey.
This change is performance-neutral due to DFG inlining of OpToThis.
All other callFrame->thisValue() usages were vetted to be spec-correct.
[1]: https://tc39.es/ecma262/#sec-ordinarycallbindthis (step 6.a.iii)
[2]: https://tc39.es/ecma262/#sec-built-in-function-objects-call-thisargument-argumentslist (step 10)
* runtime/ArrayPrototype.cpp:
(JSC::createArrayIteratorObject):
* runtime/DatePrototype.cpp:
(JSC::dateProtoFuncToPrimitiveSymbol):
(JSC::dateProtoFuncToJSON):
* runtime/ErrorPrototype.cpp:
(JSC::errorProtoFuncToString):
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncToString):
Modified Paths
Diff
Modified: trunk/JSTests/ChangeLog (267028 => 267029)
--- trunk/JSTests/ChangeLog 2020-09-14 19:30:11 UTC (rev 267028)
+++ trunk/JSTests/ChangeLog 2020-09-14 19:49:01 UTC (rev 267029)
@@ -1,3 +1,12 @@
+2020-09-14 Alexey Shvayka <[email protected]>
+
+ Make a few built-in methods throw if called as top-level functions
+ https://bugs.webkit.org/show_bug.cgi?id=216467
+
+ Reviewed by Darin Adler.
+
+ * test262/expectations.yaml: Mark 10 test cases as passing.
+
2020-09-14 Saam Barati <[email protected]>
Don't assume byte code operands are uint32 JSValues
Modified: trunk/JSTests/test262/expectations.yaml (267028 => 267029)
--- trunk/JSTests/test262/expectations.yaml 2020-09-14 19:30:11 UTC (rev 267028)
+++ trunk/JSTests/test262/expectations.yaml 2020-09-14 19:49:01 UTC (rev 267029)
@@ -609,9 +609,6 @@
test/built-ins/Array/length/define-own-prop-length-overflow-order.js:
default: 'Test262Error: Expected a RangeError but got a TypeError'
strict mode: 'Test262Error: Expected a RangeError but got a TypeError'
-test/built-ins/Array/prototype/methods-called-as-functions.js:
- default: 'Test262Error: entries Expected a TypeError to be thrown but no exception was thrown at all'
- strict mode: 'Test262Error: entries Expected a TypeError to be thrown but no exception was thrown at all'
test/built-ins/ArrayBuffer/prototype/byteLength/detached-buffer.js:
default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
@@ -642,15 +639,6 @@
test/built-ins/ArrayIteratorPrototype/next/detach-typedarray-in-progress.js:
default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
-test/built-ins/Date/prototype/Symbol.toPrimitive/called-as-function.js:
- default: 'Test262Error: Expected a TypeError but got a Test262Error'
- strict mode: 'Test262Error: Expected a TypeError but got a Test262Error'
-test/built-ins/Date/prototype/toJSON/called-as-function.js:
- default: 'Test262Error: Expected a TypeError but got a Test262Error'
- strict mode: 'Test262Error: Expected a TypeError but got a Test262Error'
-test/built-ins/Error/prototype/toString/called-as-function.js:
- default: 'Test262Error: Expected a TypeError but got a Test262Error'
- strict mode: 'Test262Error: Expected a TypeError but got a Test262Error'
test/built-ins/Function/call-bind-this-realm-undef.js:
default: 'Test262Error: implicit undefined Expected SameValue(«[object global]», «[object Undefined]») to be true'
strict mode: 'Test262Error: implicit undefined Expected SameValue(«[object global]», «[object Undefined]») to be true'
@@ -1285,9 +1273,6 @@
test/built-ins/RegExp/prototype/exec/u-lastindex-adv.js:
default: 'Test262Error: Expected SameValue(«�», «null») to be true'
strict mode: 'Test262Error: Expected SameValue(«�», «null») to be true'
-test/built-ins/RegExp/prototype/toString/called-as-function.js:
- default: 'Test262Error: Expected a TypeError but got a Test262Error'
- strict mode: 'Test262Error: Expected a TypeError but got a Test262Error'
test/built-ins/RegExp/quantifier-integer-limit.js:
default: 'SyntaxError: Invalid regular _expression_: number too large in {} quantifier'
strict mode: 'SyntaxError: Invalid regular _expression_: number too large in {} quantifier'
Modified: trunk/Source/_javascript_Core/ChangeLog (267028 => 267029)
--- trunk/Source/_javascript_Core/ChangeLog 2020-09-14 19:30:11 UTC (rev 267028)
+++ trunk/Source/_javascript_Core/ChangeLog 2020-09-14 19:49:01 UTC (rev 267029)
@@ -1,3 +1,38 @@
+2020-09-14 Alexey Shvayka <[email protected]>
+
+ Make a few built-in methods throw if called as top-level functions
+ https://bugs.webkit.org/show_bug.cgi?id=216467
+
+ Reviewed by Darin Adler.
+
+ Non-strict userland functions substitute undefined & null `this` values
+ with the global object [1], while built-in functions do not [2].
+
+ This patch adds 5 missing toThis(globalObject, ECMAMode::strict()) calls,
+ preventing built-in methods from being called as top-level functions:
+
+ ```
+ let {toString} = Error.prototype;
+ toString(); // now throws TypeError
+ ```
+
+ Aligns JSC with V8 and SpiderMonkey.
+ This change is performance-neutral due to DFG inlining of OpToThis.
+ All other callFrame->thisValue() usages were vetted to be spec-correct.
+
+ [1]: https://tc39.es/ecma262/#sec-ordinarycallbindthis (step 6.a.iii)
+ [2]: https://tc39.es/ecma262/#sec-built-in-function-objects-call-thisargument-argumentslist (step 10)
+
+ * runtime/ArrayPrototype.cpp:
+ (JSC::createArrayIteratorObject):
+ * runtime/DatePrototype.cpp:
+ (JSC::dateProtoFuncToPrimitiveSymbol):
+ (JSC::dateProtoFuncToJSON):
+ * runtime/ErrorPrototype.cpp:
+ (JSC::errorProtoFuncToString):
+ * runtime/RegExpPrototype.cpp:
+ (JSC::regExpProtoFuncToString):
+
2020-09-14 Devin Rousso <[email protected]>
Web Inspector: REGRESSION(r266885): dyld: Symbol not found: __ZN9Inspector17BackendDispatcher12sendResponseElON3WTF6RefPtrINS1_8JSONImpl6ObjectENS1_13DumbPtrTraitsIS4_EEEEb
Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (267028 => 267029)
--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2020-09-14 19:30:11 UTC (rev 267028)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2020-09-14 19:49:01 UTC (rev 267029)
@@ -828,7 +828,7 @@
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- JSObject* thisObject = callFrame->thisValue().toObject(globalObject);
+ JSObject* thisObject = callFrame->thisValue().toThis(globalObject, ECMAMode::strict()).toObject(globalObject);
EXCEPTION_ASSERT(!!scope.exception() == !thisObject);
UNUSED_PARAM(scope);
if (UNLIKELY(!thisObject))
Modified: trunk/Source/_javascript_Core/runtime/DatePrototype.cpp (267028 => 267029)
--- trunk/Source/_javascript_Core/runtime/DatePrototype.cpp 2020-09-14 19:30:11 UTC (rev 267028)
+++ trunk/Source/_javascript_Core/runtime/DatePrototype.cpp 2020-09-14 19:49:01 UTC (rev 267029)
@@ -352,7 +352,7 @@
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- JSValue thisValue = callFrame->thisValue();
+ JSValue thisValue = callFrame->thisValue().toThis(globalObject, ECMAMode::strict());
if (!thisValue.isObject())
return throwVMTypeError(globalObject, scope, "Date.prototype[Symbol.toPrimitive] expected |this| to be an object.");
JSObject* thisObject = jsCast<JSObject*>(thisValue);
@@ -883,7 +883,7 @@
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- JSValue thisValue = callFrame->thisValue();
+ JSValue thisValue = callFrame->thisValue().toThis(globalObject, ECMAMode::strict());
JSObject* object = thisValue.toObject(globalObject);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
Modified: trunk/Source/_javascript_Core/runtime/ErrorPrototype.cpp (267028 => 267029)
--- trunk/Source/_javascript_Core/runtime/ErrorPrototype.cpp 2020-09-14 19:30:11 UTC (rev 267028)
+++ trunk/Source/_javascript_Core/runtime/ErrorPrototype.cpp 2020-09-14 19:49:01 UTC (rev 267029)
@@ -73,7 +73,7 @@
auto scope = DECLARE_THROW_SCOPE(vm);
// 1. Let O be the this value.
- JSValue thisValue = callFrame->thisValue();
+ JSValue thisValue = callFrame->thisValue().toThis(globalObject, ECMAMode::strict());
// 2. If Type(O) is not Object, throw a TypeError exception.
if (!thisValue.isObject())
Modified: trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp (267028 => 267029)
--- trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp 2020-09-14 19:30:11 UTC (rev 267028)
+++ trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp 2020-09-14 19:49:01 UTC (rev 267029)
@@ -206,7 +206,7 @@
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- JSValue thisValue = callFrame->thisValue();
+ JSValue thisValue = callFrame->thisValue().toThis(globalObject, ECMAMode::strict());
if (!thisValue.isObject())
return throwVMTypeError(globalObject, scope);