Title: [267029] trunk
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);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to