Promise constructor should check argument before [[Construct]]
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Aug 2019 20:09:39 +0000 (20:09 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Aug 2019 20:09:39 +0000 (20:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=198976

Patch by Alexey Shvayka <shvaikalesh@gmail.com> on 2019-08-16
Reviewed by Ross Kirsling.

JSTests:

* stress/create-subclass-structure-may-throw-exception-when-getting-prototype.js: Fix test.
* stress/create-subclass-structure-might-throw.js: Fix test.
* test262/expectations.yaml: Mark 2 test cases as passing.

Source/JavaScriptCore:

Check if argument is a function before invoking `createSubclassStructure`.
(step 2 of https://tc39.es/ecma262/#sec-promise-executor)

* builtins/PromiseOperations.js:
(globalPrivate.initializePromise): Remove typeof check.
* runtime/JSPromiseConstructor.cpp:
(JSC::constructPromise): Add isFunction check.

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

JSTests/ChangeLog
JSTests/stress/create-subclass-structure-may-throw-exception-when-getting-prototype.js
JSTests/stress/create-subclass-structure-might-throw.js
JSTests/test262/expectations.yaml
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/builtins/PromiseOperations.js
Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp

index 4d3599e..4bc3a96 100644 (file)
@@ -1,3 +1,14 @@
+2019-08-16  Alexey Shvayka  <shvaikalesh@gmail.com>
+
+        Promise constructor should check argument before [[Construct]]
+        https://bugs.webkit.org/show_bug.cgi?id=198976
+
+        Reviewed by Ross Kirsling.
+
+        * stress/create-subclass-structure-may-throw-exception-when-getting-prototype.js: Fix test.
+        * stress/create-subclass-structure-might-throw.js: Fix test.
+        * test262/expectations.yaml: Mark 2 test cases as passing.
+
 2019-08-16  Ryan Haddad  <ryanhaddad@apple.com>
 
         Unreviewed, rolling out r248709.
index f78d1b3..14bc000 100644 (file)
@@ -29,7 +29,6 @@ Object.defineProperty(bf, "prototype", {
     Error,
     Uint8Array,
     ArrayBuffer,
-    Promise,
     Map,
     WeakMap,
     Set,
@@ -40,5 +39,9 @@ Object.defineProperty(bf, "prototype", {
     }, `Error: OK`);
 });
 
+shouldThrow(() => {
+    Reflect.construct(Promise, [() => {}], bf);
+}, `Error: OK`);
+
 // Proxy constructor is not aware of new.target.
 Reflect.construct(Proxy, [{}, {}], bf);
index ef8640f..1d851b5 100644 (file)
@@ -21,7 +21,10 @@ for (let target of targets) {
     for (let i = 0; i < 500; i++) {
         let threw = false;
         try {
-            new proxy;
+            if (target === Promise)
+                new proxy(function() {});
+            else
+                new proxy;
         } catch(e) {
             threw = true;
             assert(e === error);
index 40ddbdb..b073620 100644 (file)
@@ -1282,9 +1282,6 @@ test/built-ins/Promise/allSettled/reject-element-function-nonconstructor.js:
 test/built-ins/Promise/allSettled/resolve-element-function-nonconstructor.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'
-test/built-ins/Promise/get-prototype-abrupt-executor-not-callable.js:
-  default: 'Test262Error: Expected a TypeError but got a Test262Error'
-  strict mode: 'Test262Error: Expected a TypeError but got a Test262Error'
 test/built-ins/Promise/proto-from-ctor-realm.js:
   default: 'Test262Error: Expected SameValue(«[object Promise]», Â«[object Promise]») to be true'
   strict mode: 'Test262Error: Expected SameValue(«[object Promise]», Â«[object Promise]») to be true'
index d874baf..cb2850b 100644 (file)
@@ -1,3 +1,18 @@
+2019-08-16  Alexey Shvayka  <shvaikalesh@gmail.com>
+
+        Promise constructor should check argument before [[Construct]]
+        https://bugs.webkit.org/show_bug.cgi?id=198976
+
+        Reviewed by Ross Kirsling.
+
+        Check if argument is a function before invoking `createSubclassStructure`.
+        (step 2 of https://tc39.es/ecma262/#sec-promise-executor)
+
+        * builtins/PromiseOperations.js:
+        (globalPrivate.initializePromise): Remove typeof check.
+        * runtime/JSPromiseConstructor.cpp:
+        (JSC::constructPromise): Add isFunction check.
+
 2019-08-16  Ryan Haddad  <ryanhaddad@apple.com>
 
         Unreviewed, rolling out r248709.
index 54d81bc..e4e1c73 100644 (file)
@@ -216,9 +216,6 @@ function initializePromise(executor)
 {
     "use strict";
 
-    if (typeof executor !== 'function')
-        @throwTypeError("Promise constructor takes a function argument");
-
     @putByIdDirectPrivate(this, "promiseState", @promiseStatePending);
     @putByIdDirectPrivate(this, "promiseReactions", []);
     @putByIdDirectPrivate(this, "promiseIsHandled", false);
index 053fed2..8409d6e 100644 (file)
@@ -112,10 +112,14 @@ static EncodedJSValue JSC_HOST_CALL constructPromise(ExecState* exec)
     if (newTarget.isUndefined())
         return throwVMTypeError(exec, scope);
 
+    JSValue executor = exec->argument(0);
+    if (!executor.isFunction(vm))
+        return throwVMTypeError(exec, scope, "Promise constructor takes a function argument"_s);
+
     Structure* promiseStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->promiseStructure());
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
     JSPromise* promise = JSPromise::create(vm, promiseStructure);
-    promise->initialize(exec, globalObject,  exec->argument(0));
+    promise->initialize(exec, globalObject, executor);
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     return JSValue::encode(promise);