Backed out 6 changesets (bug 1185106) for SM bustage CLOSED TREE

Backed out changeset 8453ae71b30d (bug 1185106)
Backed out changeset 446ea07800c9 (bug 1185106)
Backed out changeset a3c1f65f0dff (bug 1185106)
Backed out changeset 5174ef291f0c (bug 1185106)
Backed out changeset 8073e7c4cf94 (bug 1185106)
Backed out changeset 3afd56565e23 (bug 1185106)
This commit is contained in:
Wes Kocher 2015-10-06 08:49:21 -07:00
parent 2fb80224dc
commit 4d978bb1e9
60 changed files with 131 additions and 1575 deletions

View File

@ -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 \

View File

@ -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;

View File

@ -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);
});
}

View File

@ -1,141 +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 "jscntxt.h"
#include "builtin/SelfHostingDefines.h"
#include "jsobjinlines.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
}
};

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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) &&

View File

@ -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);

View File

@ -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))

View File

@ -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;

View File

@ -183,7 +183,6 @@ class PackedScopeCoordinate
F(VOID) \
F(NOT) \
F(BITNOT) \
F(AWAIT) \
\
/* \
* Binary operators. \

View File

@ -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(&ltok, 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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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'") \

View File

@ -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

View File

@ -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

View File

@ -1,2 +1 @@
// classesEnabled ended up needing a fairly broad scope.
load(libdir + "../../tests/shell.js");
load(libdir + "../../tests/ecma_6/shell.js");

View File

@ -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);

View File

@ -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()));

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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();

View File

@ -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")

View File

@ -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()) {

View File

@ -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_;
}

View File

@ -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)

View File

@ -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_);

View File

@ -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; }

View File

@ -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 */

View File

@ -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',

View File

@ -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."),

View File

@ -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);
});

View File

@ -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);
});

View File

@ -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));
};
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -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");

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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
*/

View File

@ -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") \

View File

@ -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"

View File

@ -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;

View File

@ -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, &REGS.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

View File

@ -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 \

View File

@ -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.

View File

@ -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;
}

View File

@ -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),

View File

@ -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 "