mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out 6 changesets (bug 1185106) for build bustage CLOSED TREE
Backed out changeset 6bd1aab9f146 (bug 1185106) Backed out changeset ede6564c4d13 (bug 1185106) Backed out changeset abf4f0c6f42e (bug 1185106) Backed out changeset 102aa11bc1aa (bug 1185106) Backed out changeset 9c74d17cf769 (bug 1185106) Backed out changeset c3d780ac9879 (bug 1185106)
This commit is contained in:
parent
0b1451ba03
commit
b0731744b5
@ -284,7 +284,6 @@ selfhosting:: selfhosted.out.h
|
||||
selfhosting_srcs := \
|
||||
$(srcdir)/builtin/Utilities.js \
|
||||
$(srcdir)/builtin/Array.js \
|
||||
$(srcdir)/builtin/AsyncFunctions.js \
|
||||
$(srcdir)/builtin/Date.js \
|
||||
$(srcdir)/builtin/Error.js \
|
||||
$(srcdir)/builtin/Generator.js \
|
||||
@ -295,7 +294,6 @@ selfhosting_srcs := \
|
||||
$(srcdir)/builtin/Module.js \
|
||||
$(srcdir)/builtin/Number.js \
|
||||
$(srcdir)/builtin/Object.js \
|
||||
$(srcdir)/builtin/Promise.js \
|
||||
$(srcdir)/builtin/Reflect.js \
|
||||
$(srcdir)/builtin/RegExp.js \
|
||||
$(srcdir)/builtin/String.js \
|
||||
|
@ -6348,7 +6348,7 @@ ParseFunction(ModuleValidator& m, ParseNode** fnOut)
|
||||
AsmJSParseContext* outerpc = m.parser().pc;
|
||||
|
||||
Directives directives(outerpc);
|
||||
FunctionBox* funbox = m.parser().newFunctionBox(fn, fun, outerpc, directives, NotGenerator, SyncFunction);
|
||||
FunctionBox* funbox = m.parser().newFunctionBox(fn, fun, outerpc, directives, NotGenerator);
|
||||
if (!funbox)
|
||||
return false;
|
||||
|
||||
|
@ -1,46 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function AsyncFunction_wrap(genFunction) {
|
||||
var wrapper = function() {
|
||||
// The try block is required to handle throws in default arguments properly.
|
||||
try {
|
||||
return AsyncFunction_start(callFunction(std_Function_apply, genFunction, this, arguments));
|
||||
} catch (e) {
|
||||
return Promise_reject(e);
|
||||
}
|
||||
};
|
||||
SetFunctionExtendedSlot(genFunction, 1, wrapper);
|
||||
var name = GetFunName(genFunction);
|
||||
if (typeof name !== 'undefined')
|
||||
SetFunName(wrapper, name);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
function AsyncFunction_start(generator) {
|
||||
return AsyncFunction_resume(generator, undefined, generator.next);
|
||||
}
|
||||
|
||||
function AsyncFunction_resume(gen, v, method) {
|
||||
let result;
|
||||
try {
|
||||
// get back into async function, run to next await point
|
||||
result = callFunction(method, gen, v);
|
||||
} catch (exc) {
|
||||
// The async function itself failed.
|
||||
return Promise_reject(exc);
|
||||
}
|
||||
|
||||
if (result.done)
|
||||
return Promise_resolve(result.value);
|
||||
|
||||
// If we get here, `await` occurred. `gen` is paused at a yield point.
|
||||
return callFunction(Promise_then,
|
||||
Promise_resolve(result.value),
|
||||
function(val) {
|
||||
return AsyncFunction_resume(gen, val, gen.next);
|
||||
}, function (err) {
|
||||
return AsyncFunction_resume(gen, err, gen.throw);
|
||||
});
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "builtin/Promise.h"
|
||||
#include "builtin/SelfHostingDefines.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
static const JSFunctionSpec promise_methods[] = {
|
||||
JS_SELF_HOSTED_FN("catch", "Promise_catch", 1, 0),
|
||||
JS_SELF_HOSTED_FN("then", "Promise_then", 2, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
static const JSFunctionSpec promise_static_methods[] = {
|
||||
JS_SELF_HOSTED_FN("all", "Promise_all", 1, 0),
|
||||
JS_SELF_HOSTED_FN("race", "Promise_race", 1, 0),
|
||||
JS_SELF_HOSTED_FN("reject", "Promise_reject", 1, 0),
|
||||
JS_SELF_HOSTED_FN("resolve", "Promise_resolve", 1, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
namespace js {
|
||||
|
||||
bool
|
||||
PromiseConstructor(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (args.length() == 0) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
|
||||
"ShellPromise.constructor", "0", "s");
|
||||
return false;
|
||||
}
|
||||
|
||||
HandleValue fn = args.get(0);
|
||||
|
||||
if (!IsCallable(fn)) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NOT_CALLABLE,
|
||||
"Argument 1 of ShellPromise.constructor");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject promise(cx, NewBuiltinClassInstance(cx, &ShellPromiseObject::class_));
|
||||
if (!promise)
|
||||
return false;
|
||||
|
||||
JS_SetReservedSlot(promise, PROMISE_STATE_SLOT, NumberValue(PROMISE_STATE_PENDING));
|
||||
JS_SetReservedSlot(promise, PROMISE_VALUE_SLOT, NullValue());
|
||||
JS_SetReservedSlot(promise, PROMISE_DEFERREDS_SLOT, NullValue());
|
||||
|
||||
RootedValue initRval(cx);
|
||||
JS::AutoValueVector argValues(cx);
|
||||
argValues.append(ObjectValue(*promise));
|
||||
argValues.append(fn);
|
||||
HandleValueArray arr(argValues);
|
||||
|
||||
JSAtom* promiseInitAtom;
|
||||
if (!(promiseInitAtom = Atomize(cx, "Promise_init", 12)))
|
||||
return false;
|
||||
|
||||
RootedPropertyName name(cx, promiseInitAtom->asPropertyName());
|
||||
RootedValue selfHostedFun(cx);
|
||||
|
||||
if (!GlobalObject::getIntrinsicValue(cx, cx->global(), name, &selfHostedFun))
|
||||
return false;
|
||||
|
||||
if (!JS_CallFunctionValue(cx, promise, selfHostedFun, arr, &initRval))
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*promise);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
CreatePromisePrototype(JSContext* cx, JSProtoKey key)
|
||||
{
|
||||
return cx->global()->createBlankPrototype(cx, &ShellPromiseObject::protoClass_);
|
||||
}
|
||||
|
||||
const Class ShellPromiseObject::class_ = {
|
||||
"ShellPromise",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) | JSCLASS_HAS_CACHED_PROTO(JSProto_ShellPromise),
|
||||
nullptr, /* addProperty */
|
||||
nullptr, /* delProperty */
|
||||
nullptr, /* getProperty */
|
||||
nullptr, /* setProperty */
|
||||
nullptr, /* enumerate */
|
||||
nullptr, /* resolve */
|
||||
nullptr, /* mayResolve */
|
||||
nullptr, /* finalize */
|
||||
nullptr, /* call */
|
||||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
nullptr, /* trace */
|
||||
{
|
||||
GenericCreateConstructor<PromiseConstructor, 2, gc::AllocKind::FUNCTION>,
|
||||
CreatePromisePrototype,
|
||||
promise_static_methods,
|
||||
nullptr,
|
||||
promise_methods
|
||||
}
|
||||
};
|
||||
|
||||
const Class ShellPromiseObject::protoClass_ = {
|
||||
"ShellPromise",
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_ShellPromise),
|
||||
nullptr, /* addProperty */
|
||||
nullptr, /* delProperty */
|
||||
nullptr, /* getProperty */
|
||||
nullptr, /* setProperty */
|
||||
nullptr, /* enumerate */
|
||||
nullptr, /* resolve */
|
||||
nullptr, /* mayResolve */
|
||||
nullptr, /* finalize */
|
||||
nullptr, /* call */
|
||||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
nullptr, /* trace */
|
||||
{
|
||||
DELEGATED_CLASSSPEC(&ShellPromiseObject::class_.spec),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
ClassSpec::IsDelegated
|
||||
}
|
||||
};
|
@ -1,29 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef builtin_Promise_h
|
||||
#define builtin_Promise_h
|
||||
|
||||
#include "vm/NativeObject.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
class AutoSetNewObjectMetadata;
|
||||
|
||||
class ShellPromiseObject : public NativeObject
|
||||
{
|
||||
public:
|
||||
static const unsigned RESERVED_SLOTS = 3;
|
||||
static const Class class_;
|
||||
static const Class protoClass_;
|
||||
};
|
||||
|
||||
bool
|
||||
PromiseConstructor(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* builtin_Promise_h */
|
@ -1,241 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* This implementation is by no means complete and is using a polyfill.
|
||||
* In particular, it doesn't fully comply to ES6 Promises spec.
|
||||
* The list of incompatibilities may not be complete and includes:
|
||||
*
|
||||
* - no [Symbol.species] implementation
|
||||
* - implementation is not really async at all, but all is executed
|
||||
* in correct order
|
||||
* - Promise.race is not implemented (not necessary for async/await)
|
||||
* - Promise.all implementation currently only handles arrays, no other
|
||||
* iterables.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This polyfill implements the Promise specification in the following way:
|
||||
* At first, Promise is initialized with the intrinsic Promise constructor,
|
||||
* with its initialization completed by calling Promise_init. The goal is to
|
||||
* completely resolve/reject the promise. There are certain helper functions:
|
||||
* - resolveOneStep() executes "one step" of the promise - which means
|
||||
* getting either the final value or next promise towards complete execution.
|
||||
* - resolveCompletely() executes the entire promise, which merely means
|
||||
* resolving one step at a time, until the final step no longer resolves
|
||||
* to a promise (which means either resolving to a value or rejecting).
|
||||
*
|
||||
* Once resolution is finished, resolveCompletely() is called in order to
|
||||
* update state of the promise. It also spawns callbacks that may have been
|
||||
* deferred with a then() - they are NOT normally taken into consideration,
|
||||
* because resolveCompletely() just runs one path.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Below is a simple simulation of an event loop. Events enqueued using
|
||||
* this setTimeout implementation must be manually triggered by calling
|
||||
* runEvents().
|
||||
*/
|
||||
var eventQueue = new List();
|
||||
|
||||
function runEvents() {
|
||||
while (eventQueue.length > 0) {
|
||||
var evt = callFunction(std_Array_pop, eventQueue);
|
||||
evt();
|
||||
}
|
||||
}
|
||||
|
||||
function setTimeout(cb, interval) {
|
||||
if (!IsCallable(cb))
|
||||
ThrowTypeError(JSMSG_NOT_CALLABLE, "Argument 0");
|
||||
if (interval !== 0)
|
||||
ThrowTypeError(JSMSG_SETTIMEOUT_INTERVAL_NONZERO);
|
||||
callFunction(std_Array_push, eventQueue, cb);
|
||||
}
|
||||
|
||||
function Handler(onFulfilled, onRejected, resolve, reject) {
|
||||
this.onFulfilled = IsCallable(onFulfilled) ? onFulfilled : null;
|
||||
this.onRejected = IsCallable(onRejected) ? onRejected : null;
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
}
|
||||
|
||||
MakeConstructible(Handler, std_Object_create(null));
|
||||
|
||||
function Promise_setState(promise, state) {
|
||||
UnsafeSetReservedSlot(promise, PROMISE_STATE_SLOT, state);
|
||||
}
|
||||
|
||||
function Promise_getState(promise) {
|
||||
return UnsafeGetReservedSlot(promise, PROMISE_STATE_SLOT);
|
||||
}
|
||||
|
||||
function Promise_setDeferreds(promise, deferreds) {
|
||||
UnsafeSetReservedSlot(promise, PROMISE_DEFERREDS_SLOT, deferreds);
|
||||
}
|
||||
|
||||
function Promise_getDeferreds(promise) {
|
||||
return UnsafeGetReservedSlot(promise, PROMISE_DEFERREDS_SLOT);
|
||||
}
|
||||
|
||||
function Promise_setValue(promise, value) {
|
||||
UnsafeSetReservedSlot(promise, PROMISE_VALUE_SLOT, value);
|
||||
}
|
||||
|
||||
function Promise_getValue(promise) {
|
||||
return UnsafeGetReservedSlot(promise, PROMISE_VALUE_SLOT);
|
||||
}
|
||||
|
||||
function Promise_init(promise, fn) {
|
||||
Promise_setDeferreds(promise, new List());
|
||||
resolveOneStep(fn,
|
||||
function(value) { resolveCompletely(promise, value); },
|
||||
function(reason) { reject(promise, reason); });
|
||||
}
|
||||
|
||||
function Promise_isThenable(valueOrPromise) {
|
||||
if (valueOrPromise && (typeof valueOrPromise === 'object' || IsCallable(valueOrPromise))) {
|
||||
var then = valueOrPromise.then;
|
||||
if (IsCallable(then))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function Promise_all(promises) {
|
||||
var length = promises.length;
|
||||
var results = [];
|
||||
return NewPromise(function (resolve, reject) {
|
||||
if (length === 0)
|
||||
return resolve([]);
|
||||
var remaining = length;
|
||||
function resolveChain(index, valueOrPromise) {
|
||||
try {
|
||||
if (Promise_isThenable(valueOrPromise)) {
|
||||
callFunction(valueOrPromise.then, valueOrPromise,
|
||||
function (valueOrPromise) { resolveChain(index, valueOrPromise); },
|
||||
reject);
|
||||
} else {
|
||||
_DefineDataProperty(results, index, valueOrPromise);
|
||||
if (--remaining === 0)
|
||||
resolve(results);
|
||||
}
|
||||
} catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < length; i++)
|
||||
resolveChain(i, promises[i]);
|
||||
});
|
||||
}
|
||||
|
||||
function Promise_race(values) {
|
||||
ThrowTypeError(JSMSG_NOT_IMPLEMENTED, "Promise.race");
|
||||
}
|
||||
|
||||
function Promise_reject(value) {
|
||||
return NewPromise(function (resolve, reject) {
|
||||
reject(value);
|
||||
});
|
||||
}
|
||||
|
||||
function Promise_resolve(value) {
|
||||
if (value && typeof value === 'object' && IsPromise(value))
|
||||
return value;
|
||||
|
||||
return NewPromise(function (resolve) {
|
||||
resolve(value);
|
||||
});
|
||||
}
|
||||
|
||||
function Promise_catch(onRejected) {
|
||||
return callFunction(Promise_then, this, undefined, onRejected);
|
||||
}
|
||||
|
||||
function asap(cb) {
|
||||
setTimeout(cb, 0);
|
||||
}
|
||||
|
||||
function deferOrExecute(promise, deferred) {
|
||||
if (Promise_getState(promise) === PROMISE_STATE_PENDING) {
|
||||
Promise_getDeferreds(promise).push(deferred);
|
||||
return;
|
||||
}
|
||||
|
||||
asap(function() {
|
||||
var cb = Promise_getState(promise) === PROMISE_STATE_RESOLVED ?
|
||||
deferred.onFulfilled : deferred.onRejected;
|
||||
if (cb === null) {
|
||||
var value = Promise_getValue(promise);
|
||||
(Promise_getState(promise) === PROMISE_STATE_RESOLVED ? deferred.resolve : deferred.reject)(value);
|
||||
return;
|
||||
}
|
||||
var returnValue;
|
||||
try {
|
||||
returnValue = cb(Promise_getValue(promise));
|
||||
} catch (e) {
|
||||
deferred.reject(e);
|
||||
return;
|
||||
}
|
||||
deferred.resolve(returnValue);
|
||||
});
|
||||
}
|
||||
|
||||
function resolveOneStep(fn, onFulfilled, onRejected) {
|
||||
var done = false;
|
||||
var callOnce = function(cb) {
|
||||
return function(value) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
cb(value);
|
||||
};
|
||||
};
|
||||
|
||||
try {
|
||||
fn(callOnce(onFulfilled), callOnce(onRejected));
|
||||
} catch (ex) {
|
||||
callOnce(onRejected)(ex);
|
||||
}
|
||||
}
|
||||
|
||||
function resolveCompletely(promise, valueOrPromise) {
|
||||
try {
|
||||
// FIXME this is probably not a type error
|
||||
if (valueOrPromise === promise)
|
||||
ThrowTypeError(JSMSG_PROMISE_RESOLVED_WITH_ITSELF);
|
||||
|
||||
if (Promise_isThenable(valueOrPromise)) {
|
||||
resolveOneStep(function(resolve, reject) { valueOrPromise.then(resolve, reject); },
|
||||
function(value) { resolveCompletely(promise, value); },
|
||||
function(value) { reject(promise, value); });
|
||||
}
|
||||
else
|
||||
callFunction(resolvingFinished, promise, PROMISE_STATE_RESOLVED, valueOrPromise);
|
||||
} catch (ex) {
|
||||
callFunction(reject, promise, ex);
|
||||
}
|
||||
}
|
||||
|
||||
function reject(promise, reason) {
|
||||
callFunction(resolvingFinished, promise, PROMISE_STATE_REJECTED, reason);
|
||||
}
|
||||
|
||||
function resolvingFinished(state, newValue) {
|
||||
Promise_setState(this, state);
|
||||
Promise_setValue(this, newValue);
|
||||
var deferreds = Promise_getDeferreds(this);
|
||||
for (var i = 0, len = deferreds.length; i < len; i++)
|
||||
deferOrExecute(this, deferreds[i]);
|
||||
Promise_setDeferreds(this, null);
|
||||
}
|
||||
|
||||
function Promise_then(onFulfilled, onRejected) {
|
||||
var promise = this;
|
||||
var newPromise = NewPromise(function(resolve, reject) {
|
||||
deferOrExecute(promise,
|
||||
new Handler(onFulfilled, onRejected, resolve, reject));
|
||||
});
|
||||
runEvents();
|
||||
return newPromise;
|
||||
}
|
@ -91,7 +91,6 @@ enum UnaryOperator {
|
||||
UNOP_BITNOT,
|
||||
UNOP_TYPEOF,
|
||||
UNOP_VOID,
|
||||
UNOP_AWAIT,
|
||||
|
||||
UNOP_LIMIT
|
||||
};
|
||||
@ -161,8 +160,7 @@ static const char* const unopNames[] = {
|
||||
"!", /* UNOP_NOT */
|
||||
"~", /* UNOP_BITNOT */
|
||||
"typeof", /* UNOP_TYPEOF */
|
||||
"void", /* UNOP_VOID */
|
||||
"await" /* UNOP_AWAIT */
|
||||
"void" /* UNOP_VOID */
|
||||
};
|
||||
|
||||
static const char* const nodeTypeNames[] = {
|
||||
@ -562,29 +560,6 @@ class NodeBuilder
|
||||
setResult(node, dst);
|
||||
}
|
||||
|
||||
bool newNode(ASTType type, TokenPos* pos,
|
||||
const char* childName1, HandleValue child1,
|
||||
const char* childName2, HandleValue child2,
|
||||
const char* childName3, HandleValue child3,
|
||||
const char* childName4, HandleValue child4,
|
||||
const char* childName5, HandleValue child5,
|
||||
const char* childName6, HandleValue child6,
|
||||
const char* childName7, HandleValue child7,
|
||||
const char* childName8, HandleValue child8,
|
||||
MutableHandleValue dst) {
|
||||
RootedObject node(cx);
|
||||
return newNode(type, pos, &node) &&
|
||||
setProperty(node, childName1, child1) &&
|
||||
setProperty(node, childName2, child2) &&
|
||||
setProperty(node, childName3, child3) &&
|
||||
setProperty(node, childName4, child4) &&
|
||||
setProperty(node, childName5, child5) &&
|
||||
setProperty(node, childName6, child6) &&
|
||||
setProperty(node, childName7, child7) &&
|
||||
setProperty(node, childName8, child8) &&
|
||||
setResult(node, dst);
|
||||
}
|
||||
|
||||
bool listNode(ASTType type, const char* propName, NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst) {
|
||||
RootedValue array(cx);
|
||||
@ -645,8 +620,8 @@ class NodeBuilder
|
||||
|
||||
bool function(ASTType type, TokenPos* pos,
|
||||
HandleValue id, NodeVector& args, NodeVector& defaults,
|
||||
HandleValue body, HandleValue rest, bool isGenerator, bool isAsync,
|
||||
bool isExpression, MutableHandleValue dst);
|
||||
HandleValue body, HandleValue rest, bool isGenerator, bool isExpression,
|
||||
MutableHandleValue dst);
|
||||
|
||||
bool variableDeclarator(HandleValue id, HandleValue init, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
@ -1782,7 +1757,7 @@ bool
|
||||
NodeBuilder::function(ASTType type, TokenPos* pos,
|
||||
HandleValue id, NodeVector& args, NodeVector& defaults,
|
||||
HandleValue body, HandleValue rest,
|
||||
bool isGenerator, bool isAsync, bool isExpression,
|
||||
bool isGenerator, bool isExpression,
|
||||
MutableHandleValue dst)
|
||||
{
|
||||
RootedValue array(cx), defarray(cx);
|
||||
@ -1792,7 +1767,6 @@ NodeBuilder::function(ASTType type, TokenPos* pos,
|
||||
return false;
|
||||
|
||||
RootedValue isGeneratorVal(cx, BooleanValue(isGenerator));
|
||||
RootedValue isAsyncVal(cx, BooleanValue(isAsync));
|
||||
RootedValue isExpressionVal(cx, BooleanValue(isExpression));
|
||||
|
||||
RootedValue cb(cx, callbacks[type]);
|
||||
@ -1807,7 +1781,6 @@ NodeBuilder::function(ASTType type, TokenPos* pos,
|
||||
"body", body,
|
||||
"rest", rest,
|
||||
"generator", isGeneratorVal,
|
||||
"async", isAsyncVal,
|
||||
"expression", isExpressionVal,
|
||||
dst);
|
||||
}
|
||||
@ -2053,9 +2026,6 @@ ASTSerializer::unop(ParseNodeKind kind, JSOp op)
|
||||
if (kind == PNK_TYPEOFNAME || kind == PNK_TYPEOFEXPR)
|
||||
return UNOP_TYPEOF;
|
||||
|
||||
if (kind == PNK_AWAIT)
|
||||
return UNOP_AWAIT;
|
||||
|
||||
switch (op) {
|
||||
case JSOP_NEG:
|
||||
return UNOP_NEG;
|
||||
@ -3114,7 +3084,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
||||
return leftAssociate(pn, dst);
|
||||
|
||||
case PNK_POW:
|
||||
return rightAssociate(pn, dst);
|
||||
return rightAssociate(pn, dst);
|
||||
|
||||
case PNK_DELETENAME:
|
||||
case PNK_DELETEPROP:
|
||||
@ -3126,7 +3096,6 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
||||
case PNK_NOT:
|
||||
case PNK_BITNOT:
|
||||
case PNK_POS:
|
||||
case PNK_AWAIT:
|
||||
case PNK_NEG: {
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos));
|
||||
|
||||
@ -3596,7 +3565,7 @@ ASTSerializer::function(ParseNode* pn, ASTType type, MutableHandleValue dst)
|
||||
|
||||
// FIXME: Provide more information (legacy generator vs star generator).
|
||||
bool isGenerator = pn->pn_funbox->isGenerator();
|
||||
bool isAsync = pn->pn_funbox->isAsync();
|
||||
|
||||
bool isExpression =
|
||||
#if JS_HAS_EXPR_CLOSURES
|
||||
func->isExprBody();
|
||||
@ -3619,7 +3588,7 @@ ASTSerializer::function(ParseNode* pn, ASTType type, MutableHandleValue dst)
|
||||
rest.setNull();
|
||||
return functionArgsAndBody(pn->pn_body, args, defaults, &body, &rest) &&
|
||||
builder.function(type, &pn->pn_pos, id, args, defaults, body,
|
||||
rest, isGenerator, isAsync, isExpression, dst);
|
||||
rest, isGenerator, isExpression, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -33,15 +33,6 @@
|
||||
// Stores the private WeakMap slot used for WeakSets
|
||||
#define WEAKSET_MAP_SLOT 0
|
||||
|
||||
// Slots for use with promises implementation.
|
||||
#define PROMISE_STATE_SLOT 0
|
||||
#define PROMISE_VALUE_SLOT 1
|
||||
#define PROMISE_DEFERREDS_SLOT 2
|
||||
|
||||
#define PROMISE_STATE_PENDING 0
|
||||
#define PROMISE_STATE_RESOLVED 1
|
||||
#define PROMISE_STATE_REJECTED 2
|
||||
|
||||
#define ITERATOR_SLOT_TARGET 0
|
||||
// Used for collection iterators.
|
||||
#define ITERATOR_SLOT_RANGE 1
|
||||
|
@ -314,7 +314,7 @@ BytecodeCompiler::saveCallerFun(HandleScript evalCaller,
|
||||
MOZ_ASSERT_IF(fun->strict(), options.strictOption);
|
||||
Directives directives(/* strict = */ options.strictOption);
|
||||
ObjectBox* funbox = parser->newFunctionBox(/* fn = */ nullptr, fun, &parseContext,
|
||||
directives, fun->generatorKind(), fun->asyncKind());
|
||||
directives, fun->generatorKind());
|
||||
if (!funbox)
|
||||
return false;
|
||||
|
||||
@ -705,7 +705,7 @@ BytecodeCompiler::compileFunctionBody(MutableHandleFunction fun,
|
||||
ParseNode* fn;
|
||||
do {
|
||||
Directives newDirectives = directives;
|
||||
fn = parser->standaloneFunctionBody(fun, formals, generatorKind, SyncFunction, directives,
|
||||
fn = parser->standaloneFunctionBody(fun, formals, generatorKind, directives,
|
||||
&newDirectives, enclosingStaticScope);
|
||||
if (!fn && !handleParseFailure(newDirectives))
|
||||
return false;
|
||||
@ -865,7 +865,7 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
|
||||
|
||||
Rooted<JSFunction*> fun(cx, lazy->functionNonDelazifying());
|
||||
MOZ_ASSERT(!lazy->isLegacyGenerator());
|
||||
ParseNode* pn = parser.standaloneLazyFunction(fun, lazy->strict(), lazy->generatorKind(), lazy->asyncKind());
|
||||
ParseNode* pn = parser.standaloneLazyFunction(fun, lazy->strict(), lazy->generatorKind());
|
||||
if (!pn)
|
||||
return false;
|
||||
|
||||
|
@ -240,6 +240,7 @@ bool
|
||||
BytecodeEmitter::emit1(JSOp op)
|
||||
{
|
||||
MOZ_ASSERT(checkStrictOrSloppy(op));
|
||||
|
||||
ptrdiff_t offset;
|
||||
if (!emitCheck(1, &offset))
|
||||
return false;
|
||||
@ -2011,7 +2012,6 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
||||
|
||||
case PNK_YIELD_STAR:
|
||||
case PNK_YIELD:
|
||||
case PNK_AWAIT:
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
*answer = true;
|
||||
return true;
|
||||
@ -5857,16 +5857,6 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
||||
MOZ_ASSERT(pn->getOp() == JSOP_LAMBDA);
|
||||
pn->setOp(JSOP_FUNWITHPROTO);
|
||||
}
|
||||
|
||||
if (funbox->isAsync())
|
||||
return emitAsyncWrapper(index, funbox->needsHomeObject());
|
||||
|
||||
if (pn->getOp() == JSOP_DEFFUN) {
|
||||
if (!emitIndex32(JSOP_LAMBDA, index))
|
||||
return false;
|
||||
return emit1(JSOP_DEFFUN);
|
||||
}
|
||||
|
||||
return emitIndex32(pn->getOp(), index);
|
||||
}
|
||||
|
||||
@ -5886,14 +5876,7 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
||||
MOZ_ASSERT(pn->getOp() == JSOP_NOP);
|
||||
MOZ_ASSERT(atBodyLevel());
|
||||
switchToPrologue();
|
||||
if (funbox->isAsync()) {
|
||||
if (!emitAsyncWrapper(index, fun->isMethod()))
|
||||
return false;
|
||||
} else {
|
||||
if (!emitIndex32(JSOP_LAMBDA, index))
|
||||
return false;
|
||||
}
|
||||
if (!emit1(JSOP_DEFFUN))
|
||||
if (!emitIndex32(JSOP_DEFFUN, index))
|
||||
return false;
|
||||
if (!updateSourceCoordNotes(pn->pn_pos.begin))
|
||||
return false;
|
||||
@ -5907,11 +5890,7 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
||||
bi->kind() == Binding::ARGUMENT);
|
||||
MOZ_ASSERT(bi.argOrLocalIndex() < JS_BIT(20));
|
||||
#endif
|
||||
if (funbox->isAsync()) {
|
||||
if (!emitAsyncWrapper(index, false))
|
||||
return false;
|
||||
}
|
||||
else if (!emitIndexOp(JSOP_LAMBDA, index))
|
||||
if (!emitIndexOp(JSOP_LAMBDA, index))
|
||||
return false;
|
||||
MOZ_ASSERT(pn->getOp() == JSOP_GETLOCAL || pn->getOp() == JSOP_GETARG);
|
||||
JSOp setOp = pn->getOp() == JSOP_GETLOCAL ? JSOP_SETLOCAL : JSOP_SETARG;
|
||||
@ -5924,30 +5903,6 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject) {
|
||||
JSAtom* atom = Atomize(cx, "AsyncFunction_wrap", 18);
|
||||
if (!atom)
|
||||
return false;
|
||||
/* TODO Comment */
|
||||
if (needsHomeObject && !emitIndex32(JSOP_LAMBDA, index))
|
||||
return false;
|
||||
if (!emitAtomOp(atom, JSOP_GETINTRINSIC))
|
||||
return false;
|
||||
if (!emit1(JSOP_UNDEFINED))
|
||||
return false;
|
||||
if (needsHomeObject) {
|
||||
if (!emitDupAt(2))
|
||||
return false;
|
||||
} else {
|
||||
if (!emitIndex32(JSOP_LAMBDA, index))
|
||||
return false;
|
||||
}
|
||||
if (!emitCall(JSOP_CALL, 1))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitDo(ParseNode* pn)
|
||||
{
|
||||
@ -7114,12 +7069,7 @@ BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
|
||||
propdef->pn_right->pn_funbox->needsHomeObject())
|
||||
{
|
||||
MOZ_ASSERT(propdef->pn_right->pn_funbox->function()->allowSuperProperty());
|
||||
bool isAsync = propdef->pn_right->pn_funbox->isAsync();
|
||||
if (isAsync && !emit1(JSOP_SWAP))
|
||||
return false;
|
||||
if (!emit2(JSOP_INITHOMEOBJECT, isIndex + isAsync))
|
||||
return false;
|
||||
if (isAsync && !emit1(JSOP_POP))
|
||||
if (!emit2(JSOP_INITHOMEOBJECT, isIndex))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -7738,7 +7688,6 @@ BytecodeEmitter::emitTree(ParseNode* pn)
|
||||
break;
|
||||
|
||||
case PNK_YIELD:
|
||||
case PNK_AWAIT:
|
||||
ok = emitYield(pn);
|
||||
break;
|
||||
|
||||
|
@ -482,8 +482,6 @@ struct BytecodeEmitter
|
||||
bool emitPropOp(ParseNode* pn, JSOp op);
|
||||
bool emitPropIncDec(ParseNode* pn);
|
||||
|
||||
bool emitAsyncWrapper(unsigned index, bool isMethod);
|
||||
|
||||
bool emitComputedPropertyName(ParseNode* computedPropName);
|
||||
|
||||
// Emit bytecode to put operands for a JSOP_GETELEM/CALLELEM/SETELEM/DELELEM
|
||||
|
@ -329,7 +329,6 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
||||
case PNK_CONDITIONAL:
|
||||
case PNK_TYPEOFNAME:
|
||||
case PNK_TYPEOFEXPR:
|
||||
case PNK_AWAIT:
|
||||
case PNK_VOID:
|
||||
case PNK_NOT:
|
||||
case PNK_BITNOT:
|
||||
@ -1854,7 +1853,6 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
||||
return Fold(cx, &pn->pn_left, parser, inGenexpLambda);
|
||||
|
||||
case PNK_YIELD:
|
||||
case PNK_AWAIT:
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
MOZ_ASSERT((pn->pn_right->isKind(PNK_NAME) && !pn->pn_right->isAssigned()) ||
|
||||
(pn->pn_right->isKind(PNK_ASSIGN) &&
|
||||
|
@ -436,11 +436,6 @@ class FullParseHandler
|
||||
return new_<BinaryNode>(PNK_YIELD, op, pos, value, gen);
|
||||
}
|
||||
|
||||
ParseNode* newAwaitExpression(uint32_t begin, ParseNode* value, ParseNode* gen) {
|
||||
TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
|
||||
return new_<BinaryNode>(PNK_AWAIT, JSOP_YIELD, pos, value, gen);
|
||||
}
|
||||
|
||||
ParseNode* newYieldStarExpression(uint32_t begin, ParseNode* value, ParseNode* gen) {
|
||||
TokenPos pos(begin, value->pn_pos.end);
|
||||
return new_<BinaryNode>(PNK_YIELD_STAR, JSOP_NOP, pos, value, gen);
|
||||
|
@ -488,7 +488,6 @@ class NameResolver
|
||||
break;
|
||||
|
||||
case PNK_YIELD:
|
||||
case PNK_AWAIT:
|
||||
MOZ_ASSERT(cur->isArity(PN_BINARY));
|
||||
if (cur->pn_left) {
|
||||
if (!resolve(cur->pn_left, prefix))
|
||||
|
@ -324,8 +324,7 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
||||
// variable, or an assignment of a PNK_GENERATOR node to the '.generator'
|
||||
// local, for a synthesized, prepended initial yield. Yum!
|
||||
case PNK_YIELD_STAR:
|
||||
case PNK_YIELD:
|
||||
case PNK_AWAIT: {
|
||||
case PNK_YIELD: {
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
MOZ_ASSERT(pn->pn_right);
|
||||
MOZ_ASSERT(pn->pn_right->isKind(PNK_NAME) ||
|
||||
@ -702,8 +701,7 @@ Parser<FullParseHandler>::cloneParseTree(ParseNode* opn)
|
||||
RootedFunction fun(context, opn->pn_funbox->function());
|
||||
NULLCHECK(pn->pn_funbox = newFunctionBox(pn, fun, pc,
|
||||
Directives(/* strict = */ opn->pn_funbox->strict()),
|
||||
opn->pn_funbox->generatorKind(),
|
||||
opn->pn_funbox->asyncKind()));
|
||||
opn->pn_funbox->generatorKind()));
|
||||
NULLCHECK(pn->pn_body = cloneParseTree(opn->pn_body));
|
||||
pn->pn_scopecoord = opn->pn_scopecoord;
|
||||
pn->pn_dflags = opn->pn_dflags;
|
||||
|
@ -183,7 +183,6 @@ class PackedScopeCoordinate
|
||||
F(VOID) \
|
||||
F(NOT) \
|
||||
F(BITNOT) \
|
||||
F(AWAIT) \
|
||||
\
|
||||
/* \
|
||||
* Binary operators. \
|
||||
|
@ -645,8 +645,7 @@ Parser<ParseHandler>::newObjectBox(JSObject* obj)
|
||||
template <typename ParseHandler>
|
||||
FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun,
|
||||
JSObject* enclosingStaticScope, ParseContext<ParseHandler>* outerpc,
|
||||
Directives directives, bool extraWarnings, GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind)
|
||||
Directives directives, bool extraWarnings, GeneratorKind generatorKind)
|
||||
: ObjectBox(fun, traceListHead),
|
||||
SharedContext(cx, directives, extraWarnings),
|
||||
bindings(),
|
||||
@ -665,8 +664,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct
|
||||
usesArguments(false),
|
||||
usesApply(false),
|
||||
usesThis(false),
|
||||
funCxFlags(),
|
||||
_asyncKind(asyncKind)
|
||||
funCxFlags()
|
||||
{
|
||||
// Functions created at parse time may be set singleton after parsing and
|
||||
// baked into JIT code, so they must be allocated tenured. They are held by
|
||||
@ -680,7 +678,6 @@ Parser<ParseHandler>::newFunctionBox(Node fn, JSFunction* fun,
|
||||
ParseContext<ParseHandler>* outerpc,
|
||||
Directives inheritedDirectives,
|
||||
GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind,
|
||||
JSObject* enclosingStaticScope)
|
||||
{
|
||||
MOZ_ASSERT_IF(outerpc, enclosingStaticScope == outerpc->innermostStaticScope());
|
||||
@ -696,7 +693,7 @@ Parser<ParseHandler>::newFunctionBox(Node fn, JSFunction* fun,
|
||||
FunctionBox* funbox =
|
||||
alloc.new_<FunctionBox>(context, traceListHead, fun, enclosingStaticScope, outerpc,
|
||||
inheritedDirectives, options().extraWarningsOption,
|
||||
generatorKind, asyncKind);
|
||||
generatorKind);
|
||||
if (!funbox) {
|
||||
ReportOutOfMemory(context);
|
||||
return nullptr;
|
||||
@ -839,9 +836,7 @@ Parser<ParseHandler>::checkStrictBinding(PropertyName* name, Node pn)
|
||||
if (!pc->sc->needStrictChecks())
|
||||
return true;
|
||||
|
||||
if (name == context->names().eval || name == context->names().arguments ||
|
||||
(IsKeyword(name) && name != context->names().await))
|
||||
{
|
||||
if (name == context->names().eval || name == context->names().arguments || IsKeyword(name)) {
|
||||
JSAutoByteString bytes;
|
||||
if (!AtomToPrintableString(context, name, &bytes))
|
||||
return false;
|
||||
@ -871,10 +866,7 @@ Parser<ParseHandler>::standaloneModule(HandleModuleObject module)
|
||||
if (!modulepc.init(*this))
|
||||
return null();
|
||||
|
||||
bool awaitIsKeyword = tokenStream.getAwaitIsKeyword();
|
||||
tokenStream.setAwaitIsKeyword(true);
|
||||
ParseNode* pn = statements(YieldIsKeyword);
|
||||
tokenStream.setAwaitIsKeyword(awaitIsKeyword);
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
@ -949,7 +941,6 @@ ParseNode*
|
||||
Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun,
|
||||
Handle<PropertyNameVector> formals,
|
||||
GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind,
|
||||
Directives inheritedDirectives,
|
||||
Directives* newDirectives,
|
||||
HandleObject enclosingStaticScope)
|
||||
@ -966,7 +957,7 @@ Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun,
|
||||
fn->pn_body = argsbody;
|
||||
|
||||
FunctionBox* funbox = newFunctionBox(fn, fun, inheritedDirectives, generatorKind,
|
||||
asyncKind, enclosingStaticScope);
|
||||
enclosingStaticScope);
|
||||
if (!funbox)
|
||||
return null();
|
||||
funbox->length = fun->nargs() - fun->hasRest();
|
||||
@ -1415,8 +1406,7 @@ struct BindData
|
||||
template <typename ParseHandler>
|
||||
JSFunction*
|
||||
Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
HandleObject proto)
|
||||
GeneratorKind generatorKind, HandleObject proto)
|
||||
{
|
||||
MOZ_ASSERT_IF(kind == Statement, atom != nullptr);
|
||||
|
||||
@ -1462,10 +1452,6 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
|
||||
: JSFunction::INTERPRETED_GENERATOR);
|
||||
}
|
||||
|
||||
// We store the async wrapper in a slot for later access.
|
||||
if (asyncKind == AsyncFunction)
|
||||
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
|
||||
|
||||
fun = NewFunctionWithProto(context, nullptr, 0, flags, nullptr, atom, proto,
|
||||
allocKind, TenuredObject);
|
||||
if (!fun)
|
||||
@ -1847,7 +1833,7 @@ Parser<ParseHandler>::bindDestructuringArg(BindData<ParseHandler>* data,
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::functionArguments(YieldHandling yieldHandling, FunctionSyntaxKind kind,
|
||||
FunctionAsyncKind asyncKind, Node funcpn, bool* hasRest)
|
||||
Node funcpn, bool* hasRest)
|
||||
{
|
||||
FunctionBox* funbox = pc->sc->asFunctionBox();
|
||||
|
||||
@ -2035,20 +2021,11 @@ Parser<ParseHandler>::functionArguments(YieldHandling yieldHandling, FunctionSyn
|
||||
// before the first default argument.
|
||||
funbox->length = pc->numArgs() - 1;
|
||||
}
|
||||
bool awaitIsKeyword;
|
||||
if (asyncKind == AsyncFunction) {
|
||||
awaitIsKeyword = tokenStream.getAwaitIsKeyword();
|
||||
tokenStream.setAwaitIsKeyword(true);
|
||||
}
|
||||
Node def_expr = assignExprWithoutYieldAndAwait(yieldHandling, JSMSG_YIELD_IN_DEFAULT);
|
||||
|
||||
Node def_expr = assignExprWithoutYield(yieldHandling, JSMSG_YIELD_IN_DEFAULT);
|
||||
if (!def_expr)
|
||||
return false;
|
||||
if (!handler.setLastFunctionArgumentDefault(funcpn, def_expr))
|
||||
return false;
|
||||
if (asyncKind == AsyncFunction) {
|
||||
tokenStream.setAwaitIsKeyword(awaitIsKeyword);
|
||||
}
|
||||
}
|
||||
|
||||
if (parenFreeArrow || IsSetterKind(kind))
|
||||
@ -2233,7 +2210,7 @@ Parser<FullParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
|
||||
RootedFunction fun(context, handler.nextLazyInnerFunction());
|
||||
MOZ_ASSERT(!fun->isLegacyGenerator());
|
||||
FunctionBox* funbox = newFunctionBox(pn, fun, pc, Directives(/* strict = */ false),
|
||||
fun->generatorKind(), fun->asyncKind());
|
||||
fun->generatorKind());
|
||||
if (!funbox)
|
||||
return false;
|
||||
|
||||
@ -2442,11 +2419,9 @@ template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::functionDef(InHandling inHandling, YieldHandling yieldHandling,
|
||||
HandlePropertyName funName, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
InvokedPrediction invoked)
|
||||
GeneratorKind generatorKind, InvokedPrediction invoked)
|
||||
{
|
||||
MOZ_ASSERT_IF(kind == Statement, funName);
|
||||
MOZ_ASSERT_IF(asyncKind == AsyncFunction, generatorKind == StarGenerator);
|
||||
|
||||
/* Make a TOK_FUNCTION node. */
|
||||
Node pn = handler.newFunctionDefinition();
|
||||
@ -2473,7 +2448,7 @@ Parser<ParseHandler>::functionDef(InHandling inHandling, YieldHandling yieldHand
|
||||
if (!proto)
|
||||
return null();
|
||||
}
|
||||
RootedFunction fun(context, newFunction(funName, kind, generatorKind, asyncKind, proto));
|
||||
RootedFunction fun(context, newFunction(funName, kind, generatorKind, proto));
|
||||
if (!fun)
|
||||
return null();
|
||||
|
||||
@ -2488,8 +2463,8 @@ Parser<ParseHandler>::functionDef(InHandling inHandling, YieldHandling yieldHand
|
||||
tokenStream.tell(&start);
|
||||
|
||||
while (true) {
|
||||
if (functionArgsAndBody(inHandling, pn, fun, kind, generatorKind, asyncKind,
|
||||
directives, &newDirectives))
|
||||
if (functionArgsAndBody(inHandling, pn, fun, kind, generatorKind, directives,
|
||||
&newDirectives))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -2559,7 +2534,6 @@ Parser<SyntaxParseHandler>::finishFunctionDefinition(Node pn, FunctionBox* funbo
|
||||
if (pc->sc->strict())
|
||||
lazy->setStrict();
|
||||
lazy->setGeneratorKind(funbox->generatorKind());
|
||||
lazy->setAsyncKind(funbox->asyncKind());
|
||||
if (funbox->usesArguments && funbox->usesApply && funbox->usesThis)
|
||||
lazy->setUsesArgumentsApplyAndThis();
|
||||
if (funbox->isDerivedClassConstructor())
|
||||
@ -2577,14 +2551,13 @@ bool
|
||||
Parser<FullParseHandler>::functionArgsAndBody(InHandling inHandling, ParseNode* pn,
|
||||
HandleFunction fun, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind,
|
||||
Directives inheritedDirectives,
|
||||
Directives* newDirectives)
|
||||
{
|
||||
ParseContext<FullParseHandler>* outerpc = pc;
|
||||
|
||||
// Create box for fun->object early to protect against last-ditch GC.
|
||||
FunctionBox* funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind, asyncKind);
|
||||
FunctionBox* funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind);
|
||||
if (!funbox)
|
||||
return false;
|
||||
|
||||
@ -2683,14 +2656,13 @@ bool
|
||||
Parser<SyntaxParseHandler>::functionArgsAndBody(InHandling inHandling, Node pn, HandleFunction fun,
|
||||
FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind,
|
||||
Directives inheritedDirectives,
|
||||
Directives* newDirectives)
|
||||
{
|
||||
ParseContext<SyntaxParseHandler>* outerpc = pc;
|
||||
|
||||
// Create box for fun->object early to protect against last-ditch GC.
|
||||
FunctionBox* funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind, asyncKind);
|
||||
FunctionBox* funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind);
|
||||
if (!funbox)
|
||||
return false;
|
||||
|
||||
@ -2706,6 +2678,7 @@ Parser<SyntaxParseHandler>::functionArgsAndBody(InHandling inHandling, Node pn,
|
||||
|
||||
if (!leaveFunction(pn, outerpc, kind))
|
||||
return false;
|
||||
|
||||
// This is a lazy function inner to another lazy function. Remember the
|
||||
// inner function so that if the outer function is eventually parsed we do
|
||||
// not need any further parsing or processing of the inner function.
|
||||
@ -2734,8 +2707,7 @@ Parser<ParseHandler>::appendToCallSiteObj(Node callSiteObj)
|
||||
template <>
|
||||
ParseNode*
|
||||
Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, bool strict,
|
||||
GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind)
|
||||
GeneratorKind generatorKind)
|
||||
{
|
||||
MOZ_ASSERT(checkOptionsCalled);
|
||||
|
||||
@ -2750,7 +2722,7 @@ Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, bool strict
|
||||
|
||||
RootedObject enclosing(context, fun->lazyScript()->enclosingScope());
|
||||
Directives directives(/* strict = */ strict);
|
||||
FunctionBox* funbox = newFunctionBox(pn, fun, directives, generatorKind, asyncKind, enclosing);
|
||||
FunctionBox* funbox = newFunctionBox(pn, fun, directives, generatorKind, enclosing);
|
||||
if (!funbox)
|
||||
return null();
|
||||
funbox->length = fun->nargs() - fun->hasRest();
|
||||
@ -2808,12 +2780,12 @@ Parser<ParseHandler>::functionArgsAndBodyGeneric(InHandling inHandling,
|
||||
// function without concern for conversion to strict mode, use of lazy
|
||||
// parsing and such.
|
||||
|
||||
FunctionBox* funbox = pc->sc->asFunctionBox();
|
||||
|
||||
bool hasRest;
|
||||
if (!functionArguments(yieldHandling, kind, funbox->asyncKind(), pn, &hasRest))
|
||||
if (!functionArguments(yieldHandling, kind, pn, &hasRest))
|
||||
return false;
|
||||
|
||||
FunctionBox* funbox = pc->sc->asFunctionBox();
|
||||
|
||||
fun->setArgCount(pc->numArgs());
|
||||
if (hasRest)
|
||||
fun->setHasRest();
|
||||
@ -2857,12 +2829,9 @@ Parser<ParseHandler>::functionArgsAndBodyGeneric(InHandling inHandling,
|
||||
#endif
|
||||
}
|
||||
|
||||
bool beforeAwaitIsKeyword = tokenStream.getAwaitIsKeyword();
|
||||
tokenStream.setAwaitIsKeyword(funbox->isAsync());
|
||||
Node body = functionBody(inHandling, yieldHandling, kind, bodyType);
|
||||
if (!body)
|
||||
return false;
|
||||
tokenStream.setAwaitIsKeyword(beforeAwaitIsKeyword);
|
||||
|
||||
if ((kind != Method && !IsConstructorKind(kind)) && fun->name() &&
|
||||
!checkStrictBinding(fun->name(), pn))
|
||||
@ -2908,8 +2877,7 @@ Parser<ParseHandler>::checkYieldNameValidity()
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::functionStmt(YieldHandling yieldHandling, DefaultHandling defaultHandling,
|
||||
FunctionAsyncKind asyncKind)
|
||||
Parser<ParseHandler>::functionStmt(YieldHandling yieldHandling, DefaultHandling defaultHandling)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
|
||||
|
||||
@ -2920,10 +2888,6 @@ Parser<ParseHandler>::functionStmt(YieldHandling yieldHandling, DefaultHandling
|
||||
return null();
|
||||
|
||||
if (tt == TOK_MUL) {
|
||||
if (asyncKind != SyncFunction) {
|
||||
report(ParseError, false, null(), JSMSG_ASYNC_GENERATOR);
|
||||
return null();
|
||||
}
|
||||
generatorKind = StarGenerator;
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return null();
|
||||
@ -2949,14 +2913,12 @@ Parser<ParseHandler>::functionStmt(YieldHandling yieldHandling, DefaultHandling
|
||||
!report(ParseStrictError, pc->sc->strict(), null(), JSMSG_STRICT_FUNCTION_STATEMENT))
|
||||
return null();
|
||||
|
||||
if (asyncKind == AsyncFunction)
|
||||
generatorKind = StarGenerator;
|
||||
return functionDef(InAllowed, yieldHandling, name, Statement, generatorKind, asyncKind);
|
||||
return functionDef(InAllowed, yieldHandling, name, Statement, generatorKind);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::functionExpr(InvokedPrediction invoked, FunctionAsyncKind asyncKind)
|
||||
Parser<ParseHandler>::functionExpr(InvokedPrediction invoked)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
|
||||
|
||||
@ -2966,10 +2928,6 @@ Parser<ParseHandler>::functionExpr(InvokedPrediction invoked, FunctionAsyncKind
|
||||
return null();
|
||||
|
||||
if (tt == TOK_MUL) {
|
||||
if (asyncKind != SyncFunction) {
|
||||
report(ParseError, false, null(), JSMSG_ASYNC_GENERATOR);
|
||||
return null();
|
||||
}
|
||||
generatorKind = StarGenerator;
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return null();
|
||||
@ -2986,10 +2944,8 @@ Parser<ParseHandler>::functionExpr(InvokedPrediction invoked, FunctionAsyncKind
|
||||
tokenStream.ungetToken();
|
||||
}
|
||||
|
||||
if (asyncKind == AsyncFunction)
|
||||
generatorKind = StarGenerator;
|
||||
YieldHandling yieldHandling = generatorKind != NotGenerator ? YieldIsKeyword : YieldIsName;
|
||||
return functionDef(InAllowed, yieldHandling, name, Expression, generatorKind, asyncKind, invoked);
|
||||
return functionDef(InAllowed, yieldHandling, name, Expression, generatorKind, invoked);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4977,7 +4933,7 @@ Parser<FullParseHandler>::exportDeclaration()
|
||||
}
|
||||
|
||||
case TOK_FUNCTION:
|
||||
kid = functionStmt(YieldIsKeyword, NameRequired, SyncFunction);
|
||||
kid = functionStmt(YieldIsKeyword, NameRequired);
|
||||
if (!kid)
|
||||
return null();
|
||||
|
||||
@ -5027,7 +4983,7 @@ Parser<FullParseHandler>::exportDeclaration()
|
||||
ParseNode* binding = nullptr;
|
||||
switch (tt) {
|
||||
case TOK_FUNCTION:
|
||||
kid = functionStmt(YieldIsKeyword, AllowDefaultName, SyncFunction);
|
||||
kid = functionStmt(YieldIsKeyword, AllowDefaultName);
|
||||
if (!kid)
|
||||
return null();
|
||||
break;
|
||||
@ -6012,7 +5968,7 @@ Parser<ParseHandler>::returnStatement(YieldHandling yieldHandling)
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::newYieldExpression(uint32_t begin, typename ParseHandler::Node expr,
|
||||
bool isYieldStar, bool isAwait)
|
||||
bool isYieldStar)
|
||||
{
|
||||
Node generator = newName(context->names().dotGenerator);
|
||||
if (!generator)
|
||||
@ -6021,9 +5977,7 @@ Parser<ParseHandler>::newYieldExpression(uint32_t begin, typename ParseHandler::
|
||||
return null();
|
||||
if (isYieldStar)
|
||||
return handler.newYieldStarExpression(begin, expr, generator);
|
||||
if (isAwait)
|
||||
return handler.newAwaitExpression(begin, expr, generator);
|
||||
return handler.newYieldExpression(begin, expr, generator, JSOP_YIELD);
|
||||
return handler.newYieldExpression(begin, expr, generator);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
@ -6476,7 +6430,6 @@ JSOpFromPropertyType(PropertyType propType)
|
||||
case PropertyType::Normal:
|
||||
case PropertyType::Method:
|
||||
case PropertyType::GeneratorMethod:
|
||||
case PropertyType::AsyncMethod:
|
||||
case PropertyType::Constructor:
|
||||
case PropertyType::DerivedConstructor:
|
||||
return JSOP_INITPROP;
|
||||
@ -6498,8 +6451,8 @@ FunctionSyntaxKindFromPropertyType(PropertyType propType)
|
||||
case PropertyType::SetterNoExpressionClosure:
|
||||
return SetterNoExpressionClosure;
|
||||
case PropertyType::Method:
|
||||
return Method;
|
||||
case PropertyType::GeneratorMethod:
|
||||
case PropertyType::AsyncMethod:
|
||||
return Method;
|
||||
case PropertyType::Constructor:
|
||||
return ClassConstructor;
|
||||
@ -6513,15 +6466,7 @@ FunctionSyntaxKindFromPropertyType(PropertyType propType)
|
||||
static GeneratorKind
|
||||
GeneratorKindFromPropertyType(PropertyType propType)
|
||||
{
|
||||
return (propType == PropertyType::GeneratorMethod ||
|
||||
propType == PropertyType::AsyncMethod)
|
||||
? StarGenerator : NotGenerator;
|
||||
}
|
||||
|
||||
static FunctionAsyncKind
|
||||
AsyncKindFromPropertyType(PropertyType propType)
|
||||
{
|
||||
return propType == PropertyType::AsyncMethod ? AsyncFunction : SyncFunction;
|
||||
return propType == PropertyType::GeneratorMethod ? StarGenerator : NotGenerator;
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -6635,7 +6580,6 @@ Parser<FullParseHandler>::classDefinition(YieldHandling yieldHandling,
|
||||
|
||||
if (propType != PropertyType::Getter && propType != PropertyType::Setter &&
|
||||
propType != PropertyType::Method && propType != PropertyType::GeneratorMethod &&
|
||||
propType != PropertyType::AsyncMethod &&
|
||||
propType != PropertyType::Constructor && propType != PropertyType::DerivedConstructor)
|
||||
{
|
||||
report(ParseError, false, null(), JSMSG_BAD_METHOD_DEF);
|
||||
@ -6804,19 +6748,6 @@ Parser<ParseHandler>::statement(YieldHandling yieldHandling, bool canHaveDirecti
|
||||
|
||||
case TOK_NAME: {
|
||||
TokenKind next;
|
||||
|
||||
#ifdef JS_HAS_ASYNC_FUNCS
|
||||
if (tokenStream.currentName() == context->names().async) {
|
||||
TokenKind nextSameLine = TOK_EOF;
|
||||
if (!tokenStream.peekTokenSameLine(&nextSameLine))
|
||||
return null();
|
||||
if (nextSameLine == TOK_FUNCTION) {
|
||||
tokenStream.consumeKnownToken(TOK_FUNCTION);
|
||||
return functionStmt(yieldHandling, NameRequired, AsyncFunction);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!tokenStream.peekToken(&next))
|
||||
return null();
|
||||
if (next == TOK_COLON)
|
||||
@ -6891,7 +6822,7 @@ Parser<ParseHandler>::statement(YieldHandling yieldHandling, bool canHaveDirecti
|
||||
|
||||
// HoistableDeclaration[?Yield]
|
||||
case TOK_FUNCTION:
|
||||
return functionStmt(yieldHandling, NameRequired, SyncFunction);
|
||||
return functionStmt(yieldHandling, NameRequired);
|
||||
|
||||
// ClassDeclaration[?Yield]
|
||||
case TOK_CLASS:
|
||||
@ -7205,19 +7136,6 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
|
||||
bool endsExpr;
|
||||
|
||||
if (tt == TOK_NAME) {
|
||||
#ifdef JS_HAS_ASYNC_FUNCS
|
||||
if (tokenStream.currentName() == context->names().async) {
|
||||
TokenKind nextSameLine = TOK_EOF;
|
||||
if (!tokenStream.peekTokenSameLine(&nextSameLine))
|
||||
return null();
|
||||
|
||||
if (nextSameLine == TOK_FUNCTION) {
|
||||
tokenStream.consumeKnownToken(TOK_FUNCTION);
|
||||
return functionExpr(PredictUninvoked, AsyncFunction);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!tokenStream.nextTokenEndsExpr(&endsExpr))
|
||||
return null();
|
||||
if (endsExpr)
|
||||
@ -7238,14 +7156,8 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
|
||||
return stringLiteral();
|
||||
}
|
||||
|
||||
if (tt == TOK_YIELD && yieldExpressionsSupported()) {
|
||||
if (pc->isAsync()) {
|
||||
report(ParseError, false, null(), JSMSG_YIELD_IN_ASYNC);
|
||||
return null();
|
||||
}
|
||||
if (tt == TOK_YIELD && yieldExpressionsSupported())
|
||||
return yieldExpression(inHandling);
|
||||
}
|
||||
|
||||
|
||||
tokenStream.ungetToken();
|
||||
|
||||
@ -7305,7 +7217,7 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
|
||||
return null();
|
||||
}
|
||||
|
||||
Node arrowFunc = functionDef(inHandling, yieldHandling, nullptr, Arrow, NotGenerator, SyncFunction);
|
||||
Node arrowFunc = functionDef(inHandling, yieldHandling, nullptr, Arrow, NotGenerator);
|
||||
if (!arrowFunc)
|
||||
return null();
|
||||
|
||||
@ -7567,27 +7479,6 @@ Parser<ParseHandler>::unaryExpr(YieldHandling yieldHandling, InvokedPrediction i
|
||||
return handler.newDelete(begin, expr);
|
||||
}
|
||||
|
||||
case TOK_AWAIT:
|
||||
{
|
||||
#ifndef JS_HAS_ASYNC_FUNCS
|
||||
MOZ_CRASH("Should not see TOK_AWAIT without async function support");
|
||||
#endif
|
||||
|
||||
TokenKind nextSameLine = TOK_EOF;
|
||||
|
||||
if (!tokenStream.peekTokenSameLine(&nextSameLine, TokenStream::Operand))
|
||||
return null();
|
||||
if (nextSameLine != TOK_EOL) {
|
||||
Node kid = unaryExpr(yieldHandling);
|
||||
if (!kid)
|
||||
return null();
|
||||
return newYieldExpression(begin, kid, /* isYieldStar = */ false, /* isAwait = */ true);
|
||||
} else {
|
||||
report(ParseError, false, null(), JSMSG_LINE_BREAK_AFTER_AWAIT);
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
||||
default: {
|
||||
Node pn = memberExpr(yieldHandling, tt, /* allowCallSyntax = */ true, invoked);
|
||||
if (!pn)
|
||||
@ -8165,13 +8056,13 @@ Parser<ParseHandler>::generatorComprehensionLambda(GeneratorKind comprehensionKi
|
||||
}
|
||||
|
||||
RootedFunction fun(context, newFunction(/* atom = */ nullptr, Expression,
|
||||
comprehensionKind, SyncFunction, proto));
|
||||
comprehensionKind, proto));
|
||||
if (!fun)
|
||||
return null();
|
||||
|
||||
// Create box for fun->object early to root it.
|
||||
Directives directives(/* strict = */ outerpc->sc->strict());
|
||||
FunctionBox* genFunbox = newFunctionBox(genfn, fun, outerpc, directives, comprehensionKind, SyncFunction);
|
||||
FunctionBox* genFunbox = newFunctionBox(genfn, fun, outerpc, directives, comprehensionKind);
|
||||
if (!genFunbox)
|
||||
return null();
|
||||
|
||||
@ -8499,16 +8390,8 @@ Parser<ParseHandler>::generatorComprehension(uint32_t begin)
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::assignExprWithoutYieldAndAwait(YieldHandling yieldHandling, unsigned msg)
|
||||
Parser<ParseHandler>::assignExprWithoutYield(YieldHandling yieldHandling, unsigned msg)
|
||||
{
|
||||
TokenKind tt;
|
||||
if (!tokenStream.peekToken(&tt, TokenStream::Operand))
|
||||
return null();
|
||||
|
||||
if (tt == TOK_AWAIT) {
|
||||
report(ParseError, false, null(), JSMSG_AWAIT_IN_DEFAULT);
|
||||
return null();
|
||||
}
|
||||
uint32_t startYieldOffset = pc->lastYieldOffset;
|
||||
Node res = assignExpr(InAllowed, yieldHandling);
|
||||
if (res && pc->lastYieldOffset != startYieldOffset) {
|
||||
@ -9040,32 +8923,12 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, Node propList,
|
||||
MOZ_ASSERT(ltok != TOK_RC);
|
||||
|
||||
bool isGenerator = false;
|
||||
bool isAsync = false;
|
||||
|
||||
if (ltok == TOK_MUL) {
|
||||
isGenerator = true;
|
||||
if (!tokenStream.getToken(<ok, TokenStream::KeywordIsName))
|
||||
return null();
|
||||
}
|
||||
|
||||
if (ltok == TOK_NAME && tokenStream.currentName() == context->names().async) {
|
||||
TokenKind tt;
|
||||
if (!tokenStream.getToken(&tt, TokenStream::KeywordIsName))
|
||||
return null();
|
||||
if (tt != TOK_LP && tt != TOK_COLON) {
|
||||
isAsync = true;
|
||||
ltok = tt;
|
||||
} else {
|
||||
tokenStream.ungetToken();
|
||||
tokenStream.addModifierException(TokenStream::NoneIsKeywordIsName);
|
||||
}
|
||||
}
|
||||
|
||||
if (isAsync && isGenerator) {
|
||||
report(ParseError, false, null(), JSMSG_ASYNC_GENERATOR);
|
||||
return null();
|
||||
}
|
||||
|
||||
propAtom.set(nullptr);
|
||||
Node propName;
|
||||
switch (ltok) {
|
||||
@ -9087,7 +8950,7 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, Node propList,
|
||||
case TOK_NAME: {
|
||||
propAtom.set(tokenStream.currentName());
|
||||
// Do not look for accessor syntax on generators
|
||||
if (isGenerator || isAsync ||
|
||||
if (isGenerator ||
|
||||
!(propAtom.get() == context->names().get ||
|
||||
propAtom.get() == context->names().set))
|
||||
{
|
||||
@ -9204,8 +9067,7 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, Node propList,
|
||||
|
||||
if (tt == TOK_LP) {
|
||||
tokenStream.ungetToken();
|
||||
*propType = isGenerator ? PropertyType::GeneratorMethod :
|
||||
(isAsync ? PropertyType::AsyncMethod : PropertyType::Method);
|
||||
*propType = isGenerator ? PropertyType::GeneratorMethod : PropertyType::Method;
|
||||
return propName;
|
||||
}
|
||||
|
||||
@ -9352,8 +9214,7 @@ Parser<ParseHandler>::methodDefinition(YieldHandling yieldHandling, PropertyType
|
||||
{
|
||||
FunctionSyntaxKind kind = FunctionSyntaxKindFromPropertyType(propType);
|
||||
GeneratorKind generatorKind = GeneratorKindFromPropertyType(propType);
|
||||
FunctionAsyncKind asyncKind = AsyncKindFromPropertyType(propType);
|
||||
return functionDef(InAllowed, yieldHandling, funName, kind, generatorKind, asyncKind);
|
||||
return functionDef(InAllowed, yieldHandling, funName, kind, generatorKind);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
@ -9462,8 +9323,7 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TokenKind tt,
|
||||
case TOK_YIELD:
|
||||
if (!checkYieldNameValidity())
|
||||
return null();
|
||||
|
||||
// Fall through.
|
||||
// Fall through.
|
||||
case TOK_NAME:
|
||||
return identifierName(yieldHandling);
|
||||
|
||||
|
@ -127,8 +127,6 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
|
||||
bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
|
||||
bool isStarGenerator() const { return generatorKind() == StarGenerator; }
|
||||
|
||||
bool isAsync() const { return sc->isFunctionBox() && sc->asFunctionBox()->isAsync(); }
|
||||
|
||||
bool isArrowFunction() const {
|
||||
return sc->isFunctionBox() && sc->asFunctionBox()->function()->isArrow();
|
||||
}
|
||||
@ -365,7 +363,6 @@ enum class PropertyType {
|
||||
SetterNoExpressionClosure,
|
||||
Method,
|
||||
GeneratorMethod,
|
||||
AsyncMethod,
|
||||
Constructor,
|
||||
DerivedConstructor
|
||||
};
|
||||
@ -507,26 +504,22 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
ObjectBox* newObjectBox(JSObject* obj);
|
||||
FunctionBox* newFunctionBox(Node fn, JSFunction* fun, ParseContext<ParseHandler>* outerpc,
|
||||
Directives directives, GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind,
|
||||
JSObject* enclosingStaticScope);
|
||||
|
||||
// Use when the funbox is the outermost.
|
||||
FunctionBox* newFunctionBox(Node fn, HandleFunction fun, Directives directives,
|
||||
GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind,
|
||||
HandleObject enclosingStaticScope)
|
||||
GeneratorKind generatorKind, HandleObject enclosingStaticScope)
|
||||
{
|
||||
return newFunctionBox(fn, fun, nullptr, directives, generatorKind,
|
||||
asyncKind, enclosingStaticScope);
|
||||
enclosingStaticScope);
|
||||
}
|
||||
|
||||
// Use when the funbox should be linked to the outerpc's innermost scope.
|
||||
FunctionBox* newFunctionBox(Node fn, HandleFunction fun, ParseContext<ParseHandler>* outerpc,
|
||||
Directives directives, GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind)
|
||||
Directives directives, GeneratorKind generatorKind)
|
||||
{
|
||||
RootedObject enclosing(context, outerpc->innermostStaticScope());
|
||||
return newFunctionBox(fn, fun, outerpc, directives, generatorKind, asyncKind, enclosing);
|
||||
return newFunctionBox(fn, fun, outerpc, directives, generatorKind, enclosing);
|
||||
}
|
||||
|
||||
ModuleBox* newModuleBox(Node pn, HandleModuleObject module);
|
||||
@ -536,7 +529,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
* a function expression).
|
||||
*/
|
||||
JSFunction* newFunction(HandleAtom atom, FunctionSyntaxKind kind, GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind, HandleObject proto);
|
||||
HandleObject proto);
|
||||
|
||||
bool generateBlockId(JSObject* staticScope, uint32_t* blockIdOut) {
|
||||
if (blockScopes.length() == StmtInfoPC::BlockIdLimit) {
|
||||
@ -575,7 +568,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
TokenKind* ttp);
|
||||
|
||||
inline Node newName(PropertyName* name);
|
||||
inline Node newYieldExpression(uint32_t begin, Node expr, bool isYieldStar = false, bool isAsync = false);
|
||||
inline Node newYieldExpression(uint32_t begin, Node expr, bool isYieldStar = false);
|
||||
|
||||
inline bool abortIfSyntaxParser();
|
||||
|
||||
@ -596,14 +589,13 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
// Parse a function, given only its body. Used for the Function and
|
||||
// Generator constructors.
|
||||
Node standaloneFunctionBody(HandleFunction fun, Handle<PropertyNameVector> formals,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
GeneratorKind generatorKind,
|
||||
Directives inheritedDirectives, Directives* newDirectives,
|
||||
HandleObject enclosingStaticScope);
|
||||
|
||||
// Parse a function, given only its arguments and body. Used for lazily
|
||||
// parsed functions.
|
||||
Node standaloneLazyFunction(HandleFunction fun, bool strict, GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind);
|
||||
Node standaloneLazyFunction(HandleFunction fun, bool strict, GeneratorKind generatorKind);
|
||||
|
||||
/*
|
||||
* Parse a function body. Pass StatementListBody if the body is a list of
|
||||
@ -655,10 +647,8 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
* Some parsers have two versions: an always-inlined version (with an 'i'
|
||||
* suffix) and a never-inlined version (with an 'n' suffix).
|
||||
*/
|
||||
Node functionStmt(YieldHandling yieldHandling,
|
||||
DefaultHandling defaultHandling, FunctionAsyncKind asyncKind);
|
||||
Node functionExpr(InvokedPrediction invoked = PredictUninvoked,
|
||||
FunctionAsyncKind asyncKind = SyncFunction);
|
||||
Node functionStmt(YieldHandling yieldHandling, DefaultHandling defaultHandling);
|
||||
Node functionExpr(InvokedPrediction invoked = PredictUninvoked);
|
||||
Node statements(YieldHandling yieldHandling);
|
||||
|
||||
Node blockStatement(YieldHandling yieldHandling);
|
||||
@ -691,7 +681,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
Node assignExpr(InHandling inHandling, YieldHandling yieldHandling,
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
Node assignExprWithoutYieldAndAwait(YieldHandling yieldHandling, unsigned err);
|
||||
Node assignExprWithoutYield(YieldHandling yieldHandling, unsigned err);
|
||||
Node yieldExpression(InHandling inHandling);
|
||||
Node condExpr1(InHandling inHandling, YieldHandling yieldHandling,
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
@ -715,13 +705,13 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
* Additional JS parsers.
|
||||
*/
|
||||
bool functionArguments(YieldHandling yieldHandling, FunctionSyntaxKind kind,
|
||||
FunctionAsyncKind asyncKind, Node funcpn, bool* hasRest);
|
||||
Node funcpn, bool* hasRest);
|
||||
|
||||
Node functionDef(InHandling inHandling, YieldHandling uieldHandling, HandlePropertyName name,
|
||||
FunctionSyntaxKind kind, GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
FunctionSyntaxKind kind, GeneratorKind generatorKind,
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
bool functionArgsAndBody(InHandling inHandling, Node pn, HandleFunction fun,
|
||||
FunctionSyntaxKind kind, GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
FunctionSyntaxKind kind, GeneratorKind generatorKind,
|
||||
Directives inheritedDirectives, Directives* newDirectives);
|
||||
|
||||
Node unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind, JSOp op, uint32_t begin);
|
||||
@ -832,7 +822,6 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
// Top-level entrypoint into destructuring pattern checking/name-analyzing.
|
||||
bool checkDestructuringPattern(BindData<ParseHandler>* data, Node pattern);
|
||||
|
||||
|
||||
// Recursive methods for checking/name-analyzing subcomponents of a
|
||||
// destructuring pattern. The array/object methods *must* be passed arrays
|
||||
// or objects. The name method may be passed anything but will report an
|
||||
|
@ -301,13 +301,10 @@ class FunctionBox : public ObjectBox, public SharedContext
|
||||
|
||||
FunctionContextFlags funCxFlags;
|
||||
|
||||
FunctionAsyncKind _asyncKind;
|
||||
|
||||
template <typename ParseHandler>
|
||||
FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun,
|
||||
JSObject* enclosingStaticScope, ParseContext<ParseHandler>* pc,
|
||||
Directives directives, bool extraWarnings, GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind);
|
||||
Directives directives, bool extraWarnings, GeneratorKind generatorKind);
|
||||
|
||||
ObjectBox* toObjectBox() override { return this; }
|
||||
JSFunction* function() const { return &object->as<JSFunction>(); }
|
||||
@ -319,8 +316,6 @@ class FunctionBox : public ObjectBox, public SharedContext
|
||||
bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
|
||||
bool isStarGenerator() const { return generatorKind() == StarGenerator; }
|
||||
bool isArrow() const { return function()->isArrow(); }
|
||||
bool isAsync() const { return _asyncKind == AsyncFunction; }
|
||||
FunctionAsyncKind asyncKind() const { return _asyncKind; }
|
||||
|
||||
void setGeneratorKind(GeneratorKind kind) {
|
||||
// A generator kind can be set at initialization, or when "yield" is
|
||||
|
@ -283,9 +283,8 @@ class SyntaxParseHandler
|
||||
bool addShorthand(Node literal, Node name, Node expr) { return true; }
|
||||
bool addObjectMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
|
||||
bool addClassMethodDefinition(Node literal, Node name, Node fn, JSOp op, bool isStatic) { return true; }
|
||||
Node newYieldExpression(uint32_t begin, Node value, Node gen, JSOp op) { return NodeUnparenthesizedYieldExpr; }
|
||||
Node newYieldExpression(uint32_t begin, Node value, Node gen) { return NodeUnparenthesizedYieldExpr; }
|
||||
Node newYieldStarExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; }
|
||||
Node newAwaitExpression(uint32_t begin, Node value, Node gen) { return NodeUnparenthesizedYieldExpr; }
|
||||
|
||||
// Statements
|
||||
|
||||
|
@ -107,8 +107,6 @@
|
||||
macro(THROW, "keyword 'throw'") \
|
||||
macro(DEBUGGER, "keyword 'debugger'") \
|
||||
macro(YIELD, "keyword 'yield'") \
|
||||
macro(ASYNC, "keyword 'async'") \
|
||||
macro(AWAIT, "keyword 'await'") \
|
||||
macro(LET, "keyword 'let'") \
|
||||
macro(EXPORT, "keyword 'export'") \
|
||||
macro(IMPORT, "keyword 'import'") \
|
||||
|
@ -986,11 +986,6 @@ TokenStream::putIdentInTokenbuf(const char16_t* identStart)
|
||||
bool
|
||||
TokenStream::checkForKeyword(const KeywordInfo* kw, TokenKind* ttp)
|
||||
{
|
||||
if (!awaitIsKeyword && kw->tokentype == TOK_AWAIT) {
|
||||
*ttp = TOK_NAME;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (kw->tokentype == TOK_RESERVED
|
||||
#ifndef JS_HAS_CLASSES
|
||||
|| kw->tokentype == TOK_CLASS
|
||||
|
@ -445,8 +445,6 @@ class MOZ_STACK_CLASS TokenStream
|
||||
{}
|
||||
};
|
||||
|
||||
bool awaitIsKeyword = false;
|
||||
|
||||
public:
|
||||
typedef Token::Modifier Modifier;
|
||||
static MOZ_CONSTEXPR_VAR Modifier None = Token::None;
|
||||
@ -687,14 +685,6 @@ class MOZ_STACK_CLASS TokenStream
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getAwaitIsKeyword() {
|
||||
return awaitIsKeyword;
|
||||
}
|
||||
|
||||
void setAwaitIsKeyword(bool _awaitIsKeyword) {
|
||||
awaitIsKeyword = _awaitIsKeyword;
|
||||
}
|
||||
|
||||
class MOZ_STACK_CLASS Position {
|
||||
public:
|
||||
// The Token fields may contain pointers to atoms, so for correct
|
||||
|
@ -1,2 +1 @@
|
||||
// classesEnabled ended up needing a fairly broad scope.
|
||||
load(libdir + "../../tests/shell.js");
|
||||
load(libdir + "../../tests/ecma_6/shell.js");
|
||||
|
@ -2496,15 +2496,15 @@ static const VMFunction DefFunOperationInfo = FunctionInfo<DefFunOperationFn>(De
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_DEFFUN()
|
||||
{
|
||||
RootedFunction fun(cx, script->getFunction(GET_UINT32_INDEX(pc)));
|
||||
|
||||
frame.popRegsAndSync(1);
|
||||
masm.unboxObject(R0, R0.scratchReg());
|
||||
masm.loadPtr(frame.addressOfScopeChain(), R1.scratchReg());
|
||||
frame.syncStack(0);
|
||||
masm.loadPtr(frame.addressOfScopeChain(), R0.scratchReg());
|
||||
|
||||
prepareVMCall();
|
||||
|
||||
pushArg(ImmGCPtr(fun));
|
||||
pushArg(R0.scratchReg());
|
||||
pushArg(R1.scratchReg());
|
||||
pushArg(ImmGCPtr(script));
|
||||
|
||||
return callVM(DefFunOperationInfo);
|
||||
|
@ -3737,9 +3737,8 @@ void
|
||||
CodeGenerator::visitDefFun(LDefFun* lir)
|
||||
{
|
||||
Register scopeChain = ToRegister(lir->scopeChain());
|
||||
Register fun = ToRegister(lir->fun());
|
||||
|
||||
pushArg(fun);
|
||||
pushArg(ImmGCPtr(lir->mir()->fun()));
|
||||
pushArg(scopeChain);
|
||||
pushArg(ImmGCPtr(current->mir()->info().script()));
|
||||
|
||||
|
@ -12585,11 +12585,13 @@ IonBuilder::jsop_defvar(uint32_t index)
|
||||
bool
|
||||
IonBuilder::jsop_deffun(uint32_t index)
|
||||
{
|
||||
JSFunction* fun = script()->getFunction(index);
|
||||
if (fun->isNative() && IsAsmJSModuleNative(fun->native()))
|
||||
return abort("asm.js module function");
|
||||
|
||||
MOZ_ASSERT(analysis().usesScopeChain());
|
||||
|
||||
MDefinition *funDef = current->pop();
|
||||
|
||||
MDefFun* deffun = MDefFun::New(alloc(), funDef, current->scopeChain());
|
||||
MDefFun* deffun = MDefFun::New(alloc(), fun, current->scopeChain());
|
||||
current->add(deffun);
|
||||
|
||||
return resumeAfter(deffun);
|
||||
|
@ -156,11 +156,7 @@ LIRGenerator::visitDefVar(MDefVar* ins)
|
||||
void
|
||||
LIRGenerator::visitDefFun(MDefFun* ins)
|
||||
{
|
||||
MDefinition* fun = ins->fun();
|
||||
MOZ_ASSERT(fun->type() == MIRType_Object);
|
||||
|
||||
LDefFun* lir = new(alloc()) LDefFun(useRegisterAtStart(fun),
|
||||
useRegisterAtStart(ins->scopeChain()));
|
||||
LDefFun* lir = new(alloc()) LDefFun(useRegisterAtStart(ins->scopeChain()));
|
||||
add(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
@ -7319,26 +7319,29 @@ class MDefVar
|
||||
};
|
||||
|
||||
class MDefFun
|
||||
: public MBinaryInstruction,
|
||||
public ObjectPolicy<0>::Data
|
||||
: public MUnaryInstruction,
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
CompilerFunction fun_;
|
||||
|
||||
private:
|
||||
MDefFun(MDefinition* fun, MDefinition* scopeChain)
|
||||
: MBinaryInstruction(fun, scopeChain)
|
||||
MDefFun(JSFunction* fun, MDefinition* scopeChain)
|
||||
: MUnaryInstruction(scopeChain),
|
||||
fun_(fun)
|
||||
{}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(DefFun)
|
||||
|
||||
static MDefFun* New(TempAllocator& alloc, MDefinition* fun, MDefinition* scopeChain) {
|
||||
static MDefFun* New(TempAllocator& alloc, JSFunction* fun, MDefinition* scopeChain) {
|
||||
return new(alloc) MDefFun(fun, scopeChain);
|
||||
}
|
||||
|
||||
MDefinition* fun() const {
|
||||
return getOperand(0);
|
||||
JSFunction* fun() const {
|
||||
return fun_;
|
||||
}
|
||||
MDefinition* scopeChain() const {
|
||||
return getOperand(1);
|
||||
return getOperand(0);
|
||||
}
|
||||
bool possiblyCalls() const override {
|
||||
return true;
|
||||
|
@ -1228,22 +1228,18 @@ class LDefVar : public LCallInstructionHelper<0, 1, 0>
|
||||
}
|
||||
};
|
||||
|
||||
class LDefFun : public LCallInstructionHelper<0, 2, 0>
|
||||
class LDefFun : public LCallInstructionHelper<0, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(DefFun)
|
||||
|
||||
LDefFun(const LAllocation& fun, const LAllocation& scopeChain)
|
||||
explicit LDefFun(const LAllocation& scopeChain)
|
||||
{
|
||||
setOperand(0, fun);
|
||||
setOperand(1, scopeChain);
|
||||
setOperand(0, scopeChain);
|
||||
}
|
||||
|
||||
const LAllocation* fun() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const LAllocation* scopeChain() {
|
||||
return getOperand(1);
|
||||
return getOperand(0);
|
||||
}
|
||||
MDefFun* mir() const {
|
||||
return mir_->toDefFun();
|
||||
|
@ -106,8 +106,6 @@ MSG_DEF(JSMSG_TERMINATED, 1, JSEXN_ERR, "Script terminated by timeo
|
||||
MSG_DEF(JSMSG_PROTO_NOT_OBJORNULL, 1, JSEXN_TYPEERR, "{0}.prototype is not an object or null")
|
||||
MSG_DEF(JSMSG_CANT_CALL_CLASS_CONSTRUCTOR, 0, JSEXN_TYPEERR, "class constructors must be invoked with |new|")
|
||||
MSG_DEF(JSMSG_DISABLED_DERIVED_CLASS, 1, JSEXN_INTERNALERR, "{0} temporarily disallowed in derived class constructors")
|
||||
MSG_DEF(JSMSG_NOT_CALLABLE, 1, JSEXN_TYPEERR, "{0} is not callable")
|
||||
MSG_DEF(JSMSG_NOT_IMPLEMENTED, 1, JSEXN_INTERNALERR, "{0} is not implemented")
|
||||
|
||||
// JSON
|
||||
MSG_DEF(JSMSG_JSON_BAD_PARSE, 3, JSEXN_SYNTAXERR, "JSON.parse: {0} at line {1} column {2} of the JSON data")
|
||||
@ -188,9 +186,6 @@ MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid array compre
|
||||
MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 0, JSEXN_INTERNALERR, "array initialiser too large")
|
||||
MSG_DEF(JSMSG_AS_AFTER_IMPORT_STAR, 0, JSEXN_SYNTAXERR, "missing keyword 'as' after import *")
|
||||
MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
|
||||
MSG_DEF(JSMSG_ASYNC_ACCESSOR, 0, JSEXN_SYNTAXERR, "async getters and setters are not allowed")
|
||||
MSG_DEF(JSMSG_ASYNC_CONSTRUCTOR, 0, JSEXN_SYNTAXERR, "constructor may not be async")
|
||||
MSG_DEF(JSMSG_ASYNC_GENERATOR, 0, JSEXN_SYNTAXERR, "generator function or method may not be async")
|
||||
MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 0, JSEXN_TYPEERR, "anonymous generator function returns a value")
|
||||
MSG_DEF(JSMSG_BAD_ARROW_ARGS, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)")
|
||||
MSG_DEF(JSMSG_BAD_BINDING, 1, JSEXN_SYNTAXERR, "redefining {0} is deprecated")
|
||||
@ -272,7 +267,6 @@ MSG_DEF(JSMSG_LABEL_NOT_FOUND, 0, JSEXN_SYNTAXERR, "label not found")
|
||||
MSG_DEF(JSMSG_LET_CLASS_BINDING, 0, JSEXN_SYNTAXERR, "'let' is not a valid name for a class")
|
||||
MSG_DEF(JSMSG_LET_COMP_BINDING, 0, JSEXN_SYNTAXERR, "'let' is not a valid name for a comprehension variable")
|
||||
MSG_DEF(JSMSG_LEXICAL_DECL_NOT_IN_BLOCK, 1, JSEXN_SYNTAXERR, "{0} declaration not directly within block")
|
||||
MSG_DEF(JSMSG_LINE_BREAK_AFTER_AWAIT, 0, JSEXN_SYNTAXERR, "no line break is allowed after 'await'")
|
||||
MSG_DEF(JSMSG_LINE_BREAK_AFTER_THROW, 0, JSEXN_SYNTAXERR, "no line break is allowed between 'throw' and its expression")
|
||||
MSG_DEF(JSMSG_MALFORMED_ESCAPE, 1, JSEXN_SYNTAXERR, "malformed {0} character escape sequence")
|
||||
MSG_DEF(JSMSG_MISSING_BINARY_DIGITS, 0, JSEXN_SYNTAXERR, "missing binary digits after '0b'")
|
||||
@ -345,9 +339,7 @@ MSG_DEF(JSMSG_USE_ASM_DIRECTIVE_FAIL, 0, JSEXN_SYNTAXERR, "\"use asm\" is only
|
||||
MSG_DEF(JSMSG_VAR_HIDES_ARG, 1, JSEXN_TYPEERR, "variable {0} redeclares argument")
|
||||
MSG_DEF(JSMSG_WHILE_AFTER_DO, 0, JSEXN_SYNTAXERR, "missing while after do-loop body")
|
||||
MSG_DEF(JSMSG_YIELD_IN_ARROW, 0, JSEXN_SYNTAXERR, "arrow function may not contain yield")
|
||||
MSG_DEF(JSMSG_YIELD_IN_ASYNC, 0, JSEXN_SYNTAXERR, "async function may not contain yield")
|
||||
MSG_DEF(JSMSG_YIELD_IN_DEFAULT, 0, JSEXN_SYNTAXERR, "yield in default expression")
|
||||
MSG_DEF(JSMSG_AWAIT_IN_DEFAULT, 0, JSEXN_SYNTAXERR, "await in default expression")
|
||||
MSG_DEF(JSMSG_BAD_COLUMN_NUMBER, 0, JSEXN_RANGEERR, "column number out of range")
|
||||
MSG_DEF(JSMSG_COMPUTED_NAME_IN_PATTERN,0, JSEXN_SYNTAXERR, "computed property names aren't supported in this destructuring declaration")
|
||||
MSG_DEF(JSMSG_DEFAULT_IN_PATTERN, 0, JSEXN_SYNTAXERR, "destructuring defaults aren't supported in this destructuring declaration")
|
||||
@ -516,10 +508,6 @@ MSG_DEF(JSMSG_NO_INDEXED_SETTER, 2, JSEXN_TYPEERR, "{0} doesn't have an
|
||||
// Super
|
||||
MSG_DEF(JSMSG_CANT_DELETE_SUPER, 0, JSEXN_REFERENCEERR, "invalid delete involving 'super'")
|
||||
|
||||
// Promise
|
||||
MSG_DEF(JSMSG_PROMISE_RESOLVED_WITH_ITSELF, 0, JSEXN_TYPEERR, "A promise cannot be resolved with itself")
|
||||
MSG_DEF(JSMSG_SETTIMEOUT_INTERVAL_NONZERO, 0, JSEXN_TYPEERR, "Intervals other than 0 are not supported")
|
||||
|
||||
// Modules
|
||||
MSG_DEF(JSMSG_BAD_DEFAULT_EXPORT, 0, JSEXN_SYNTAXERR, "default export cannot be provided by export *")
|
||||
MSG_DEF(JSMSG_MISSING_INDIRECT_EXPORT, 0, JSEXN_SYNTAXERR, "indirect export not found")
|
||||
|
@ -944,12 +944,7 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool bodyOnly, bool lamb
|
||||
return nullptr;
|
||||
}
|
||||
if (!fun->isArrow()) {
|
||||
bool ok;
|
||||
if (fun->isStarGenerator())
|
||||
ok = out.append("function* ");
|
||||
else
|
||||
ok = out.append("function ");
|
||||
if (!ok)
|
||||
if (!(fun->isStarGenerator() ? out.append("function* ") : out.append("function ")))
|
||||
return nullptr;
|
||||
}
|
||||
if (fun->atom()) {
|
||||
|
@ -285,13 +285,6 @@ class JSFunction : public js::NativeObject
|
||||
flags_ |= RESOLVED_NAME;
|
||||
}
|
||||
|
||||
void setAsyncKind(js::FunctionAsyncKind asyncKind) {
|
||||
if (isInterpretedLazy())
|
||||
lazyScript()->setAsyncKind(asyncKind);
|
||||
else
|
||||
nonLazyScript()->setAsyncKind(asyncKind);
|
||||
}
|
||||
|
||||
JSAtom* atom() const { return hasGuessedAtom() ? nullptr : atom_.get(); }
|
||||
|
||||
js::PropertyName* name() const {
|
||||
@ -466,18 +459,12 @@ class JSFunction : public js::NativeObject
|
||||
return js::NotGenerator;
|
||||
}
|
||||
|
||||
js::FunctionAsyncKind asyncKind() const {
|
||||
return isInterpretedLazy() ? lazyScript()->asyncKind() : nonLazyScript()->asyncKind();
|
||||
}
|
||||
|
||||
bool isGenerator() const { return generatorKind() != js::NotGenerator; }
|
||||
|
||||
bool isLegacyGenerator() const { return generatorKind() == js::LegacyGenerator; }
|
||||
|
||||
bool isStarGenerator() const { return generatorKind() == js::StarGenerator; }
|
||||
|
||||
bool isAsync() const { return asyncKind() == js::AsyncFunction; }
|
||||
|
||||
void setScript(JSScript* script_) {
|
||||
mutableScript() = script_;
|
||||
}
|
||||
|
@ -56,12 +56,6 @@
|
||||
#define IF_SAB(real,imaginary) imaginary
|
||||
#endif
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
#define IF_NIGHTLY(real,imaginary) real
|
||||
#else
|
||||
#define IF_NIGHTLY(real,imaginary) imaginary
|
||||
#endif
|
||||
|
||||
#define JS_FOR_PROTOTYPES(real,imaginary) \
|
||||
imaginary(Null, 0, InitNullClass, dummy) \
|
||||
real(Object, 1, InitViaClassSpec, OCLASP(Plain)) \
|
||||
@ -121,7 +115,6 @@ IF_SAB(real,imaginary)(Atomics, 53, InitAtomicsClass, OCLASP
|
||||
real(Module, 55, InitModuleClass, OCLASP(Module)) \
|
||||
real(ImportEntry, 56, InitImportEntryClass, OCLASP(ImportEntry)) \
|
||||
real(ExportEntry, 57, InitExportEntryClass, OCLASP(ExportEntry)) \
|
||||
IF_NIGHTLY(real, imaginary)(ShellPromise, 58, InitViaClassSpec, OCLASP(ShellPromise)) \
|
||||
|
||||
#define JS_FOR_EACH_PROTOTYPE(macro) JS_FOR_PROTOTYPES(macro,macro)
|
||||
|
||||
|
@ -2759,7 +2759,6 @@ JSScript::linkToFunctionFromEmitter(js::ExclusiveContext* cx, JS::Handle<JSScrip
|
||||
|
||||
script->isGeneratorExp_ = funbox->inGenexpLambda;
|
||||
script->setGeneratorKind(funbox->generatorKind());
|
||||
script->setAsyncKind(funbox->asyncKind());
|
||||
|
||||
// Link the function and the script to each other, so that StaticScopeIter
|
||||
// may walk the scope chain of currently compiling scripts.
|
||||
@ -2850,7 +2849,6 @@ JSScript::fullyInitFromEmitter(ExclusiveContext* cx, HandleScript script, Byteco
|
||||
MOZ_ASSERT(script->functionNonDelazifying() == funbox->function());
|
||||
MOZ_ASSERT(script->isGeneratorExp_ == funbox->inGenexpLambda);
|
||||
MOZ_ASSERT(script->generatorKind() == funbox->generatorKind());
|
||||
MOZ_ASSERT(script->asyncKind() == funbox->asyncKind());
|
||||
} else {
|
||||
MOZ_ASSERT(!script->funHasExtensibleScope_);
|
||||
MOZ_ASSERT(!script->funNeedsDeclEnvObject_);
|
||||
|
@ -873,8 +873,6 @@ class ScriptSourceObject : public NativeObject
|
||||
|
||||
enum GeneratorKind { NotGenerator, LegacyGenerator, StarGenerator };
|
||||
|
||||
enum FunctionAsyncKind { SyncFunction, AsyncFunction };
|
||||
|
||||
static inline unsigned
|
||||
GeneratorKindAsBits(GeneratorKind generatorKind) {
|
||||
return static_cast<unsigned>(generatorKind);
|
||||
@ -1169,8 +1167,6 @@ class JSScript : public js::gc::TenuredCell
|
||||
|
||||
bool isDerivedClassConstructor_:1;
|
||||
|
||||
bool isAsync_:1;
|
||||
|
||||
// Add padding so JSScript is gc::Cell aligned. Make padding protected
|
||||
// instead of private to suppress -Wunused-private-field compiler warnings.
|
||||
protected:
|
||||
@ -1437,12 +1433,6 @@ class JSScript : public js::gc::TenuredCell
|
||||
generatorKindBits_ = GeneratorKindAsBits(kind);
|
||||
}
|
||||
|
||||
js::FunctionAsyncKind asyncKind() const { return isAsync_ ? js::AsyncFunction : js::SyncFunction; }
|
||||
|
||||
void setAsyncKind(js::FunctionAsyncKind kind) {
|
||||
isAsync_ = kind == js::AsyncFunction;
|
||||
}
|
||||
|
||||
void setNeedsHomeObject() {
|
||||
needsHomeObject_ = true;
|
||||
}
|
||||
@ -2109,11 +2099,11 @@ class LazyScript : public gc::TenuredCell
|
||||
// Assorted bits that should really be in ScriptSourceObject.
|
||||
uint32_t version : 8;
|
||||
|
||||
uint32_t numFreeVariables : 23;
|
||||
uint32_t numFreeVariables : 24;
|
||||
uint32_t numInnerFunctions : 20;
|
||||
|
||||
uint32_t generatorKindBits : 2;
|
||||
uint32_t isAsync : 1;
|
||||
|
||||
// N.B. These are booleans but need to be uint32_t to pack correctly on MSVC.
|
||||
// If you add another boolean here, make sure to initialze it in
|
||||
// LazyScript::CreateRaw().
|
||||
@ -2226,10 +2216,6 @@ class LazyScript : public gc::TenuredCell
|
||||
|
||||
GeneratorKind generatorKind() const { return GeneratorKindFromBits(p_.generatorKindBits); }
|
||||
|
||||
FunctionAsyncKind asyncKind() const { return p_.isAsync ? AsyncFunction : SyncFunction; }
|
||||
|
||||
void setAsyncKind(FunctionAsyncKind kind) { p_.isAsync = kind == AsyncFunction; }
|
||||
|
||||
bool isGenerator() const { return generatorKind() != NotGenerator; }
|
||||
|
||||
bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
|
||||
|
@ -46,9 +46,6 @@
|
||||
/* Support for ES7 Exponentiation proposal. */
|
||||
#define JS_HAS_EXPONENTIATION 1
|
||||
|
||||
/* Support for ES7 Async Functions. */
|
||||
#define JS_HAS_ASYNC_FUNCS 1
|
||||
|
||||
#endif // NIGHTLY_BUILD
|
||||
|
||||
#endif /* jsversion_h */
|
||||
|
@ -152,7 +152,6 @@ UNIFIED_SOURCES += [
|
||||
'builtin/ModuleObject.cpp',
|
||||
'builtin/Object.cpp',
|
||||
'builtin/Profilers.cpp',
|
||||
'builtin/Promise.cpp',
|
||||
'builtin/Reflect.cpp',
|
||||
'builtin/ReflectParse.cpp',
|
||||
'builtin/SIMD.cpp',
|
||||
|
@ -1536,68 +1536,6 @@ PrintErr(JSContext* cx, unsigned argc, Value* vp)
|
||||
return PrintInternal(cx, args, gErrFile);
|
||||
}
|
||||
|
||||
static bool
|
||||
SetTimeout(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (args.length() < 2) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
|
||||
"setTimeout", args.length() == 0 ? "0" : "1", "s");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue rval(cx);
|
||||
JS::AutoValueVector argValues(cx);
|
||||
argValues.append(args.get(0));
|
||||
argValues.append(args.get(1));
|
||||
HandleValueArray arr(argValues);
|
||||
|
||||
JSAtom* setTimeoutAtom;
|
||||
if (!(setTimeoutAtom = Atomize(cx, "setTimeout", 10)))
|
||||
return false;
|
||||
|
||||
RootedPropertyName name(cx, setTimeoutAtom->asPropertyName());
|
||||
RootedValue selfHostedFun(cx);
|
||||
|
||||
if (!GlobalObject::getIntrinsicValue(cx, cx->global(), name, &selfHostedFun))
|
||||
return false;
|
||||
|
||||
RootedObject undef(cx);
|
||||
if (!JS_CallFunctionValue(cx, undef, selfHostedFun, arr, &rval))
|
||||
return false;
|
||||
|
||||
args.rval().set(rval);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
RunEvents(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
RootedValue rval(cx);
|
||||
JS::AutoValueVector argValues(cx);
|
||||
HandleValueArray arr(argValues);
|
||||
|
||||
JSAtom* runEvents;
|
||||
if (!(runEvents = Atomize(cx, "runEvents", 9)))
|
||||
return false;
|
||||
|
||||
RootedPropertyName name(cx, runEvents->asPropertyName());
|
||||
RootedValue selfHostedFun(cx);
|
||||
|
||||
if (!GlobalObject::getIntrinsicValue(cx, cx->global(), name, &selfHostedFun))
|
||||
return false;
|
||||
|
||||
RootedObject undef(cx);
|
||||
if (!JS_CallFunctionValue(cx, undef, selfHostedFun, arr, &rval))
|
||||
return false;
|
||||
|
||||
args.rval().set(rval);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
Help(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
@ -4658,15 +4596,6 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
|
||||
"dateNow()",
|
||||
" Return the current time with sub-ms precision."),
|
||||
|
||||
JS_FN_HELP("setTimeout", SetTimeout, 2, 2,
|
||||
"setTimeout(fn, timeout)",
|
||||
" Execute a function after a specified timeout. Currently only 0 is supported."),
|
||||
|
||||
JS_FN_HELP("runEvents", RunEvents, 2, 2,
|
||||
"runEvents()",
|
||||
" Run events that were scheduled using setTimeout() calls.\n"
|
||||
" This call is required, because there is no real event loop."),
|
||||
|
||||
JS_FN_HELP("help", Help, 0, 0,
|
||||
"help([name ...])",
|
||||
" Display usage and help messages."),
|
||||
|
@ -1,45 +0,0 @@
|
||||
/**
|
||||
* Because there is no way to "wait" for a callback in this testing system,
|
||||
* there was a need to make one big promise out of all test cases.
|
||||
*/
|
||||
|
||||
var Promise = ShellPromise;
|
||||
|
||||
Promise.all([
|
||||
|
||||
assertEventuallyEq(new Promise(resolve => resolve(2)), 2),
|
||||
|
||||
assertEventuallyThrows(new Promise((_, reject) => reject(new Error())), Error),
|
||||
|
||||
assertEventuallyThrows(new Promise(() => { throw new Error(); }), Error),
|
||||
|
||||
assertEventuallyEq(new Promise(resolve => resolve())
|
||||
.then(() => 3), 3),
|
||||
|
||||
assertEventuallyEq(new Promise(resolve => resolve())
|
||||
.then(() => new Promise(r => r(3))), 3),
|
||||
|
||||
assertEventuallyEq(new Promise((_, reject) => reject(new Error()))
|
||||
.catch(() => new Promise(r => r(3))), 3),
|
||||
|
||||
assertEventuallyThrows(new Promise(resolve => resolve())
|
||||
.then(() => { throw new Error(); }), Error),
|
||||
|
||||
assertEventuallyEq(new Promise((_, reject) => reject(new Error()))
|
||||
.catch(() => 4), 4),
|
||||
|
||||
assertEventuallyEq(Promise.resolve(5), 5),
|
||||
|
||||
assertEventuallyThrows(Promise.reject(new Error()), Error),
|
||||
|
||||
assertEventuallyDeepEq(Promise.all([]), []),
|
||||
|
||||
assertEventuallyDeepEq(Promise.all(Array(10).fill()
|
||||
.map((_, id) => new Promise(resolve => resolve(id)))),
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
|
||||
|
||||
])
|
||||
.then(() => {
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
});
|
@ -1,12 +0,0 @@
|
||||
var Promise = ShellPromise;
|
||||
|
||||
var oldThen = Promise.prototype.then;
|
||||
|
||||
// Changing then() should not break catch()
|
||||
Promise.prototype.then = function() { throw new Error(); };
|
||||
|
||||
new Promise(a => { throw new Error(); })
|
||||
.catch(() => {
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
});
|
@ -1,23 +0,0 @@
|
||||
/**
|
||||
* These functions are inspired by chai-as-promised library for promise testing
|
||||
* in JS applications. They check if promises eventually resolve to a given value
|
||||
* or are rejected with a specified error type.
|
||||
*/
|
||||
|
||||
if (typeof assertEventuallyEq === 'undefined') {
|
||||
assertEventuallyEq = function(promise, expected) {
|
||||
return promise.then(actual => assertEq(actual, expected));
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof assertEventuallyThrows === 'undefined') {
|
||||
assertEventuallyThrows = function(promise, expectedErrorType) {
|
||||
return promise.catch(actualE => assertEq(actualE instanceof expectedErrorType, true));
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof assertEventuallyDeepEq === 'undefined') {
|
||||
assertEventuallyDeepEq = function(promise, expected) {
|
||||
return promise.then(actual => assertDeepEq(actual, expected));
|
||||
};
|
||||
}
|
@ -215,3 +215,14 @@ if (typeof assertWarning === 'undefined') {
|
||||
disableLastWarning();
|
||||
}
|
||||
}
|
||||
|
||||
function classesEnabled(testCode = "class Foo { constructor() {} }") {
|
||||
try {
|
||||
new Function(testCode);
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (!(e instanceof SyntaxError))
|
||||
throw e;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function assertThrowsSE(code) {
|
||||
assertThrows(() => Reflect.parse(code), SyntaxError);
|
||||
}
|
||||
|
||||
if (asyncFunctionsEnabled()) {
|
||||
assertThrowsSE("'use strict'; async function eval() {}");
|
||||
assertThrowsSE("'use strict'; async function arguments() {}");
|
||||
assertThrowsSE("async function a(k = super.prop) { }");
|
||||
assertThrowsSE("async function a() { super.prop(); }");
|
||||
assertThrowsSE("async function a() { super(); }");
|
||||
|
||||
assertThrowsSE("async function a(k = await 3) {}");
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
@ -1,20 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var test = `
|
||||
|
||||
async function test() { }
|
||||
|
||||
var anon = async function() { }
|
||||
|
||||
assertEq(test.name, "test");
|
||||
assertEq(anon.name, "");
|
||||
|
||||
`;
|
||||
|
||||
if (asyncFunctionsEnabled())
|
||||
eval(test);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
@ -1,65 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var test = `
|
||||
|
||||
var Promise = ShellPromise;
|
||||
|
||||
class X {
|
||||
constructor() {
|
||||
this.value = 42;
|
||||
}
|
||||
async getValue() {
|
||||
return this.value;
|
||||
}
|
||||
setValue(value) {
|
||||
this.value = value;
|
||||
}
|
||||
async increment() {
|
||||
var value = await this.getValue();
|
||||
this.setValue(value + 1);
|
||||
return this.getValue();
|
||||
}
|
||||
async getBaseClassName() {
|
||||
return 'X';
|
||||
}
|
||||
static async getStaticValue() {
|
||||
return 44;
|
||||
}
|
||||
}
|
||||
|
||||
class Y extends X {
|
||||
constructor() { }
|
||||
async getBaseClassName() {
|
||||
return super.getBaseClassName();
|
||||
}
|
||||
}
|
||||
|
||||
var objLiteral = {
|
||||
async get() {
|
||||
return 45;
|
||||
},
|
||||
someStuff: 5
|
||||
};
|
||||
|
||||
var x = new X();
|
||||
var y = new Y();
|
||||
|
||||
Promise.all([
|
||||
assertEventuallyEq(x.getValue(), 42),
|
||||
assertEventuallyEq(x.increment(), 43),
|
||||
assertEventuallyEq(X.getStaticValue(), 44),
|
||||
assertEventuallyEq(objLiteral.get(), 45),
|
||||
assertEventuallyEq(y.getBaseClassName(), 'X'),
|
||||
]).then(() => {
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
});
|
||||
|
||||
`;
|
||||
|
||||
if (classesEnabled() && asyncFunctionsEnabled())
|
||||
eval(test);
|
||||
else if (typeof reportCompare === 'function')
|
||||
reportCompare(0,0,"OK");
|
@ -1,177 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var test = `
|
||||
|
||||
var Promise = ShellPromise;
|
||||
|
||||
async function empty() {
|
||||
|
||||
}
|
||||
|
||||
async function simpleReturn() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
async function simpleAwait() {
|
||||
var result = await 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
async function simpleAwaitAsync() {
|
||||
var result = await simpleReturn();
|
||||
return 2 + result;
|
||||
}
|
||||
|
||||
async function returnOtherAsync() {
|
||||
return 1 + await simpleAwaitAsync();
|
||||
}
|
||||
|
||||
async function simpleThrower() {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
async function delegatedThrower() {
|
||||
var val = await simpleThrower();
|
||||
return val;
|
||||
}
|
||||
|
||||
async function tryCatch() {
|
||||
try {
|
||||
await delegatedThrower();
|
||||
return 'FAILED';
|
||||
} catch (_) {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
async function tryCatchThrow() {
|
||||
try {
|
||||
await delegatedThrower();
|
||||
return 'FAILED';
|
||||
} catch (_) {
|
||||
return delegatedThrower();
|
||||
}
|
||||
}
|
||||
|
||||
async function wellFinally() {
|
||||
try {
|
||||
await delegatedThrower();
|
||||
} catch (_) {
|
||||
return 'FAILED';
|
||||
} finally {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
async function finallyMayFail() {
|
||||
try {
|
||||
await delegatedThrower();
|
||||
} catch (_) {
|
||||
return 5;
|
||||
} finally {
|
||||
return delegatedThrower();
|
||||
}
|
||||
}
|
||||
|
||||
async function embedded() {
|
||||
async function inner() {
|
||||
return 7;
|
||||
}
|
||||
return await inner();
|
||||
}
|
||||
|
||||
// recursion, it works!
|
||||
async function fib(n) {
|
||||
return (n == 0 || n == 1) ? n : await fib(n - 1) + await fib(n - 2);
|
||||
}
|
||||
|
||||
// mutual recursion
|
||||
async function isOdd(n) {
|
||||
async function isEven(n) {
|
||||
return n === 0 || await isOdd(n - 1);
|
||||
}
|
||||
return n !== 0 && await isEven(n - 1);
|
||||
}
|
||||
|
||||
// recursion, take three!
|
||||
var hardcoreFib = async function fib2(n) {
|
||||
return (n == 0 || n == 1) ? n : await fib2(n - 1) + await fib2(n - 2);
|
||||
}
|
||||
|
||||
var asyncExpr = async function() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
var namedAsyncExpr = async function simple() {
|
||||
return 11;
|
||||
}
|
||||
|
||||
async function executionOrder() {
|
||||
var value = 0;
|
||||
async function first() {
|
||||
return (value = value === 0 ? 1 : value);
|
||||
}
|
||||
async function second() {
|
||||
return (value = value === 0 ? 2 : value);
|
||||
}
|
||||
async function third() {
|
||||
return (value = value === 0 ? 3 : value);
|
||||
}
|
||||
return await first() + await second() + await third() + 6;
|
||||
}
|
||||
|
||||
async function miscellaneous() {
|
||||
if (arguments.length === 3 &&
|
||||
arguments.callee.name === "miscellaneous")
|
||||
return 14;
|
||||
}
|
||||
|
||||
function thrower() {
|
||||
throw 15;
|
||||
}
|
||||
|
||||
async function defaultArgs(arg = thrower()) {
|
||||
|
||||
}
|
||||
|
||||
// Async functions are not constructible
|
||||
assertThrows(() => {
|
||||
async function Person() {
|
||||
|
||||
}
|
||||
new Person();
|
||||
}, TypeError);
|
||||
|
||||
Promise.all([
|
||||
assertEventuallyEq(empty(), undefined),
|
||||
assertEventuallyEq(simpleReturn(), 1),
|
||||
assertEventuallyEq(simpleAwait(), 2),
|
||||
assertEventuallyEq(simpleAwaitAsync(), 3),
|
||||
assertEventuallyEq(returnOtherAsync(), 4),
|
||||
assertEventuallyThrows(simpleThrower(), Error),
|
||||
assertEventuallyEq(tryCatch(), 5),
|
||||
assertEventuallyThrows(tryCatchThrow(), Error),
|
||||
assertEventuallyEq(wellFinally(), 6),
|
||||
assertEventuallyThrows(finallyMayFail(), Error),
|
||||
assertEventuallyEq(embedded(), 7),
|
||||
assertEventuallyEq(fib(6), 8),
|
||||
assertEventuallyEq(executionOrder(), 9),
|
||||
assertEventuallyEq(asyncExpr(), 10),
|
||||
assertEventuallyEq(namedAsyncExpr(), 11),
|
||||
assertEventuallyEq(isOdd(12).then(v => v ? "oops" : 12), 12),
|
||||
assertEventuallyEq(hardcoreFib(7), 13),
|
||||
assertEventuallyEq(miscellaneous(1, 2, 3), 14),
|
||||
assertEventuallyEq(defaultArgs().catch(e => e), 15)
|
||||
]).then(() => {
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
});
|
||||
|
||||
`;
|
||||
|
||||
if (asyncFunctionsEnabled())
|
||||
eval(test);
|
||||
else if (typeof reportCompare === 'function')
|
||||
reportCompare(0,0,"OK");
|
@ -1,36 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* These methods are inspired by chai-as-promised library for promise testing
|
||||
* in JS applications. They check if promises eventually resolve to a given value
|
||||
* or are rejected with a specified error type.
|
||||
*/
|
||||
|
||||
if (typeof assertEventuallyEq === 'undefined') {
|
||||
assertEventuallyEq = function(promise, expected) {
|
||||
return promise.then(actual => assertEq(actual, expected));
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof assertEventuallyThrows === 'undefined') {
|
||||
assertEventuallyThrows = function(promise, expectedErrorType) {
|
||||
return promise.catch(actualE => assertEq(actualE instanceof expectedErrorType, true));
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof assertEventuallyDeepEq === 'undefined') {
|
||||
assertEventuallyDeepEq = function(promise, expected) {
|
||||
return promise.then(actual => assertDeepEq(actual, expected));
|
||||
};
|
||||
}
|
||||
|
||||
function asyncFunctionsEnabled() {
|
||||
try {
|
||||
eval("async function f() { }");
|
||||
return true;
|
||||
} catch (e if e instanceof SyntaxError) {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
if (asyncFunctionsEnabled()) {
|
||||
parseModule("async function f() { await 3; }");
|
||||
parseModule("async function f() { await 3; }");
|
||||
assertThrows(() => parseModule("var await = 5;"), SyntaxError);
|
||||
assertThrows(() => parseModule("export var await;"), SyntaxError);
|
||||
assertThrows(() => parseModule("async function f() { function g() { await 3; } }"), SyntaxError);
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
@ -1,87 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Currently only a part of async/await grammar is supported:
|
||||
* - Async function statements are supported.
|
||||
* - Await expressions are supported (as regular unary expressions).
|
||||
* All other parts of proposal are probably not supported.
|
||||
* Even the supported parts of implementation may not be 100% compliant with
|
||||
* the grammar. This is to be considered a proof-of-concept implementation.
|
||||
*/
|
||||
|
||||
if (asyncFunctionsEnabled()) {
|
||||
assertEq(Reflect.parse("function a() {}").body[0].async, false);
|
||||
assertEq(Reflect.parse("function* a() {}").body[0].async, false);
|
||||
assertEq(Reflect.parse("async function a() {}").body[0].async, true);
|
||||
assertEq(Reflect.parse("() => {}").body[0].async, undefined);
|
||||
|
||||
// Async generators are not allowed (with regards to spec)
|
||||
assertThrows(() => Reflect.parse("async function* a() {}"), SyntaxError);
|
||||
|
||||
// No line terminator after async
|
||||
assertEq(Reflect.parse("async\nfunction a(){}").body[0].expression.name, "async");
|
||||
|
||||
// Async arrow functions are allowed, but not supported yet
|
||||
assertThrows(() => Reflect.parse("async () => true"), SyntaxError);
|
||||
|
||||
// Async function expressions
|
||||
assertEq(Reflect.parse("(async function() {})()").body[0].expression.callee.async, true);
|
||||
assertEq(Reflect.parse("var k = async function() {}").body[0].declarations[0].init.async, true);
|
||||
assertEq(Reflect.parse("var nmd = async function named() {}").body[0].declarations[0].init.id.name, "named");
|
||||
|
||||
// Awaiting not directly inside an async function is not allowed
|
||||
assertThrows(() => Reflect.parse("await 4;"), SyntaxError);
|
||||
assertThrows(() => Reflect.parse("function a() { await 4; }"), SyntaxError);
|
||||
assertThrows(() => Reflect.parse("function* a() { await 4; }"), SyntaxError);
|
||||
assertThrows(() => Reflect.parse("async function k() { function a() { await 4; } }"), SyntaxError);
|
||||
|
||||
// No line terminator after await is allowed
|
||||
assertThrows(() => Reflect.parse("async function a() { await\n4; }"), SyntaxError);
|
||||
|
||||
// Await is not allowed as a default expr.
|
||||
assertThrows(() => Reflect.parse("async function a(k = await 3) {}"), SyntaxError);
|
||||
assertThrows(() => Reflect.parse("async function a() { async function b(k = await 3) {} }"), SyntaxError);
|
||||
|
||||
// Await is not legal as an identifier in an async function.
|
||||
assertThrows(() => Reflect.parse("async function a() { var await = 4; }"), SyntaxError);
|
||||
assertThrows(() => Reflect.parse("async function a() { return await; }"), SyntaxError);
|
||||
|
||||
// Yield is not allowed in an async function / treated as identifier
|
||||
assertThrows(() => Reflect.parse("async function a() { yield 3; }"), SyntaxError);
|
||||
|
||||
// Await is still available as an identifier name in strict mode code.
|
||||
Reflect.parse("function a() { 'use strict'; var await = 3; }");
|
||||
Reflect.parse("'use strict'; var await = 3;");
|
||||
|
||||
// Await is treated differently depending on context. Various cases.
|
||||
Reflect.parse("var await = 3; async function a() { await 4; }");
|
||||
Reflect.parse("async function a() { await 4; } var await = 5");
|
||||
Reflect.parse("async function a() { function b() { return await; } }")
|
||||
|
||||
Reflect.parse("async function a() { var k = { async: 4 } }");
|
||||
|
||||
Reflect.parse("function a() { await: 4 }");
|
||||
|
||||
assertEq(Reflect.parse("async function a() { await 4; }")
|
||||
.body[0].body.body[0].expression.operator, "await");
|
||||
|
||||
assertEq(Reflect.parse("async function a() { async function b() { await 4; } }")
|
||||
.body[0].body.body[0].body.body[0].expression.operator, "await");
|
||||
|
||||
// operator priority test
|
||||
assertEq(Reflect.parse("async function a() { await 2 + 3; }")
|
||||
.body[0].body.body[0].expression.left.argument.value, 2);
|
||||
assertEq(Reflect.parse("async function a() { await 2 + 3; }")
|
||||
.body[0].body.body[0].expression.left.operator, "await");
|
||||
assertEq(Reflect.parse("async function a() { await 2 + 3; }")
|
||||
.body[0].body.body[0].expression.right.value, 3);
|
||||
|
||||
// blocks and other constructions
|
||||
assertEq(Reflect.parse("{ async function a() { return 2; } }")
|
||||
.body[0].body[0].async, true);
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
@ -872,17 +872,6 @@ function assertThrowsInstanceOf(f, ctor, msg) {
|
||||
throw new Error(fullmsg);
|
||||
};
|
||||
|
||||
function classesEnabled(testCode = "class Foo { constructor() {} }") {
|
||||
try {
|
||||
new Function(testCode);
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (!(e instanceof SyntaxError))
|
||||
throw e;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some tests need to know if we are in Rhino as opposed to SpiderMonkey
|
||||
*/
|
||||
|
@ -18,8 +18,6 @@
|
||||
macro(apply, apply, "apply") \
|
||||
macro(arguments, arguments, "arguments") \
|
||||
macro(as, as, "as") \
|
||||
macro(async, async, "async") \
|
||||
macro(await, await, "await") \
|
||||
macro(ArrayIteratorNext, ArrayIteratorNext, "ArrayIteratorNext") \
|
||||
macro(ArrayType, ArrayType, "ArrayType") \
|
||||
macro(ArrayValues, ArrayValues, "ArrayValues") \
|
||||
|
@ -23,11 +23,6 @@
|
||||
#include "builtin/MapObject.h"
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "builtin/Object.h"
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
#include "builtin/Promise.h"
|
||||
#endif
|
||||
|
||||
#include "builtin/RegExp.h"
|
||||
#include "builtin/SIMD.h"
|
||||
#include "builtin/SymbolObject.h"
|
||||
|
@ -382,12 +382,6 @@ class GlobalObject : public NativeObject
|
||||
return &global->getPrototype(JSProto_Symbol).toObject().as<NativeObject>();
|
||||
}
|
||||
|
||||
static NativeObject* getOrCreatePromisePrototype(JSContext* cx, Handle<GlobalObject*> global) {
|
||||
if (!ensureConstructor(cx, global, JSProto_ShellPromise))
|
||||
return nullptr;
|
||||
return &global->getPrototype(JSProto_ShellPromise).toObject().as<NativeObject>();
|
||||
}
|
||||
|
||||
static NativeObject* getOrCreateRegExpPrototype(JSContext* cx, Handle<GlobalObject*> global) {
|
||||
if (!ensureConstructor(cx, global, JSProto_RegExp))
|
||||
return nullptr;
|
||||
|
@ -3507,18 +3507,17 @@ CASE(JSOP_DEFVAR)
|
||||
}
|
||||
END_CASE(JSOP_DEFVAR)
|
||||
|
||||
CASE(JSOP_DEFFUN) {
|
||||
CASE(JSOP_DEFFUN)
|
||||
{
|
||||
/*
|
||||
* A top-level function defined in Global or Eval code (see ECMA-262
|
||||
* Ed. 3), or else a SpiderMonkey extension: a named function statement in
|
||||
* a compound statement (not at the top statement level of global code, or
|
||||
* at the top level of a function body).
|
||||
*/
|
||||
MOZ_ASSERT(REGS.sp[-1].isObject());
|
||||
ReservedRooted<JSFunction*> fun(&rootFunction0, ®S.sp[-1].toObject().as<JSFunction>());
|
||||
ReservedRooted<JSFunction*> fun(&rootFunction0, script->getFunction(GET_UINT32_INDEX(REGS.pc)));
|
||||
if (!DefFunOperation(cx, script, REGS.fp()->scopeChain(), fun))
|
||||
goto error;
|
||||
REGS.sp--;
|
||||
}
|
||||
END_CASE(JSOP_DEFFUN)
|
||||
|
||||
@ -4322,6 +4321,14 @@ js::DefFunOperation(JSContext* cx, HandleScript script, HandleObject scopeChain,
|
||||
* requests in server-side JS.
|
||||
*/
|
||||
RootedFunction fun(cx, funArg);
|
||||
if (fun->isNative() || fun->environment() != scopeChain) {
|
||||
fun = CloneFunctionObjectIfNotSingleton(cx, fun, scopeChain, nullptr, TenuredObject);
|
||||
if (!fun)
|
||||
return false;
|
||||
} else {
|
||||
MOZ_ASSERT(script->treatAsRunOnce());
|
||||
MOZ_ASSERT(!script->functionNonDelazifying());
|
||||
}
|
||||
|
||||
/*
|
||||
* We define the function as a property of the variable object and not the
|
||||
|
@ -56,7 +56,6 @@
|
||||
macro(protected, protected_, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
|
||||
macro(public, public_, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
|
||||
macro(static, static_, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
|
||||
macro(await, await, TOK_AWAIT, JSVERSION_DEFAULT) \
|
||||
/* \
|
||||
* Yield is a token inside function*. Outside of a function*, it is a \
|
||||
* future reserved keyword in strict mode, but a keyword in JS1.7 even \
|
||||
|
@ -1294,7 +1294,7 @@
|
||||
* Operands: uint32_t funcIndex
|
||||
* Stack: =>
|
||||
*/ \
|
||||
macro(JSOP_DEFFUN, 127,"deffun", NULL, 1, 1, 0, JOF_BYTE) \
|
||||
macro(JSOP_DEFFUN, 127,"deffun", NULL, 5, 0, 0, JOF_OBJECT) \
|
||||
/*
|
||||
* Defines the new binding on the frame's current variables-object (the
|
||||
* scope object on the scope chain designated to receive new variables) with
|
||||
@ -1983,6 +1983,7 @@
|
||||
* Stack: val => ToString(val)
|
||||
*/ \
|
||||
macro(JSOP_TOSTRING, 228, "tostring", NULL, 1, 1, 1, JOF_BYTE)
|
||||
|
||||
/*
|
||||
* In certain circumstances it may be useful to "pad out" the opcode space to
|
||||
* a power of two. Use this macro to do so.
|
||||
|
@ -237,12 +237,7 @@ CallObject::createForFunction(JSContext* cx, HandleObject enclosing, HandleFunct
|
||||
* object holding function's name.
|
||||
*/
|
||||
if (callee->isNamedLambda()) {
|
||||
if (callee->isAsync()) {
|
||||
RootedFunction fun(cx, &callee->getExtendedSlot(1).toObject().as<JSFunction>());
|
||||
scopeChain = DeclEnvObject::create(cx, scopeChain, fun);
|
||||
} else {
|
||||
scopeChain = DeclEnvObject::create(cx, scopeChain, callee);
|
||||
}
|
||||
scopeChain = DeclEnvObject::create(cx, scopeChain, callee);
|
||||
if (!scopeChain)
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "builtin/MapObject.h"
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "builtin/Object.h"
|
||||
#include "builtin/Promise.h"
|
||||
#include "builtin/Reflect.h"
|
||||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "builtin/SIMD.h"
|
||||
@ -442,54 +441,6 @@ intrinsic_GetIteratorPrototype(JSContext* cx, unsigned argc, Value* vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_NewPromise(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
return js::PromiseConstructor(cx, argc, vp);
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_IsPromise(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 1);
|
||||
MOZ_ASSERT(args[0].isObject());
|
||||
bool isPromise = args[0].toObject().getClass() == &ShellPromiseObject::class_;
|
||||
|
||||
args.rval().setBoolean(isPromise);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_SetFunName(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 2);
|
||||
MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<JSFunction>());
|
||||
MOZ_ASSERT(args[1].isString());
|
||||
JSAtom* atom = AtomizeString(cx, args[1].toString());
|
||||
if (atom == nullptr)
|
||||
return false;
|
||||
RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
|
||||
fun->setFlags(fun->flags() & ~JSFunction::HAS_GUESSED_ATOM);
|
||||
fun->initAtom(atom);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_GetFunName(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 1);
|
||||
MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<JSFunction>());
|
||||
PropertyName* name = args[0].toObject().as<JSFunction>().name();
|
||||
if (!name)
|
||||
args.rval().setUndefined();
|
||||
else
|
||||
args.rval().setString(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
@ -1243,20 +1194,6 @@ intrinsic_IsWeakSet(JSContext* cx, unsigned argc, Value* vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
intrinsic_SetFunctionExtendedSlot(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 3);
|
||||
MOZ_ASSERT(args[0].isObject());
|
||||
MOZ_ASSERT(args[0].toObject().is<JSFunction>());
|
||||
MOZ_ASSERT(args[1].isInt32());
|
||||
|
||||
args[0].toObject().as<JSFunction>().setExtendedSlot(args[1].toPrivateUint32(), args[2]);
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default locale as a well-formed, but not necessarily canonicalized,
|
||||
* BCP-47 language tag.
|
||||
@ -1496,7 +1433,6 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||
JS_FN("_ConstructorForTypedArray", intrinsic_ConstructorForTypedArray, 1,0),
|
||||
JS_FN("DecompileArg", intrinsic_DecompileArg, 2,0),
|
||||
JS_FN("RuntimeDefaultLocale", intrinsic_RuntimeDefaultLocale, 0,0),
|
||||
JS_FN("SetFunctionExtendedSlot", intrinsic_SetFunctionExtendedSlot, 3,0),
|
||||
JS_FN("LocalTZA", intrinsic_LocalTZA, 0,0),
|
||||
|
||||
JS_INLINABLE_FN("_IsConstructing", intrinsic_IsConstructing, 0,0,
|
||||
@ -1584,11 +1520,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||
CallNonGenericSelfhostedMethod<Is<StarGeneratorObject>>, 2, 0),
|
||||
|
||||
JS_FN("IsWeakSet", intrinsic_IsWeakSet, 1,0),
|
||||
JS_FN("NewPromise", intrinsic_NewPromise, 1,0),
|
||||
JS_FN("IsPromise", intrinsic_IsPromise, 1,0),
|
||||
|
||||
JS_FN("SetFunName", intrinsic_SetFunName, 2,0),
|
||||
JS_FN("GetFunName", intrinsic_GetFunName, 1,0),
|
||||
// See builtin/TypedObject.h for descriptors of the typedobj functions.
|
||||
JS_FN("NewOpaqueTypedObject", js::NewOpaqueTypedObject, 1, 0),
|
||||
JS_FN("NewDerivedTypedObject", js::NewDerivedTypedObject, 3, 0),
|
||||
|
@ -29,11 +29,11 @@ namespace js {
|
||||
*
|
||||
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
|
||||
*/
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 311;
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 310;
|
||||
static const uint32_t XDR_BYTECODE_VERSION =
|
||||
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
|
||||
|
||||
static_assert(JSErr_Limit == 425,
|
||||
static_assert(JSErr_Limit == 415,
|
||||
"GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
|
||||
"removed MSG_DEFs from js.msg, you should increment "
|
||||
"XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "
|
||||
|
Loading…
Reference in New Issue
Block a user