Changeset 263222 in webkit


Ignore:
Timestamp:
Jun 18, 2020, 11:22:15 AM (4 years ago)
Author:
Alexey Shvayka
Message:

Promise built-in functions should be anonymous non-constructors
https://bugs.webkit.org/show_bug.cgi?id=213317

Reviewed by Darin Adler.

JSTests:

  • test262/expectations.yaml: Mark 20 test cases as passing.

Source/JavaScriptCore:

This patch makes userland-exposed Promise built-in functions
non-constructors and sets their "name" properties to empty strings
as per spec [1], aligning JSC with V8 and SpiderMonkey.

@createResolvingFunctionsWithoutPromise change is covered by test262's
async-generator/yield-thenable-create-resolving-functions-*.js cases.

Promise microbenchmarks are neutral. Promise constructors bytecode is
unchanged, while @createResolvingFunctions* bytecode is reduced by 2
instructions.

[1]: https://tc39.es/ecma262/#sec-ecmascript-standard-built-in-objects

  • builtins/PromiseConstructor.js:

(nakedConstructor.Promise):
(nakedConstructor.InternalPromise):

  • builtins/PromiseOperations.js:

(globalPrivate.newPromiseCapabilitySlow):
(globalPrivate.createResolvingFunctions):
(globalPrivate.createResolvingFunctionsWithoutPromise):
(globalPrivate.createResolvingFunctions.resolve): Deleted.
(globalPrivate.createResolvingFunctions.reject): Deleted.
(resolve): Deleted.
(reject): Deleted.

  • builtins/PromisePrototype.js:

(globalPrivate.getThenFinally):
(globalPrivate.getCatchFinally):
(valueThunk): Deleted.
(thrower): Deleted.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r263216 r263222  
     12020-06-18  Alexey Shvayka  <shvaikalesh@gmail.com>
     2
     3        Promise built-in functions should be anonymous non-constructors
     4        https://bugs.webkit.org/show_bug.cgi?id=213317
     5
     6        Reviewed by Darin Adler.
     7
     8        * test262/expectations.yaml: Mark 20 test cases as passing.
     9
    1102020-06-18  Alexey Shvayka  <shvaikalesh@gmail.com>
    211
  • trunk/JSTests/test262/expectations.yaml

    r263216 r263222  
    995995  default: 'Test262Error: Expected [b, a] and [a, b] to have the same contents. '
    996996  strict mode: 'Test262Error: Expected [b, a] and [a, b] to have the same contents. '
    997 test/built-ins/Promise/create-resolving-functions-reject.js:
    998   default: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected true but got false'
    999   strict mode: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected true but got false'
    1000 test/built-ins/Promise/create-resolving-functions-resolve.js:
    1001   default: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected true but got false'
    1002   strict mode: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected true but got false'
    1003 test/built-ins/Promise/executor-function-nonconstructor.js:
    1004   default: 'Test262Error: Expected SameValue(«true», «false») to be true'
    1005   strict mode: 'Test262Error: Expected SameValue(«true», «false») to be true'
    1006 test/built-ins/Promise/prototype/finally/invokes-then-with-function.js:
    1007   default: 'Test262Error: fulfillment handler is not constructor'
    1008   strict mode: 'Test262Error: fulfillment handler is not constructor'
    1009 test/built-ins/Promise/prototype/finally/rejected-observable-then-calls-argument.js:
    1010   default: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected true but got false'
    1011   strict mode: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected true but got false'
    1012 test/built-ins/Promise/prototype/finally/resolved-observable-then-calls-argument.js:
    1013   default: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected true but got false'
    1014   strict mode: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected true but got false'
    1015 test/built-ins/Promise/reject-function-nonconstructor.js:
    1016   default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
    1017   strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
    1018 test/built-ins/Promise/resolve-function-nonconstructor.js:
    1019   default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
    1020   strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
    1021997test/built-ins/Proxy/apply/arguments-realm.js:
    1022998  default: 'Test262Error: Expected SameValue(«function Array() {'
     
    21092085test/language/expressions/async-generator/named-eval-var-scope-syntax-err.js:
    21102086  default: 'Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all'
    2111 test/language/expressions/async-generator/yield-thenable-create-resolving-functions-reject.js:
    2112   default: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected true but got false'
    2113   strict mode: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected true but got false'
    2114 test/language/expressions/async-generator/yield-thenable-create-resolving-functions-resolve.js:
    2115   default: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected true but got false'
    2116   strict mode: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected true but got false'
    21172087test/language/expressions/await/async-await-interleaved.js:
    21182088  default: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected [Await: 1, Promise: 1, Promise: 2, Await: 2] and [Await: 1, Promise: 1, Await: 2, Promise: 2] to have the same contents. Async/await and promises should be interleaved'
  • trunk/Source/JavaScriptCore/ChangeLog

    r263216 r263222  
     12020-06-18  Alexey Shvayka  <shvaikalesh@gmail.com>
     2
     3        Promise built-in functions should be anonymous non-constructors
     4        https://bugs.webkit.org/show_bug.cgi?id=213317
     5
     6        Reviewed by Darin Adler.
     7
     8        This patch makes userland-exposed Promise built-in functions
     9        non-constructors and sets their "name" properties to empty strings
     10        as per spec [1], aligning JSC with V8 and SpiderMonkey.
     11
     12        @createResolvingFunctionsWithoutPromise change is covered by test262's
     13        async-generator/yield-thenable-create-resolving-functions-*.js cases.
     14
     15        Promise microbenchmarks are neutral. Promise constructors bytecode is
     16        unchanged, while @createResolvingFunctions* bytecode is reduced by 2
     17        instructions.
     18
     19        [1]: https://tc39.es/ecma262/#sec-ecmascript-standard-built-in-objects
     20
     21        * builtins/PromiseConstructor.js:
     22        (nakedConstructor.Promise):
     23        (nakedConstructor.InternalPromise):
     24        * builtins/PromiseOperations.js:
     25        (globalPrivate.newPromiseCapabilitySlow):
     26        (globalPrivate.createResolvingFunctions):
     27        (globalPrivate.createResolvingFunctionsWithoutPromise):
     28        (globalPrivate.createResolvingFunctions.resolve): Deleted.
     29        (globalPrivate.createResolvingFunctions.reject): Deleted.
     30        (resolve): Deleted.
     31        (reject): Deleted.
     32        * builtins/PromisePrototype.js:
     33        (globalPrivate.getThenFinally):
     34        (globalPrivate.getCatchFinally):
     35        (valueThunk): Deleted.
     36        (thrower): Deleted.
     37
    1382020-06-18  Alexey Shvayka  <shvaikalesh@gmail.com>
    239
  • trunk/Source/JavaScriptCore/builtins/PromiseConstructor.js

    r260273 r263222  
    292292    try {
    293293        executor(
    294             function (resolution) {
     294            (resolution) => {
    295295                return @resolvePromiseWithFirstResolvingFunctionCallCheck(capturedPromise, resolution);
    296296            },
    297             function (reason) {
     297            (reason) => {
    298298                return @rejectPromiseWithFirstResolvingFunctionCallCheck(capturedPromise, reason);
    299299            });
     
    318318    try {
    319319        executor(
    320             function (resolution) {
     320            (resolution) => {
    321321                return @resolvePromiseWithFirstResolvingFunctionCallCheck(capturedPromise, resolution);
    322322            },
    323             function (reason) {
     323            (reason) => {
    324324                return @rejectPromiseWithFirstResolvingFunctionCallCheck(capturedPromise, reason);
    325325            });
  • trunk/Source/JavaScriptCore/builtins/PromiseOperations.js

    r261601 r263222  
    4949    };
    5050
    51     var promise = new constructor(function (resolve, reject) {
     51    var promise = new constructor((resolve, reject) => {
    5252        if (promiseCapability.@resolve !== @undefined)
    5353            @throwTypeError("resolve function is already set");
     
    237237{
    238238    "use strict";
    239 
    240239    @assert(@isPromise(promise));
    241240
    242241    var alreadyResolved = false;
    243242
    244     function @resolve(resolution) {
     243    var resolve = (0, /* prevent function name inference */ (resolution) => {
    245244        if (alreadyResolved)
    246245            return @undefined;
     
    248247
    249248        return @resolvePromise(promise, resolution);
    250     }
    251 
    252     function @reject(reason) {
     249    });
     250
     251    var reject = (0, /* prevent function name inference */ (reason) => {
    253252        if (alreadyResolved)
    254253            return @undefined;
     
    256255
    257256        return @rejectPromise(promise, reason);
    258     }
    259 
    260     return { @resolve, @reject };
     257    });
     258
     259    return { @resolve: resolve, @reject: reject };
    261260}
    262261
     
    331330    var alreadyResolved = false;
    332331
    333     function @resolve(resolution) {
     332    var resolve = (0, /* prevent function name inference */ (resolution) => {
    334333        if (alreadyResolved)
    335334            return @undefined;
     
    337336
    338337        @resolveWithoutPromise(resolution, onFulfilled, onRejected);
    339     }
    340 
    341     function @reject(reason) {
     338    });
     339
     340    var reject = (0, /* prevent function name inference */ (reason) => {
    342341        if (alreadyResolved)
    343342            return @undefined;
     
    345344
    346345        @rejectWithoutPromise(reason, onFulfilled, onRejected);
    347     }
    348 
    349     return { @resolve, @reject };
     346    });
     347
     348    return { @resolve: resolve, @reject: reject };
    350349}
    351350
  • trunk/Source/JavaScriptCore/builtins/PromisePrototype.js

    r254418 r263222  
    103103    "use strict";
    104104
    105     return function(value)
     105    return (value) =>
    106106    {
    107107        @assert(typeof onFinally === "function");
     
    114114
    115115        var promise = resultCapability.@promise;
    116         var valueThunk = function () { return value; };
    117 
    118         return promise.then(valueThunk);
     116        return promise.then(() => value);
    119117    }
    120118}
     
    125123    "use strict";
    126124
    127     return function(reason)
     125    return (reason) =>
    128126    {
    129127        @assert(typeof onFinally === "function");
     
    136134
    137135        var promise = resultCapability.@promise;
    138         var thrower = function () { throw reason; };
    139 
    140         return promise.then(thrower);
     136        return promise.then(() => { throw reason; });
    141137    }
    142138}
Note: See TracChangeset for help on using the changeset viewer.