mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-26 10:10:31 +00:00
Backed out changeset 77052db08766 (bug 611388)
This commit is contained in:
parent
7fc241ad16
commit
1ddef21ea8
@ -54,23 +54,12 @@ const debug = false;
|
||||
var expectedConsoleMessages = [];
|
||||
var expectLoggedMessages = null;
|
||||
|
||||
function get_RDF() {
|
||||
try {
|
||||
return Components.classes["@mozilla.org/rdf/rdf-service;1"].
|
||||
getService(Components.interfaces.nsIRDFService);
|
||||
} catch (ex) { }
|
||||
}
|
||||
|
||||
function get_ContainerUtils()
|
||||
{
|
||||
try {
|
||||
return Components.classes["@mozilla.org/rdf/container-utils;1"].
|
||||
getService(Components.interfaces.nsIRDFContainerUtils);
|
||||
} catch(ex) { }
|
||||
}
|
||||
|
||||
const RDF = get_RDF();
|
||||
const ContainerUtils = get_ContainerUtils();
|
||||
try {
|
||||
const RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].
|
||||
getService(Components.interfaces.nsIRDFService);
|
||||
const ContainerUtils = Components.classes["@mozilla.org/rdf/container-utils;1"].
|
||||
getService(Components.interfaces.nsIRDFContainerUtils);
|
||||
} catch(ex) { }
|
||||
|
||||
var xmlDoc;
|
||||
|
||||
|
@ -1240,7 +1240,7 @@ LookupAliasedName(BytecodeEmitter *bce, HandleScript script, PropertyName *name,
|
||||
if (freeVariables[i].isHoistedUse() && bindingIndex >= lexicalBegin) {
|
||||
MOZ_ASSERT(pn);
|
||||
MOZ_ASSERT(pn->isUsed());
|
||||
pn->pn_dflags |= PND_LEXICAL;
|
||||
pn->pn_dflags |= PND_LET;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -1289,7 +1289,7 @@ AssignHops(BytecodeEmitter *bce, ParseNode *pn, unsigned src, ScopeCoordinate *d
|
||||
static inline MaybeCheckLexical
|
||||
NodeNeedsCheckLexical(ParseNode *pn)
|
||||
{
|
||||
return pn->isHoistedLexicalUse() ? CheckLexical : DontCheckLexical;
|
||||
return pn->isHoistedLetUse() ? CheckLexical : DontCheckLexical;
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -1461,7 +1461,6 @@ BytecodeEmitter::isAliasedName(ParseNode *pn)
|
||||
|
||||
switch (dn->kind()) {
|
||||
case Definition::LET:
|
||||
case Definition::CONST:
|
||||
/*
|
||||
* There are two ways to alias a let variable: nested functions and
|
||||
* dynamic scope operations. (This is overly conservative since the
|
||||
@ -1486,7 +1485,7 @@ BytecodeEmitter::isAliasedName(ParseNode *pn)
|
||||
*/
|
||||
return script->formalIsAliased(pn->pn_cookie.slot());
|
||||
case Definition::VAR:
|
||||
case Definition::GLOBALCONST:
|
||||
case Definition::CONST:
|
||||
MOZ_ASSERT_IF(sc->allLocalsAliased(), script->varIsAliased(pn->pn_cookie.slot()));
|
||||
return script->varIsAliased(pn->pn_cookie.slot());
|
||||
case Definition::PLACEHOLDER:
|
||||
@ -1778,7 +1777,6 @@ BindNameToSlotHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
break;
|
||||
|
||||
case Definition::VAR:
|
||||
case Definition::GLOBALCONST:
|
||||
case Definition::CONST:
|
||||
case Definition::LET:
|
||||
switch (op) {
|
||||
@ -2079,7 +2077,7 @@ CheckSideEffects(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool
|
||||
}
|
||||
}
|
||||
|
||||
if (pn->isHoistedLexicalUse()) {
|
||||
if (pn->isHoistedLetUse()) {
|
||||
// Hoisted uses of lexical bindings throw on access.
|
||||
*answer = true;
|
||||
}
|
||||
@ -4658,7 +4656,7 @@ EmitLet(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pnLet)
|
||||
ParseNode *varList = pnLet->pn_left;
|
||||
MOZ_ASSERT(varList->isArity(PN_LIST));
|
||||
ParseNode *letBody = pnLet->pn_right;
|
||||
MOZ_ASSERT(letBody->isLexical() && letBody->isKind(PNK_LEXICALSCOPE));
|
||||
MOZ_ASSERT(letBody->isLet() && letBody->isKind(PNK_LEXICALSCOPE));
|
||||
|
||||
int letHeadDepth = bce->stackDepth;
|
||||
|
||||
@ -4748,7 +4746,7 @@ static bool
|
||||
EmitForInOrOfVariables(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool *letDecl)
|
||||
{
|
||||
*letDecl = pn->isKind(PNK_LEXICALSCOPE);
|
||||
MOZ_ASSERT_IF(*letDecl, pn->isLexical());
|
||||
MOZ_ASSERT_IF(*letDecl, pn->isLet());
|
||||
|
||||
// If the left part is 'var x', emit code to define x if necessary using a
|
||||
// prolog opcode, but do not emit a pop. If it is 'let x', EnterBlockScope
|
||||
@ -6701,7 +6699,7 @@ frontend::EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
// Assign the destructuring arguments before defining any functions,
|
||||
// see bug 419662.
|
||||
MOZ_ASSERT(pnchild->isKind(PNK_SEMI));
|
||||
MOZ_ASSERT(pnchild->pn_kid->isKind(PNK_VAR) || pnchild->pn_kid->isKind(PNK_GLOBALCONST));
|
||||
MOZ_ASSERT(pnchild->pn_kid->isKind(PNK_VAR) || pnchild->pn_kid->isKind(PNK_CONST));
|
||||
if (!EmitTree(cx, bce, pnchild))
|
||||
return false;
|
||||
pnchild = pnchild->pn_next;
|
||||
@ -6834,7 +6832,7 @@ frontend::EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
break;
|
||||
|
||||
case PNK_VAR:
|
||||
case PNK_GLOBALCONST:
|
||||
case PNK_CONST:
|
||||
if (!EmitVariables(cx, bce, pn, InitializeVars))
|
||||
return false;
|
||||
break;
|
||||
@ -6997,8 +6995,6 @@ frontend::EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
break;
|
||||
|
||||
case PNK_LET:
|
||||
case PNK_CONST:
|
||||
MOZ_ASSERT_IF(pn->isKind(PNK_CONST), !pn->isArity(PN_BINARY));
|
||||
ok = pn->isArity(PN_BINARY)
|
||||
? EmitLet(cx, bce, pn)
|
||||
: EmitVariables(cx, bce, pn, InitializeVars);
|
||||
|
@ -667,8 +667,8 @@ class FullParseHandler
|
||||
uint16_t firstDominatingLexicalSlot)
|
||||
{
|
||||
MOZ_ASSERT(pn->isUsed());
|
||||
if (dn->isLexical() && dn->pn_cookie.slot() < firstDominatingLexicalSlot)
|
||||
pn->pn_dflags |= PND_LEXICAL;
|
||||
if (dn->isLet() && dn->pn_cookie.slot() < firstDominatingLexicalSlot)
|
||||
pn->pn_dflags |= PND_LET;
|
||||
}
|
||||
|
||||
static uintptr_t definitionToBits(Definition *dn) {
|
||||
|
@ -308,7 +308,7 @@ const char *
|
||||
Definition::kindString(Kind kind)
|
||||
{
|
||||
static const char * const table[] = {
|
||||
"", js_var_str, js_const_str, js_const_str, js_let_str, "argument", js_function_str, "unknown"
|
||||
"", js_var_str, js_const_str, js_let_str, js_function_str, "argument", "unknown"
|
||||
};
|
||||
|
||||
MOZ_ASSERT(unsigned(kind) <= unsigned(ARG));
|
||||
@ -505,7 +505,7 @@ Parser<FullParseHandler>::cloneLeftHandSide(ParseNode *opn)
|
||||
if (opn->isDefn()) {
|
||||
/* We copied some definition-specific state into pn. Clear it out. */
|
||||
pn->pn_cookie.makeFree();
|
||||
pn->pn_dflags &= ~(PND_LEXICAL | PND_BOUND);
|
||||
pn->pn_dflags &= ~(PND_LET | PND_BOUND);
|
||||
pn->setDefn(false);
|
||||
|
||||
handler.linkUseToDef(pn, (Definition *) opn);
|
||||
|
@ -114,7 +114,6 @@ class UpvarCookie
|
||||
F(CONTINUE) \
|
||||
F(VAR) \
|
||||
F(CONST) \
|
||||
F(GLOBALCONST) \
|
||||
F(WITH) \
|
||||
F(RETURN) \
|
||||
F(NEW) \
|
||||
@ -683,8 +682,7 @@ class ParseNode
|
||||
Definition *resolve();
|
||||
|
||||
/* PN_CODE and PN_NAME pn_dflags bits. */
|
||||
#define PND_LEXICAL 0x01 /* lexical (block-scoped) binding or use of a hoisted
|
||||
let or const */
|
||||
#define PND_LET 0x01 /* let (block-scoped) binding or use of a hoisted let */
|
||||
#define PND_CONST 0x02 /* const binding (orthogonal to let) */
|
||||
#define PND_ASSIGNED 0x04 /* set if ever LHS of assignment */
|
||||
#define PND_PLACEHOLDER 0x08 /* placeholder definition for lexdep */
|
||||
@ -766,7 +764,7 @@ class ParseNode
|
||||
|
||||
inline bool test(unsigned flag) const;
|
||||
|
||||
bool isLexical() const { return test(PND_LEXICAL) && !isUsed(); }
|
||||
bool isLet() const { return test(PND_LET) && !isUsed(); }
|
||||
bool isConst() const { return test(PND_CONST); }
|
||||
bool isPlaceholder() const { return test(PND_PLACEHOLDER); }
|
||||
bool isDeoptimized() const { return test(PND_DEOPTIMIZED); }
|
||||
@ -774,7 +772,7 @@ class ParseNode
|
||||
bool isClosed() const { return test(PND_CLOSED); }
|
||||
bool isBound() const { return test(PND_BOUND); }
|
||||
bool isImplicitArguments() const { return test(PND_IMPLICITARGUMENTS); }
|
||||
bool isHoistedLexicalUse() const { return test(PND_LEXICAL) && isUsed(); }
|
||||
bool isHoistedLetUse() const { return test(PND_LET) && isUsed(); }
|
||||
|
||||
/* True if pn is a parsenode representing a literal constant. */
|
||||
bool isLiteral() const {
|
||||
@ -1416,7 +1414,7 @@ struct Definition : public ParseNode
|
||||
return pn_cookie.isFree();
|
||||
}
|
||||
|
||||
enum Kind { MISSING = 0, VAR, GLOBALCONST, CONST, LET, ARG, NAMED_LAMBDA, PLACEHOLDER };
|
||||
enum Kind { MISSING = 0, VAR, CONST, LET, ARG, NAMED_LAMBDA, PLACEHOLDER };
|
||||
|
||||
bool canHaveInitializer() { return int(kind()) <= int(ARG); }
|
||||
|
||||
@ -1435,10 +1433,10 @@ struct Definition : public ParseNode
|
||||
return PLACEHOLDER;
|
||||
if (isOp(JSOP_GETARG))
|
||||
return ARG;
|
||||
if (isLexical())
|
||||
return isConst() ? CONST : LET;
|
||||
if (isConst())
|
||||
return GLOBALCONST;
|
||||
return CONST;
|
||||
if (isLet())
|
||||
return LET;
|
||||
return VAR;
|
||||
}
|
||||
};
|
||||
|
@ -122,7 +122,7 @@ MarkUsesAsHoistedLexical(ParseNode *pn)
|
||||
// Distinguish hoisted uses as a different JSOp for easier compilation.
|
||||
while ((pnu = *pnup) != nullptr && pnu->pn_blockid >= start) {
|
||||
MOZ_ASSERT(pnu->isUsed());
|
||||
pnu->pn_dflags |= PND_LEXICAL;
|
||||
pnu->pn_dflags |= PND_LET;
|
||||
pnup = &pnu->pn_link;
|
||||
}
|
||||
}
|
||||
@ -137,7 +137,7 @@ ParseContext<FullParseHandler>::define(TokenStream &ts,
|
||||
MOZ_ASSERT_IF(pn->isDefn(), pn->isPlaceholder());
|
||||
|
||||
Definition *prevDef = nullptr;
|
||||
if (kind == Definition::LET || kind == Definition::CONST)
|
||||
if (kind == Definition::LET)
|
||||
prevDef = decls_.lookupFirst(name);
|
||||
else
|
||||
MOZ_ASSERT(!decls_.lookupFirst(name));
|
||||
@ -148,8 +148,7 @@ ParseContext<FullParseHandler>::define(TokenStream &ts,
|
||||
if (prevDef) {
|
||||
ParseNode **pnup = &prevDef->dn_uses;
|
||||
ParseNode *pnu;
|
||||
unsigned start = (kind == Definition::LET || kind == Definition::CONST) ? pn->pn_blockid
|
||||
: bodyid;
|
||||
unsigned start = (kind == Definition::LET) ? pn->pn_blockid : bodyid;
|
||||
|
||||
while ((pnu = *pnup) != nullptr && pnu->pn_blockid >= start) {
|
||||
MOZ_ASSERT(pnu->pn_blockid >= bodyid);
|
||||
@ -171,7 +170,7 @@ ParseContext<FullParseHandler>::define(TokenStream &ts,
|
||||
pn->pn_dflags |= prevDef->pn_dflags & PND_CLOSED;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_IF(kind != Definition::LET && kind != Definition::CONST, !lexdeps->lookup(name));
|
||||
MOZ_ASSERT_IF(kind != Definition::LET, !lexdeps->lookup(name));
|
||||
pn->setDefn(true);
|
||||
pn->pn_dflags &= ~PND_PLACEHOLDER;
|
||||
if (kind == Definition::CONST)
|
||||
@ -198,7 +197,7 @@ ParseContext<FullParseHandler>::define(TokenStream &ts,
|
||||
return false;
|
||||
break;
|
||||
|
||||
case Definition::GLOBALCONST:
|
||||
case Definition::CONST:
|
||||
case Definition::VAR:
|
||||
if (sc->isFunctionBox()) {
|
||||
dn->setOp((js_CodeSpec[dn->getOp()].format & JOF_SET) ? JSOP_SETLOCAL : JSOP_GETLOCAL);
|
||||
@ -216,9 +215,8 @@ ParseContext<FullParseHandler>::define(TokenStream &ts,
|
||||
break;
|
||||
|
||||
case Definition::LET:
|
||||
case Definition::CONST:
|
||||
dn->setOp(JSOP_INITLEXICAL);
|
||||
dn->pn_dflags |= (PND_LEXICAL | PND_BOUND);
|
||||
dn->pn_dflags |= (PND_LET | PND_BOUND);
|
||||
MOZ_ASSERT(dn->pn_cookie.level() == staticLevel); /* see bindLet */
|
||||
if (atBodyLevel()) {
|
||||
if (!bodyLevelLexicals_.append(dn))
|
||||
@ -316,8 +314,7 @@ template <typename ParseHandler>
|
||||
void
|
||||
ParseContext<ParseHandler>::popLetDecl(JSAtom *atom)
|
||||
{
|
||||
MOZ_ASSERT(ParseHandler::getDefinitionKind(decls_.lookupFirst(atom)) == Definition::LET ||
|
||||
ParseHandler::getDefinitionKind(decls_.lookupFirst(atom)) == Definition::CONST);
|
||||
MOZ_ASSERT(ParseHandler::getDefinitionKind(decls_.lookupFirst(atom)) == Definition::LET);
|
||||
decls_.remove(atom);
|
||||
}
|
||||
|
||||
@ -341,7 +338,6 @@ AppendPackedBindings(const ParseContext<ParseHandler> *pc, const DeclVector &vec
|
||||
kind = Binding::VARIABLE;
|
||||
break;
|
||||
case Definition::CONST:
|
||||
case Definition::GLOBALCONST:
|
||||
kind = Binding::CONSTANT;
|
||||
break;
|
||||
case Definition::ARG:
|
||||
@ -1173,7 +1169,6 @@ struct BindData
|
||||
|
||||
JSOp op; /* prolog bytecode or nop */
|
||||
Binder binder; /* binder, discriminates u */
|
||||
bool isConst; /* const binding? */
|
||||
|
||||
struct LetData {
|
||||
explicit LetData(ExclusiveContext *cx) : blockObj(cx) {}
|
||||
@ -1182,21 +1177,18 @@ struct BindData
|
||||
unsigned overflow;
|
||||
} let;
|
||||
|
||||
void initLexical(VarContext varContext, StaticBlockObject *blockObj, unsigned overflow,
|
||||
bool isConst = false) {
|
||||
void initLet(VarContext varContext, StaticBlockObject *blockObj, unsigned overflow) {
|
||||
this->pn = ParseHandler::null();
|
||||
this->op = JSOP_INITLEXICAL;
|
||||
this->isConst = isConst;
|
||||
this->binder = Parser<ParseHandler>::bindLexical;
|
||||
this->binder = Parser<ParseHandler>::bindLet;
|
||||
this->let.varContext = varContext;
|
||||
this->let.blockObj = blockObj;
|
||||
this->let.overflow = overflow;
|
||||
}
|
||||
|
||||
void initVarOrGlobalConst(JSOp op) {
|
||||
void initVarOrConst(JSOp op) {
|
||||
this->op = op;
|
||||
this->isConst = op == JSOP_DEFCONST;
|
||||
this->binder = Parser<ParseHandler>::bindVarOrGlobalConst;
|
||||
this->binder = Parser<ParseHandler>::bindVarOrConst;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1297,7 +1289,7 @@ static bool
|
||||
IsNonDominatingInScopedSwitch(ParseContext<FullParseHandler> *pc, HandleAtom name,
|
||||
Definition *dn)
|
||||
{
|
||||
MOZ_ASSERT(dn->isLexical());
|
||||
MOZ_ASSERT(dn->isLet());
|
||||
StmtInfoPC *stmt = LexicalLookup(pc, name, nullptr, (StmtInfoPC *)nullptr);
|
||||
if (stmt && stmt->type == STMT_SWITCH)
|
||||
return dn->pn_cookie.slot() < stmt->firstDominatingLexicalInCase;
|
||||
@ -1306,9 +1298,9 @@ IsNonDominatingInScopedSwitch(ParseContext<FullParseHandler> *pc, HandleAtom nam
|
||||
|
||||
static void
|
||||
AssociateUsesWithOuterDefinition(ParseNode *pnu, Definition *dn, Definition *outer_dn,
|
||||
bool markUsesAsLexical)
|
||||
bool markUsesAsLet)
|
||||
{
|
||||
uint32_t dflags = markUsesAsLexical ? PND_LEXICAL : 0;
|
||||
uint32_t dflags = markUsesAsLet ? PND_LET : 0;
|
||||
while (true) {
|
||||
pnu->pn_lexdef = outer_dn;
|
||||
pnu->pn_dflags |= dflags;
|
||||
@ -1420,10 +1412,10 @@ Parser<FullParseHandler>::leaveFunction(ParseNode *fn, ParseContext<FullParseHan
|
||||
// from another case in a switch, those uses also need to
|
||||
// be marked as needing dead zone checks.
|
||||
RootedAtom name(context, atom);
|
||||
bool markUsesAsLexical = outer_dn->isLexical() &&
|
||||
(bodyLevelHoistedUse ||
|
||||
IsNonDominatingInScopedSwitch(outerpc, name, outer_dn));
|
||||
AssociateUsesWithOuterDefinition(pnu, dn, outer_dn, markUsesAsLexical);
|
||||
bool markUsesAsLet = outer_dn->isLet() &&
|
||||
(bodyLevelHoistedUse ||
|
||||
IsNonDominatingInScopedSwitch(outerpc, name, outer_dn));
|
||||
AssociateUsesWithOuterDefinition(pnu, dn, outer_dn, markUsesAsLet);
|
||||
}
|
||||
|
||||
outer_dn->pn_dflags |= dn->pn_dflags & ~PND_PLACEHOLDER;
|
||||
@ -1772,8 +1764,7 @@ Parser<FullParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
|
||||
MOZ_ASSERT(!dn->isUsed());
|
||||
MOZ_ASSERT(dn->isDefn());
|
||||
|
||||
bool throwRedeclarationError = dn->kind() == Definition::GLOBALCONST ||
|
||||
dn->kind() == Definition::CONST ||
|
||||
bool throwRedeclarationError = dn->kind() == Definition::CONST ||
|
||||
dn->kind() == Definition::LET;
|
||||
if (options().extraWarningsOption || throwRedeclarationError) {
|
||||
JSAutoByteString name;
|
||||
@ -2002,10 +1993,7 @@ Parser<SyntaxParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
|
||||
* function (thereby avoiding JSOP_DEFFUN and dynamic name lookup).
|
||||
*/
|
||||
if (DefinitionNode dn = pc->decls().lookupFirst(funName)) {
|
||||
if (dn == Definition::GLOBALCONST ||
|
||||
dn == Definition::CONST ||
|
||||
dn == Definition::LET)
|
||||
{
|
||||
if (dn == Definition::CONST) {
|
||||
JSAutoByteString name;
|
||||
if (!AtomToPrintableString(context, funName, &name) ||
|
||||
!report(ParseError, false, null(), JSMSG_REDECLARED_VAR,
|
||||
@ -2859,7 +2847,7 @@ Parser<ParseHandler>::matchLabel(MutableHandle<PropertyName*> label)
|
||||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::reportRedeclaration(Node pn, Definition::Kind redeclKind, HandlePropertyName name)
|
||||
Parser<ParseHandler>::reportRedeclaration(Node pn, bool isConst, HandlePropertyName name)
|
||||
{
|
||||
JSAutoByteString printable;
|
||||
if (!AtomToPrintableString(context, name, &printable))
|
||||
@ -2869,18 +2857,14 @@ Parser<ParseHandler>::reportRedeclaration(Node pn, Definition::Kind redeclKind,
|
||||
if (stmt && stmt->type == STMT_CATCH) {
|
||||
report(ParseError, false, pn, JSMSG_REDECLARED_CATCH_IDENTIFIER, printable.ptr());
|
||||
} else {
|
||||
if (redeclKind == Definition::ARG) {
|
||||
report(ParseError, false, pn, JSMSG_REDECLARED_PARAM, printable.ptr());
|
||||
} else {
|
||||
report(ParseError, false, pn, JSMSG_REDECLARED_VAR, Definition::kindString(redeclKind),
|
||||
printable.ptr());
|
||||
}
|
||||
report(ParseError, false, pn, JSMSG_REDECLARED_VAR, isConst ? "const" : "variable",
|
||||
printable.ptr());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Define a lexical binding in a block, let-expression, or comprehension scope. pc
|
||||
* Define a let-variable in a block, let-expression, or comprehension scope. pc
|
||||
* must already be in such a scope.
|
||||
*
|
||||
* Throw a SyntaxError if 'atom' is an invalid name. Otherwise create a
|
||||
@ -2890,8 +2874,8 @@ Parser<ParseHandler>::reportRedeclaration(Node pn, Definition::Kind redeclKind,
|
||||
*/
|
||||
template <>
|
||||
/* static */ bool
|
||||
Parser<FullParseHandler>::bindLexical(BindData<FullParseHandler> *data,
|
||||
HandlePropertyName name, Parser<FullParseHandler> *parser)
|
||||
Parser<FullParseHandler>::bindLet(BindData<FullParseHandler> *data,
|
||||
HandlePropertyName name, Parser<FullParseHandler> *parser)
|
||||
{
|
||||
ParseContext<FullParseHandler> *pc = parser->pc;
|
||||
ParseNode *pn = data->pn;
|
||||
@ -2928,34 +2912,25 @@ Parser<FullParseHandler>::bindLexical(BindData<FullParseHandler> *data,
|
||||
if (!pn->pn_cookie.set(parser->tokenStream, pc->staticLevel, index))
|
||||
return false;
|
||||
|
||||
Definition *dn = pc->decls().lookupFirst(name);
|
||||
Definition::Kind bindingKind = data->isConst ? Definition::CONST : Definition::LET;
|
||||
|
||||
/*
|
||||
* For bindings that are hoisted to the beginning of the block/function,
|
||||
* define() right now. Otherwise, delay define until PushLetScope.
|
||||
*/
|
||||
if (data->let.varContext == HoistVars) {
|
||||
Definition *dn = pc->decls().lookupFirst(name);
|
||||
if (dn && dn->pn_blockid == pc->blockid())
|
||||
return parser->reportRedeclaration(pn, dn->kind(), name);
|
||||
if (!pc->define(parser->tokenStream, name, pn, bindingKind))
|
||||
return parser->reportRedeclaration(pn, dn->isConst(), name);
|
||||
if (!pc->define(parser->tokenStream, name, pn, Definition::LET))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blockObj) {
|
||||
bool redeclared;
|
||||
RootedId id(cx, NameToId(name));
|
||||
RootedShape shape(cx, StaticBlockObject::addVar(cx, blockObj, id,
|
||||
data->isConst, index, &redeclared));
|
||||
RootedShape shape(cx, StaticBlockObject::addVar(cx, blockObj, id, index, &redeclared));
|
||||
if (!shape) {
|
||||
if (redeclared) {
|
||||
// The only way to be redeclared without a previous definition is if we're in a
|
||||
// comma separated list in a DontHoistVars block, so a let block of for header. In
|
||||
// that case, we must be redeclaring the same type of definition as we're trying to
|
||||
// make.
|
||||
Definition::Kind dnKind = dn ? dn->kind() : bindingKind;
|
||||
parser->reportRedeclaration(pn, dnKind, name);
|
||||
}
|
||||
if (redeclared)
|
||||
parser->reportRedeclaration(pn, false, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2973,8 +2948,8 @@ Parser<FullParseHandler>::bindLexical(BindData<FullParseHandler> *data,
|
||||
|
||||
template <>
|
||||
/* static */ bool
|
||||
Parser<SyntaxParseHandler>::bindLexical(BindData<SyntaxParseHandler> *data,
|
||||
HandlePropertyName name, Parser<SyntaxParseHandler> *parser)
|
||||
Parser<SyntaxParseHandler>::bindLet(BindData<SyntaxParseHandler> *data,
|
||||
HandlePropertyName name, Parser<SyntaxParseHandler> *parser)
|
||||
{
|
||||
if (!parser->checkStrictBinding(name, data->pn))
|
||||
return false;
|
||||
@ -3116,8 +3091,8 @@ OuterLet(ParseContext<ParseHandler> *pc, StmtInfoPC *stmt, HandleAtom atom)
|
||||
|
||||
template <typename ParseHandler>
|
||||
/* static */ bool
|
||||
Parser<ParseHandler>::bindVarOrGlobalConst(BindData<ParseHandler> *data,
|
||||
HandlePropertyName name, Parser<ParseHandler> *parser)
|
||||
Parser<ParseHandler>::bindVarOrConst(BindData<ParseHandler> *data,
|
||||
HandlePropertyName name, Parser<ParseHandler> *parser)
|
||||
{
|
||||
ExclusiveContext *cx = parser->context;
|
||||
ParseContext<ParseHandler> *pc = parser->pc;
|
||||
@ -3157,7 +3132,7 @@ Parser<ParseHandler>::bindVarOrGlobalConst(BindData<ParseHandler> *data,
|
||||
|
||||
if (defs.empty()) {
|
||||
return pc->define(parser->tokenStream, name, pn,
|
||||
isConstDecl ? Definition::GLOBALCONST : Definition::VAR);
|
||||
isConstDecl ? Definition::CONST : Definition::VAR);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3184,7 +3159,6 @@ Parser<ParseHandler>::bindVarOrGlobalConst(BindData<ParseHandler> *data,
|
||||
bool inCatchBody = (stmt && stmt->type == STMT_CATCH);
|
||||
bool error = (isConstDecl ||
|
||||
dn_kind == Definition::CONST ||
|
||||
dn_kind == Definition::GLOBALCONST ||
|
||||
(dn_kind == Definition::LET &&
|
||||
(!inCatchBody || OuterLet(pc, stmt, name))));
|
||||
|
||||
@ -3531,7 +3505,7 @@ Parser<FullParseHandler>::pushLetScope(HandleStaticBlockObject blockObj, StmtInf
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
pn->pn_dflags |= PND_LEXICAL;
|
||||
pn->pn_dflags |= PND_LET;
|
||||
|
||||
/* Populate the new scope with decls found in the head with updated blockid. */
|
||||
if (!ForEachLetDef(tokenStream, pc, blockObj, AddLetDecl(stmt->blockid)))
|
||||
@ -3718,10 +3692,10 @@ Parser<ParseHandler>::variables(ParseNodeKind kind, bool *psimple,
|
||||
* The four options here are:
|
||||
* - PNK_VAR: We're parsing var declarations.
|
||||
* - PNK_CONST: We're parsing const declarations.
|
||||
* - PNK_GLOBALCONST: We're parsing const declarations at toplevel (see bug 589119).
|
||||
* - PNK_LET: We are parsing a let declaration.
|
||||
* - PNK_CALL: We are parsing the head of a let block.
|
||||
*/
|
||||
MOZ_ASSERT(kind == PNK_VAR || kind == PNK_CONST || kind == PNK_LET || kind == PNK_GLOBALCONST);
|
||||
MOZ_ASSERT(kind == PNK_VAR || kind == PNK_CONST || kind == PNK_LET || kind == PNK_CALL);
|
||||
|
||||
/*
|
||||
* The simple flag is set if the declaration has the form 'var x', with
|
||||
@ -3729,11 +3703,7 @@ Parser<ParseHandler>::variables(ParseNodeKind kind, bool *psimple,
|
||||
*/
|
||||
MOZ_ASSERT_IF(psimple, *psimple);
|
||||
|
||||
JSOp op = JSOP_NOP;
|
||||
if (kind == PNK_VAR)
|
||||
op = JSOP_DEFVAR;
|
||||
else if (kind == PNK_GLOBALCONST)
|
||||
op = JSOP_DEFCONST;
|
||||
JSOp op = kind == PNK_LET ? JSOP_NOP : kind == PNK_VAR ? JSOP_DEFVAR : JSOP_DEFCONST;
|
||||
|
||||
Node pn = handler.newList(kind, null(), op);
|
||||
if (!pn)
|
||||
@ -3745,12 +3715,10 @@ Parser<ParseHandler>::variables(ParseNodeKind kind, bool *psimple,
|
||||
* this code will change soon.
|
||||
*/
|
||||
BindData<ParseHandler> data(context);
|
||||
if (kind == PNK_VAR || kind == PNK_GLOBALCONST) {
|
||||
data.initVarOrGlobalConst(op);
|
||||
} else {
|
||||
data.initLexical(varContext, blockObj, JSMSG_TOO_MANY_LOCALS,
|
||||
/* isConst = */ kind == PNK_CONST);
|
||||
}
|
||||
if (kind == PNK_LET)
|
||||
data.initLet(varContext, blockObj, JSMSG_TOO_MANY_LOCALS);
|
||||
else
|
||||
data.initVarOrConst(op);
|
||||
|
||||
bool first = true;
|
||||
Node pn2;
|
||||
@ -3783,8 +3751,7 @@ Parser<ParseHandler>::variables(ParseNodeKind kind, bool *psimple,
|
||||
|
||||
// See comment below for bindBeforeInitializer in the code that
|
||||
// handles the non-destructuring case.
|
||||
bool bindBeforeInitializer = (kind != PNK_LET && kind != PNK_CONST) ||
|
||||
parsingForInOrOfInit;
|
||||
bool bindBeforeInitializer = kind != PNK_LET || parsingForInOrOfInit;
|
||||
if (bindBeforeInitializer && !checkDestructuring(&data, pn2))
|
||||
return null();
|
||||
|
||||
@ -3821,10 +3788,10 @@ Parser<ParseHandler>::variables(ParseNodeKind kind, bool *psimple,
|
||||
}
|
||||
|
||||
RootedPropertyName name(context, tokenStream.currentName());
|
||||
pn2 = newBindingNode(name, kind == PNK_VAR || kind == PNK_GLOBALCONST, varContext);
|
||||
pn2 = newBindingNode(name, kind == PNK_VAR || kind == PNK_CONST, varContext);
|
||||
if (!pn2)
|
||||
return null();
|
||||
if (data.isConst)
|
||||
if (data.op == JSOP_DEFCONST)
|
||||
handler.setFlag(pn2, PND_CONST);
|
||||
data.pn = pn2;
|
||||
|
||||
@ -3845,7 +3812,7 @@ Parser<ParseHandler>::variables(ParseNodeKind kind, bool *psimple,
|
||||
// If we are not parsing a let declaration, bind the name
|
||||
// now. Otherwise we must wait until after parsing the initializing
|
||||
// assignment.
|
||||
bool bindBeforeInitializer = kind != PNK_LET && kind != PNK_CONST;
|
||||
bool bindBeforeInitializer = kind != PNK_LET;
|
||||
if (bindBeforeInitializer && !data.binder(&data, name, this))
|
||||
return null();
|
||||
|
||||
@ -3859,11 +3826,6 @@ Parser<ParseHandler>::variables(ParseNodeKind kind, bool *psimple,
|
||||
if (!handler.finishInitializerAssignment(pn2, init, data.op))
|
||||
return null();
|
||||
} else {
|
||||
if (data.isConst && !pc->parsingForInit) {
|
||||
report(ParseError, false, null(), JSMSG_BAD_CONST_DECL);
|
||||
return null();
|
||||
}
|
||||
|
||||
if (!data.binder(&data, name, this))
|
||||
return null();
|
||||
}
|
||||
@ -3881,7 +3843,7 @@ Parser<ParseHandler>::variables(ParseNodeKind kind, bool *psimple,
|
||||
|
||||
template <>
|
||||
ParseNode *
|
||||
Parser<FullParseHandler>::lexicalDeclaration(bool isConst)
|
||||
Parser<FullParseHandler>::letDeclaration()
|
||||
{
|
||||
handler.disableSyntaxParser();
|
||||
|
||||
@ -3901,8 +3863,7 @@ Parser<FullParseHandler>::lexicalDeclaration(bool isConst)
|
||||
*/
|
||||
StmtInfoPC *stmt = pc->topStmt;
|
||||
if (stmt && (!stmt->maybeScope() || stmt->isForLetBlock)) {
|
||||
report(ParseError, false, null(), JSMSG_LEXICAL_DECL_NOT_IN_BLOCK,
|
||||
isConst ? "const" : "let");
|
||||
report(ParseError, false, null(), JSMSG_LET_DECL_NOT_IN_BLOCK);
|
||||
return null();
|
||||
}
|
||||
|
||||
@ -3921,10 +3882,9 @@ Parser<FullParseHandler>::lexicalDeclaration(bool isConst)
|
||||
* conflicting slots. Forbid top-level let declarations to
|
||||
* prevent such conflicts from ever occurring.
|
||||
*/
|
||||
bool isGlobal = !pc->sc->isFunctionBox() && stmt == pc->topScopeStmt;
|
||||
if (options().selfHostingMode && isGlobal) {
|
||||
report(ParseError, false, null(), JSMSG_SELFHOSTED_TOP_LEVEL_LEXICAL,
|
||||
isConst ? "'const'" : "'let'");
|
||||
bool globalLet = !pc->sc->isFunctionBox() && stmt == pc->topScopeStmt;
|
||||
if (options().selfHostingMode && globalLet) {
|
||||
report(ParseError, false, null(), JSMSG_SELFHOSTED_TOP_LEVEL_LET);
|
||||
return null();
|
||||
}
|
||||
|
||||
@ -3942,12 +3902,7 @@ Parser<FullParseHandler>::lexicalDeclaration(bool isConst)
|
||||
* FIXME global-level lets are still considered vars until
|
||||
* other bugs are fixed.
|
||||
*/
|
||||
ParseNodeKind kind = PNK_LET;
|
||||
if (isGlobal)
|
||||
kind = isConst ? PNK_GLOBALCONST : PNK_VAR;
|
||||
else if (isConst)
|
||||
kind = PNK_CONST;
|
||||
pn = variables(kind);
|
||||
pn = variables(globalLet ? PNK_VAR : PNK_LET);
|
||||
if (!pn)
|
||||
return null();
|
||||
pn->pn_xflags |= PNX_POPVAR;
|
||||
@ -4007,8 +3962,7 @@ Parser<FullParseHandler>::lexicalDeclaration(bool isConst)
|
||||
pc->blockNode = pn1;
|
||||
}
|
||||
|
||||
pn = variables(isConst ? PNK_CONST : PNK_LET, nullptr,
|
||||
&pc->staticScope->as<StaticBlockObject>(), HoistVars);
|
||||
pn = variables(PNK_LET, nullptr, &pc->staticScope->as<StaticBlockObject>(), HoistVars);
|
||||
if (!pn)
|
||||
return null();
|
||||
pn->pn_xflags = PNX_POPVAR;
|
||||
@ -4019,7 +3973,7 @@ Parser<FullParseHandler>::lexicalDeclaration(bool isConst)
|
||||
|
||||
template <>
|
||||
SyntaxParseHandler::Node
|
||||
Parser<SyntaxParseHandler>::lexicalDeclaration(bool)
|
||||
Parser<SyntaxParseHandler>::letDeclaration()
|
||||
{
|
||||
JS_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return SyntaxParseHandler::NodeFailure;
|
||||
@ -4040,7 +3994,7 @@ Parser<FullParseHandler>::letStatement()
|
||||
pn = letBlock(LetStatement);
|
||||
MOZ_ASSERT_IF(pn, pn->isKind(PNK_LET) || pn->isKind(PNK_SEMI));
|
||||
} else {
|
||||
pn = lexicalDeclaration(/* isConst = */ false);
|
||||
pn = letDeclaration();
|
||||
}
|
||||
return pn;
|
||||
}
|
||||
@ -4297,7 +4251,8 @@ Parser<ParseHandler>::exportDeclaration()
|
||||
break;
|
||||
|
||||
case TOK_VAR:
|
||||
kid = variables(PNK_VAR);
|
||||
case TOK_CONST:
|
||||
kid = variables(tt == TOK_VAR ? PNK_VAR : PNK_CONST);
|
||||
if (!kid)
|
||||
return null();
|
||||
kid->pn_xflags = PNX_POPVAR;
|
||||
@ -4313,8 +4268,7 @@ Parser<ParseHandler>::exportDeclaration()
|
||||
// and fall through.
|
||||
tokenStream.ungetToken();
|
||||
case TOK_LET:
|
||||
case TOK_CONST:
|
||||
kid = lexicalDeclaration(tt == TOK_CONST);
|
||||
kid = letDeclaration();
|
||||
if (!kid)
|
||||
return null();
|
||||
break;
|
||||
@ -4458,7 +4412,7 @@ Parser<FullParseHandler>::isValidForStatementLHS(ParseNode *pn1, JSVersion versi
|
||||
if (isForDecl) {
|
||||
if (pn1->pn_count > 1)
|
||||
return false;
|
||||
if (pn1->isKind(PNK_CONST))
|
||||
if (pn1->isOp(JSOP_DEFCONST))
|
||||
return false;
|
||||
|
||||
// In JS 1.7 only, for (var [K, V] in EXPR) has a special meaning.
|
||||
@ -4496,22 +4450,6 @@ Parser<FullParseHandler>::isValidForStatementLHS(ParseNode *pn1, JSVersion versi
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkForHeadConstInitializers(ParseNode *pn1)
|
||||
{
|
||||
if (!pn1->isKind(PNK_CONST))
|
||||
return true;
|
||||
|
||||
for (ParseNode *assign = pn1->pn_head; assign; assign = assign->pn_next) {
|
||||
MOZ_ASSERT(assign->isKind(PNK_ASSIGN) || assign->isKind(PNK_NAME));
|
||||
if (assign->isKind(PNK_NAME) && !assign->isAssigned())
|
||||
return false;
|
||||
// PNK_ASSIGN nodes (destructuring assignment) are always assignments.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
ParseNode *
|
||||
Parser<FullParseHandler>::forStatement()
|
||||
@ -4571,11 +4509,11 @@ Parser<FullParseHandler>::forStatement()
|
||||
* clause of an ordinary for loop.
|
||||
*/
|
||||
pc->parsingForInit = true;
|
||||
if (tt == TOK_VAR) {
|
||||
if (tt == TOK_VAR || tt == TOK_CONST) {
|
||||
isForDecl = true;
|
||||
tokenStream.consumeKnownToken(tt);
|
||||
pn1 = variables(PNK_VAR);
|
||||
} else if (tt == TOK_LET || tt == TOK_CONST) {
|
||||
pn1 = variables(tt == TOK_VAR ? PNK_VAR : PNK_CONST);
|
||||
} else if (tt == TOK_LET) {
|
||||
handler.disableSyntaxParser();
|
||||
tokenStream.consumeKnownToken(tt);
|
||||
if (!tokenStream.peekToken(&tt))
|
||||
@ -4587,8 +4525,7 @@ Parser<FullParseHandler>::forStatement()
|
||||
blockObj = StaticBlockObject::create(context);
|
||||
if (!blockObj)
|
||||
return null();
|
||||
pn1 = variables(tt == TOK_CONST ? PNK_CONST: PNK_LET, nullptr, blockObj,
|
||||
DontHoistVars);
|
||||
pn1 = variables(PNK_LET, nullptr, blockObj, DontHoistVars);
|
||||
}
|
||||
} else {
|
||||
pn1 = expr();
|
||||
@ -4780,14 +4717,8 @@ Parser<FullParseHandler>::forStatement()
|
||||
if (blockObj) {
|
||||
/*
|
||||
* Desugar 'for (let A; B; C) D' into 'let (A) { for (; B; C) D }'
|
||||
* to induce the correct scoping for A. Ensure here that the previously
|
||||
* unchecked assignment mandate for const declarations holds.
|
||||
* to induce the correct scoping for A.
|
||||
*/
|
||||
if (!checkForHeadConstInitializers(pn1)) {
|
||||
report(ParseError, false, nullptr, JSMSG_BAD_CONST_DECL);
|
||||
return null();
|
||||
}
|
||||
|
||||
forLetImpliedBlock = pushLetScope(blockObj, &letStmt);
|
||||
if (!forLetImpliedBlock)
|
||||
return null();
|
||||
@ -4912,7 +4843,7 @@ Parser<SyntaxParseHandler>::forStatement()
|
||||
if (tt == TOK_VAR) {
|
||||
isForDecl = true;
|
||||
tokenStream.consumeKnownToken(tt);
|
||||
lhsNode = variables(PNK_VAR, &simpleForDecl);
|
||||
lhsNode = variables(tt == TOK_VAR ? PNK_VAR : PNK_CONST, &simpleForDecl);
|
||||
}
|
||||
else if (tt == TOK_CONST || tt == TOK_LET) {
|
||||
JS_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
@ -5581,8 +5512,8 @@ Parser<ParseHandler>::tryStatement()
|
||||
* scoped, not a property of a new Object instance. This is
|
||||
* an intentional change that anticipates ECMA Ed. 4.
|
||||
*/
|
||||
data.initLexical(HoistVars, &pc->staticScope->template as<StaticBlockObject>(),
|
||||
JSMSG_TOO_MANY_CATCH_VARS);
|
||||
data.initLet(HoistVars, &pc->staticScope->template as<StaticBlockObject>(),
|
||||
JSMSG_TOO_MANY_CATCH_VARS);
|
||||
MOZ_ASSERT(data.let.blockObj);
|
||||
|
||||
if (!tokenStream.getToken(&tt))
|
||||
@ -5709,10 +5640,9 @@ Parser<ParseHandler>::statement(bool canHaveDirectives)
|
||||
case TOK_CONST:
|
||||
if (!abortIfSyntaxParser())
|
||||
return null();
|
||||
return lexicalDeclaration(/* isConst = */ true);
|
||||
|
||||
// FALL THROUGH
|
||||
case TOK_VAR: {
|
||||
Node pn = variables(PNK_VAR);
|
||||
Node pn = variables(tt == TOK_CONST ? PNK_CONST : PNK_VAR);
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
@ -6689,8 +6619,7 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode *bodyExpr, unsigned
|
||||
return null();
|
||||
|
||||
MOZ_ASSERT(pc->staticScope && pc->staticScope == pn->pn_objbox->object);
|
||||
data.initLexical(HoistVars, &pc->staticScope->as<StaticBlockObject>(),
|
||||
JSMSG_ARRAY_INIT_TOO_BIG);
|
||||
data.initLet(HoistVars, &pc->staticScope->as<StaticBlockObject>(), JSMSG_ARRAY_INIT_TOO_BIG);
|
||||
|
||||
while (true) {
|
||||
/*
|
||||
@ -7133,7 +7062,7 @@ Parser<ParseHandler>::comprehensionFor(GeneratorKind comprehensionKind)
|
||||
RootedStaticBlockObject blockObj(context, StaticBlockObject::create(context));
|
||||
if (!blockObj)
|
||||
return null();
|
||||
data.initLexical(DontHoistVars, blockObj, JSMSG_TOO_MANY_LOCALS);
|
||||
data.initLet(DontHoistVars, blockObj, JSMSG_TOO_MANY_LOCALS);
|
||||
Node lhs = newName(name);
|
||||
if (!lhs)
|
||||
return null();
|
||||
|
@ -542,7 +542,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
Node tryStatement();
|
||||
Node debuggerStatement();
|
||||
|
||||
Node lexicalDeclaration(bool isConst);
|
||||
Node letDeclaration();
|
||||
Node letStatement();
|
||||
Node importDeclaration();
|
||||
Node exportDeclaration();
|
||||
@ -634,7 +634,6 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
|
||||
bool isValidForStatementLHS(Node pn1, JSVersion version, bool forDecl, bool forEach,
|
||||
ParseNodeKind headKind);
|
||||
bool checkForHeadConstInitializers(Node pn1);
|
||||
bool checkAndMarkAsIncOperand(Node kid, TokenKind tt, bool preorder);
|
||||
bool checkStrictAssignment(Node lhs);
|
||||
bool checkStrictBinding(PropertyName *name, Node pn);
|
||||
@ -668,16 +667,16 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
HandlePropertyName name, Parser<ParseHandler> *parser);
|
||||
|
||||
static bool
|
||||
bindLexical(BindData<ParseHandler> *data,
|
||||
HandlePropertyName name, Parser<ParseHandler> *parser);
|
||||
bindLet(BindData<ParseHandler> *data,
|
||||
HandlePropertyName name, Parser<ParseHandler> *parser);
|
||||
|
||||
static bool
|
||||
bindVarOrGlobalConst(BindData<ParseHandler> *data,
|
||||
HandlePropertyName name, Parser<ParseHandler> *parser);
|
||||
bindVarOrConst(BindData<ParseHandler> *data,
|
||||
HandlePropertyName name, Parser<ParseHandler> *parser);
|
||||
|
||||
static Node null() { return ParseHandler::null(); }
|
||||
|
||||
bool reportRedeclaration(Node pn, Definition::Kind redeclKind, HandlePropertyName name);
|
||||
bool reportRedeclaration(Node pn, bool isConst, HandlePropertyName name);
|
||||
bool reportBadReturn(Node pn, ParseReportKind kind, unsigned errnum, unsigned anonerrnum);
|
||||
DefinitionNode getOrCreateLexicalDependency(ParseContext<ParseHandler> *pc, JSAtom *atom);
|
||||
|
||||
|
@ -2,6 +2,7 @@ load(libdir + "asm.js");
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
assertAsmTypeFail(USE_ASM + "var i; function f(){} return f");
|
||||
assertAsmTypeFail(USE_ASM + "const i; function f(){} return f");
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "var i=0; function f(){} return f"))(), undefined);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "const i=0; function f(){} return f"))(), undefined);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "var i=42; function f(){ return i|0 } return f"))(), 42);
|
||||
|
@ -9,5 +9,5 @@
|
||||
for each (y in [])
|
||||
)
|
||||
)
|
||||
{const functional=undefined}
|
||||
{const functional}
|
||||
})()
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Binary: cache/js-dbg-64-fe91973cc783-linux
|
||||
// Flags:
|
||||
//
|
||||
const [x]='';
|
||||
const x;[x]='';
|
||||
for(;[] && false;){}
|
||||
|
@ -1 +1 @@
|
||||
Function("with([]){const x=0}")()
|
||||
Function("with([])const x=0")()
|
||||
|
@ -1,5 +0,0 @@
|
||||
// |jit-test| error: TypeError
|
||||
{
|
||||
const x = 0;
|
||||
function x() { }
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
// |jit-test| error: TypeError
|
||||
const x = 0;
|
||||
function x() { }
|
@ -1,5 +0,0 @@
|
||||
// |jit-test| error: TypeError
|
||||
{
|
||||
let x;
|
||||
function x() { }
|
||||
}
|
@ -9,4 +9,15 @@ function assertThrowsReferenceError(f) {
|
||||
}
|
||||
|
||||
assertThrowsReferenceError(function () { delete x; let x; });
|
||||
assertThrowsReferenceError(function () { delete x; const x = undefined; });
|
||||
|
||||
// FIXME do this unconditionally once bug 611388 lands.
|
||||
function constIsLexical() {
|
||||
try {
|
||||
(function () { z++; const z; })();
|
||||
return false;
|
||||
} catch (e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (constIsLexical())
|
||||
assertThrowsReferenceError(function () { delete x; const x; });
|
||||
|
@ -10,4 +10,15 @@ function assertThrowsReferenceError(f) {
|
||||
|
||||
// TDZ is effectful, don't optimize out x.
|
||||
assertThrowsReferenceError(function () { x; let x; });
|
||||
assertThrowsReferenceError(function () { x; const x = undefined; });
|
||||
|
||||
// FIXME do this unconditionally once bug 611388 lands.
|
||||
function constIsLexical() {
|
||||
try {
|
||||
(function () { z++; const z; })();
|
||||
return false;
|
||||
} catch (e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (constIsLexical())
|
||||
assertThrowsReferenceError(function () { x; const x; });
|
||||
|
@ -235,10 +235,10 @@ test("const x = 1 @");
|
||||
test("const x = 1 + @");
|
||||
test("const x = 1 + 2 @");
|
||||
test("const x = 1 + 2, @");
|
||||
test("const x = 1 + 2, y = 0@");
|
||||
test("const x = 1 + 2, y = 0, @");
|
||||
test("const x = 1 + 2, y = 0, z = 0 @");
|
||||
test("const x = 1 + 2, y = 0, z = 0; @");
|
||||
test("const x = 1 + 2, y @");
|
||||
test("const x = 1 + 2, y, @");
|
||||
test("const x = 1 + 2, y, z @");
|
||||
test("const x = 1 + 2, y, z; @");
|
||||
|
||||
test("const [ @");
|
||||
test("const [ x @");
|
||||
|
@ -1,4 +1,4 @@
|
||||
with ({b:1}) {
|
||||
const [ b ] = [];
|
||||
assertEq(b, undefined);
|
||||
}
|
||||
assertEq(b, undefined);
|
||||
|
@ -1,5 +1,3 @@
|
||||
// |jit-test| error: ReferenceError
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new g.Debugger(this);
|
||||
|
||||
|
@ -110,7 +110,7 @@ MSG_DEF(JSMSG_BAD_PROTOTYPE, 1, JSEXN_TYPEERR, "'prototype' property o
|
||||
MSG_DEF(JSMSG_IN_NOT_OBJECT, 1, JSEXN_TYPEERR, "invalid 'in' operand {0}")
|
||||
MSG_DEF(JSMSG_TOO_MANY_CON_SPREADARGS, 0, JSEXN_RANGEERR, "too many constructor arguments")
|
||||
MSG_DEF(JSMSG_TOO_MANY_FUN_SPREADARGS, 0, JSEXN_RANGEERR, "too many function arguments")
|
||||
MSG_DEF(JSMSG_UNINITIALIZED_LEXICAL, 1, JSEXN_REFERENCEERR, "can't access lexical declaration `{0}' before initialization")
|
||||
MSG_DEF(JSMSG_UNINITIALIZED_LEXICAL, 1, JSEXN_REFERENCEERR, "can't access let declaration `{0}' before initialization")
|
||||
|
||||
// Date
|
||||
MSG_DEF(JSMSG_INVALID_DATE, 0, JSEXN_RANGEERR, "invalid date")
|
||||
@ -181,7 +181,6 @@ MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 1, JSEXN_SYNTAXERR, "missing keyword 'as'
|
||||
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")
|
||||
MSG_DEF(JSMSG_BAD_CONST_DECL, 0, JSEXN_SYNTAXERR, "missing = in const declaration")
|
||||
MSG_DEF(JSMSG_BAD_CONTINUE, 0, JSEXN_SYNTAXERR, "continue must be inside loop")
|
||||
MSG_DEF(JSMSG_BAD_DESTRUCT_ASS, 0, JSEXN_REFERENCEERR, "invalid destructuring assignment operator")
|
||||
MSG_DEF(JSMSG_BAD_DESTRUCT_TARGET, 0, JSEXN_SYNTAXERR, "invalid destructuring target")
|
||||
@ -245,7 +244,7 @@ MSG_DEF(JSMSG_INVALID_FOR_OF_INIT, 0, JSEXN_SYNTAXERR, "for-of loop variable
|
||||
MSG_DEF(JSMSG_IN_AFTER_FOR_NAME, 0, JSEXN_SYNTAXERR, "missing 'in' or 'of' after for")
|
||||
MSG_DEF(JSMSG_LABEL_NOT_FOUND, 0, JSEXN_SYNTAXERR, "label not found")
|
||||
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_LET_DECL_NOT_IN_BLOCK, 0, JSEXN_SYNTAXERR, "let declaration not directly within block")
|
||||
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'")
|
||||
@ -286,7 +285,7 @@ MSG_DEF(JSMSG_REDECLARED_CATCH_IDENTIFIER, 1, JSEXN_TYPEERR, "redeclaration of i
|
||||
MSG_DEF(JSMSG_REDECLARED_PARAM, 1, JSEXN_TYPEERR, "redeclaration of formal parameter {0}")
|
||||
MSG_DEF(JSMSG_RESERVED_ID, 1, JSEXN_SYNTAXERR, "{0} is a reserved identifier")
|
||||
MSG_DEF(JSMSG_REST_WITH_DEFAULT, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default")
|
||||
MSG_DEF(JSMSG_SELFHOSTED_TOP_LEVEL_LEXICAL, 1, JSEXN_SYNTAXERR, "self-hosted code cannot contain top-level {0} declarations")
|
||||
MSG_DEF(JSMSG_SELFHOSTED_TOP_LEVEL_LET,0, JSEXN_SYNTAXERR, "self-hosted code cannot contain top-level 'let' declarations")
|
||||
MSG_DEF(JSMSG_SELFHOSTED_UNBOUND_NAME, 0, JSEXN_TYPEERR, "self-hosted code may not contain unbound name lookups")
|
||||
MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition")
|
||||
MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer")
|
||||
|
@ -1732,7 +1732,7 @@ class ASTSerializer
|
||||
bool sourceElement(ParseNode *pn, MutableHandleValue dst);
|
||||
|
||||
bool declaration(ParseNode *pn, MutableHandleValue dst);
|
||||
bool variableDeclaration(ParseNode *pn, bool lexical, MutableHandleValue dst);
|
||||
bool variableDeclaration(ParseNode *pn, bool let, MutableHandleValue dst);
|
||||
bool variableDeclarator(ParseNode *pn, MutableHandleValue dst);
|
||||
bool let(ParseNode *pn, bool expr, MutableHandleValue dst);
|
||||
bool importDeclaration(ParseNode *pn, MutableHandleValue dst);
|
||||
@ -2001,7 +2001,6 @@ ASTSerializer::declaration(ParseNode *pn, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_FUNCTION) ||
|
||||
pn->isKind(PNK_VAR) ||
|
||||
pn->isKind(PNK_GLOBALCONST) ||
|
||||
pn->isKind(PNK_LET) ||
|
||||
pn->isKind(PNK_CONST));
|
||||
|
||||
@ -2010,28 +2009,21 @@ ASTSerializer::declaration(ParseNode *pn, MutableHandleValue dst)
|
||||
return function(pn, AST_FUNC_DECL, dst);
|
||||
|
||||
case PNK_VAR:
|
||||
case PNK_GLOBALCONST:
|
||||
case PNK_CONST:
|
||||
return variableDeclaration(pn, false, dst);
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(pn->isKind(PNK_LET) || pn->isKind(PNK_CONST));
|
||||
MOZ_ASSERT(pn->isKind(PNK_LET));
|
||||
return variableDeclaration(pn, true, dst);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::variableDeclaration(ParseNode *pn, bool lexical, MutableHandleValue dst)
|
||||
ASTSerializer::variableDeclaration(ParseNode *pn, bool let, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT_IF(lexical, pn->isKind(PNK_LET) || pn->isKind(PNK_CONST));
|
||||
MOZ_ASSERT_IF(!lexical, pn->isKind(PNK_VAR) || pn->isKind(PNK_GLOBALCONST));
|
||||
MOZ_ASSERT(let ? pn->isKind(PNK_LET) : (pn->isKind(PNK_VAR) || pn->isKind(PNK_CONST)));
|
||||
|
||||
VarDeclKind kind = VARDECL_ERR;
|
||||
// Treat both the toplevel const binding (secretly var-like) and the lexical const
|
||||
// the same way
|
||||
if (lexical)
|
||||
kind = pn->isKind(PNK_LET) ? VARDECL_LET : VARDECL_CONST;
|
||||
else
|
||||
kind = pn->isKind(PNK_VAR) ? VARDECL_VAR : VARDECL_CONST;
|
||||
VarDeclKind kind = let ? VARDECL_LET : pn->isKind(PNK_VAR) ? VARDECL_VAR : VARDECL_CONST;
|
||||
|
||||
NodeVector dtors(cx);
|
||||
if (!dtors.reserve(pn->pn_count))
|
||||
@ -2174,7 +2166,6 @@ ASTSerializer::exportDeclaration(ParseNode *pn, MutableHandleValue dst)
|
||||
|
||||
case PNK_VAR:
|
||||
case PNK_CONST:
|
||||
case PNK_GLOBALCONST:
|
||||
case PNK_LET:
|
||||
if (!variableDeclaration(kid, kind == PNK_LET, &decl))
|
||||
return false;
|
||||
@ -2317,7 +2308,7 @@ ASTSerializer::forInit(ParseNode *pn, MutableHandleValue dst)
|
||||
return true;
|
||||
}
|
||||
|
||||
return (pn->isKind(PNK_VAR) || pn->isKind(PNK_GLOBALCONST))
|
||||
return (pn->isKind(PNK_VAR) || pn->isKind(PNK_CONST))
|
||||
? variableDeclaration(pn, false, dst)
|
||||
: expression(pn, dst);
|
||||
}
|
||||
@ -2350,11 +2341,10 @@ ASTSerializer::statement(ParseNode *pn, MutableHandleValue dst)
|
||||
switch (pn->getKind()) {
|
||||
case PNK_FUNCTION:
|
||||
case PNK_VAR:
|
||||
case PNK_GLOBALCONST:
|
||||
case PNK_CONST:
|
||||
return declaration(pn, dst);
|
||||
|
||||
case PNK_LET:
|
||||
case PNK_CONST:
|
||||
return pn->isArity(PN_BINARY)
|
||||
? let(pn, false, dst)
|
||||
: declaration(pn, dst);
|
||||
|
@ -129,11 +129,11 @@ Bindings::initWithTemporaryStorage(ExclusiveContext *cx, InternalBindingsHandle
|
||||
if (bi->aliased()) {
|
||||
// Per ES6, lexical bindings cannot be accessed until
|
||||
// initialized. Remember the first aliased slot that is a
|
||||
// body-level lexical, so that they may be initialized to sentinel
|
||||
// body-level let, so that they may be initialized to sentinel
|
||||
// magic values.
|
||||
if (numBodyLevelLexicals > 0 &&
|
||||
nslots < aliasedBodyLevelLexicalBegin &&
|
||||
bi.isBodyLevelLexical() &&
|
||||
bi->kind() == Binding::VARIABLE &&
|
||||
bi.localIndex() >= numVars)
|
||||
{
|
||||
aliasedBodyLevelLexicalBegin = nslots;
|
||||
|
@ -1740,11 +1740,6 @@ class BindingIter
|
||||
MOZ_ASSERT(i_ >= bindings_->numArgs());
|
||||
return i_ - bindings_->numArgs();
|
||||
}
|
||||
bool isBodyLevelLexical() const {
|
||||
MOZ_ASSERT(!done());
|
||||
const Binding &binding = **this;
|
||||
return binding.kind() != Binding::ARGUMENT;
|
||||
}
|
||||
|
||||
const Binding &operator*() const { MOZ_ASSERT(!done()); return bindings_->bindingArray()[i_]; }
|
||||
const Binding *operator->() const { MOZ_ASSERT(!done()); return &bindings_->bindingArray()[i_]; }
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
try {
|
||||
evalcx("Object.freeze(this); eval('const q = undefined;')");
|
||||
evalcx("Object.freeze(this); eval('const q;')");
|
||||
} catch (e) {
|
||||
assertEq(e.message, "({lazy:false}) is not extensible");
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ function test()
|
||||
|
||||
for (var i = 0; i < limit; i++)
|
||||
{
|
||||
eval('const pv' + i + ' = undefined;');
|
||||
eval('const pv' + i + ';');
|
||||
}
|
||||
|
||||
reportCompare(expect, actual, summary);
|
||||
|
@ -21,7 +21,7 @@ var limit = 2 << 16;
|
||||
|
||||
for (var i = 0; i < limit; i++)
|
||||
{
|
||||
eval('const pv' + i + ' = undefined;');
|
||||
eval('const pv' + i + ';');
|
||||
}
|
||||
|
||||
reportCompare(expect, actual, summary);
|
||||
|
@ -14,7 +14,7 @@ printStatus (summary);
|
||||
|
||||
jit(true);
|
||||
|
||||
const c = undefined; (function() { for (var j=0;j<5;++j) { c = 1; } })();
|
||||
const c; (function() { for (var j=0;j<5;++j) { c = 1; } })();
|
||||
|
||||
jit(false);
|
||||
|
||||
|
@ -19,8 +19,8 @@ function test()
|
||||
enterFunc ('test');
|
||||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
(function() { for each(x in y) { } const x = undefined; });
|
||||
|
||||
(function() { for each(x in y) { } const x; });
|
||||
|
||||
reportCompare(expect, actual, summary);
|
||||
|
||||
|
@ -20,6 +20,7 @@ function test()
|
||||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
expect = /TypeError: redeclaration of const b/;
|
||||
try
|
||||
{
|
||||
eval('(function() { let(x = 1) { const b = 2 }; let b = 3; })');
|
||||
@ -29,7 +30,7 @@ function test()
|
||||
actual = ex + '';
|
||||
}
|
||||
|
||||
reportCompare(expect, actual, summary);
|
||||
reportMatch(expect, actual, summary);
|
||||
|
||||
exitFunc ('test');
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ function test()
|
||||
try
|
||||
{
|
||||
actual = 'No Error';
|
||||
(function () { f(x = yield); const x = undefined; });
|
||||
(function () { f(x = yield); const x; });
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
|
@ -46,7 +46,7 @@ function test()
|
||||
// =====
|
||||
|
||||
for(
|
||||
const NaN = undefined;
|
||||
const NaN;
|
||||
this.__defineSetter__("x4", function(){});
|
||||
(eval("", (p={})))) let ({} = (((x ))(function ([]) {})), x1) y;
|
||||
|
||||
|
@ -25,7 +25,7 @@ function test()
|
||||
expect = 'TypeError: redeclaration of formal parameter e';
|
||||
try
|
||||
{
|
||||
eval('(function (e) { var e; const e = undefined; });');
|
||||
eval('(function (e) { var e; const e; });');
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
|
@ -22,7 +22,7 @@ function test()
|
||||
|
||||
// ------- Comment #101 From Gary Kwong [:nth10sd]
|
||||
|
||||
uneval(function(){with({functional: []}){x5, y = this;const y = undefined }});
|
||||
uneval(function(){with({functional: []}){x5, y = this;const y }});
|
||||
// Assertion failure: strcmp(rval, with_cookie) == 0, at ../jsopcode.cpp:2567
|
||||
|
||||
reportCompare(expect, actual, summary);
|
||||
|
@ -32,9 +32,9 @@ function test()
|
||||
function f() {
|
||||
"" + (function(){
|
||||
for( ; [function(){}] ; x = 0)
|
||||
with({x: ""}) {
|
||||
with({x: ""})
|
||||
const x = []
|
||||
}});
|
||||
});
|
||||
}
|
||||
f();
|
||||
|
||||
|
@ -22,11 +22,11 @@ function test()
|
||||
|
||||
// ------- Comment #112 From Jesse Ruderman
|
||||
|
||||
expect = 'ReferenceError: can\'t access lexical declaration `q\' before initialization';
|
||||
expect = 'TypeError: q is not a function';
|
||||
|
||||
try
|
||||
{
|
||||
q = new Function("(function() { q(3); })(); const q = undefined;"); q();
|
||||
q = new Function("(function() { q(3); })(); const q;"); q();
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
|
@ -28,7 +28,7 @@ function test()
|
||||
|
||||
try
|
||||
{
|
||||
eval('x; function x(){}; const x = undefined;');
|
||||
eval('x; function x(){}; const x;');
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
@ -46,7 +46,7 @@ function test()
|
||||
// =====
|
||||
try
|
||||
{
|
||||
(function(){(yield []) (function(){with({}){x} }); const x = undefined;})();
|
||||
(function(){(yield []) (function(){with({}){x} }); const x;})();
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
@ -81,7 +81,7 @@ function test()
|
||||
// =====
|
||||
try
|
||||
{
|
||||
eval('(function(){{for(c in (function (){ for(x in (x1))window} )()) {const x = undefined;} }})();');
|
||||
eval('(function(){{for(c in (function (){ for(x in (x1))window} )()) {const x;} }})();');
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
|
@ -22,7 +22,7 @@ function test()
|
||||
printStatus (summary);
|
||||
|
||||
// crash [@ js_Interpret]
|
||||
(eval("(function(){ this.watch(\"x\", function () { new function ()y } ); const y = undefined });"))();
|
||||
(eval("(function(){ this.watch(\"x\", function () { new function ()y } ); const y });"))();
|
||||
x = NaN;
|
||||
reportCompare(expect, actual, summary + ': 2');
|
||||
|
||||
|
@ -21,7 +21,7 @@ function test()
|
||||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
expect = 'TypeError: redeclaration of var e';
|
||||
expect = 'TypeError: redeclaration of variable e';
|
||||
try
|
||||
{
|
||||
eval('{ var e = 3; let e = ""; } print(typeof e);');
|
||||
|
@ -24,7 +24,7 @@ function test()
|
||||
expect = 'SyntaxError: invalid for/in left-hand side';
|
||||
try
|
||||
{
|
||||
eval('const x = undefined; for (x in []);');
|
||||
eval('const x; for (x in []);');
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
|
@ -21,8 +21,7 @@ function test()
|
||||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
let x;
|
||||
with({x: (x -= 0)}){([]); const x = undefined; }
|
||||
with({x: (x -= 0)}){([]); const x }
|
||||
|
||||
reportCompare(expect, actual, summary);
|
||||
|
||||
|
@ -26,19 +26,19 @@ assertEq(testLenientAndStrict('let x,arguments;',
|
||||
parsesSuccessfully,
|
||||
parseRaisesException(SyntaxError)),
|
||||
true);
|
||||
assertEq(testLenientAndStrict('const eval = undefined;',
|
||||
assertEq(testLenientAndStrict('const eval;',
|
||||
parsesSuccessfully,
|
||||
parseRaisesException(SyntaxError)),
|
||||
true);
|
||||
assertEq(testLenientAndStrict('const x = undefined,eval = undefined;',
|
||||
assertEq(testLenientAndStrict('const x,eval;',
|
||||
parsesSuccessfully,
|
||||
parseRaisesException(SyntaxError)),
|
||||
true);
|
||||
assertEq(testLenientAndStrict('const arguments = undefined;',
|
||||
assertEq(testLenientAndStrict('const arguments;',
|
||||
parsesSuccessfully,
|
||||
parseRaisesException(SyntaxError)),
|
||||
true);
|
||||
assertEq(testLenientAndStrict('const x = undefined,arguments = undefined;',
|
||||
assertEq(testLenientAndStrict('const x,arguments;',
|
||||
parsesSuccessfully,
|
||||
parseRaisesException(SyntaxError)),
|
||||
true);
|
||||
|
@ -30,7 +30,7 @@ function assertRedeclarationErrorThrown(expression)
|
||||
}
|
||||
}
|
||||
|
||||
assertRedeclarationErrorThrown("try {} catch(e) { const e = undefined; }");
|
||||
assertRedeclarationErrorThrown("try {} catch(e) { const e; }");
|
||||
assertRedeclarationErrorThrown("try {} catch(e) { let e; }");
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
|
@ -686,10 +686,6 @@ testParamPatternCombinations(function(n) ("[a" + n + ", ..." + "b" + n + "]"),
|
||||
function testVarPatternCombinations(makePattSrc, makePattPatt) {
|
||||
var pattSrcs = makePatternCombinations(function(n) ("x" + n), makePattSrc);
|
||||
var pattPatts = makePatternCombinations(function(n) ({ id: ident("x" + n), init: null }), makePattPatt);
|
||||
// It's illegal to have uninitialized const declarations, so we need a
|
||||
// separate set of patterns and sources.
|
||||
var constSrcs = makePatternCombinations(function(n) ("x" + n + " = undefined"), makePattSrc);
|
||||
var constPatts = makePatternCombinations(function(n) ({ id: ident("x" + n), init: ident("undefined") }), makePattPatt);
|
||||
|
||||
for (var i = 0; i < pattSrcs.length; i++) {
|
||||
// variable declarations in blocks
|
||||
@ -699,15 +695,15 @@ function testVarPatternCombinations(makePattSrc, makePattPatt) {
|
||||
assertLocalDecl("let " + pattSrcs[i].join(",") + ";", letDecl(pattPatts[i]));
|
||||
assertBlockDecl("let " + pattSrcs[i].join(",") + ";", letDecl(pattPatts[i]));
|
||||
|
||||
assertDecl("const " + constSrcs[i].join(",") + ";", constDecl(constPatts[i]));
|
||||
assertDecl("const " + pattSrcs[i].join(",") + ";", constDecl(pattPatts[i]));
|
||||
|
||||
// variable declarations in for-loop heads
|
||||
assertStmt("for (var " + pattSrcs[i].join(",") + "; foo; bar);",
|
||||
forStmt(varDecl(pattPatts[i]), ident("foo"), ident("bar"), emptyStmt));
|
||||
assertStmt("for (let " + pattSrcs[i].join(",") + "; foo; bar);",
|
||||
letStmt(pattPatts[i], forStmt(null, ident("foo"), ident("bar"), emptyStmt)));
|
||||
assertStmt("for (const " + constSrcs[i].join(",") + "; foo; bar);",
|
||||
letStmt(constPatts[i], forStmt(null, ident("foo"), ident("bar"), emptyStmt)));
|
||||
assertStmt("for (const " + pattSrcs[i].join(",") + "; foo; bar);",
|
||||
forStmt(constDecl(pattPatts[i]), ident("foo"), ident("bar"), emptyStmt));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1079,7 +1075,7 @@ assertGlobalStmt("for (;;) continue", forStmt(null, null, null, 15), { continueS
|
||||
|
||||
assertBlockDecl("var x", "var", { variableDeclaration: function(kind) kind });
|
||||
assertBlockDecl("let x", "let", { variableDeclaration: function(kind) kind });
|
||||
assertBlockDecl("const x = undefined", "const", { variableDeclaration: function(kind) kind });
|
||||
assertBlockDecl("const x", "const", { variableDeclaration: function(kind) kind });
|
||||
assertBlockDecl("function f() { }", "function", { functionDeclaration: function() "function" });
|
||||
|
||||
assertGlobalExpr("(x,y,z)", 1, { sequenceExpression: function() 1 });
|
||||
|
@ -682,7 +682,7 @@ StaticBlockObject::create(ExclusiveContext *cx)
|
||||
|
||||
/* static */ Shape *
|
||||
StaticBlockObject::addVar(ExclusiveContext *cx, Handle<StaticBlockObject*> block, HandleId id,
|
||||
bool constant, unsigned index, bool *redeclared)
|
||||
unsigned index, bool *redeclared)
|
||||
{
|
||||
MOZ_ASSERT(JSID_IS_ATOM(id));
|
||||
MOZ_ASSERT(index < LOCAL_INDEX_LIMIT);
|
||||
@ -701,13 +701,11 @@ StaticBlockObject::addVar(ExclusiveContext *cx, Handle<StaticBlockObject*> block
|
||||
* block's shape later.
|
||||
*/
|
||||
uint32_t slot = JSSLOT_FREE(&BlockObject::class_) + index;
|
||||
uint32_t readonly = constant ? JSPROP_READONLY : 0;
|
||||
uint32_t propFlags = readonly | JSPROP_ENUMERATE | JSPROP_PERMANENT;
|
||||
return NativeObject::addPropertyInternal<SequentialExecution>(cx, block, id,
|
||||
/* getter = */ nullptr,
|
||||
/* setter = */ nullptr,
|
||||
slot,
|
||||
propFlags,
|
||||
JSPROP_ENUMERATE | JSPROP_PERMANENT,
|
||||
/* attrs = */ 0,
|
||||
spp,
|
||||
/* allowDictionary = */ false);
|
||||
@ -775,20 +773,18 @@ js::XDRStaticBlockObject(XDRState<mode> *xdr, HandleObject enclosingScope,
|
||||
? AtomToId(atom)
|
||||
: INT_TO_JSID(i));
|
||||
|
||||
uint32_t propFlags;
|
||||
if (!xdr->codeUint32(&propFlags))
|
||||
return false;
|
||||
|
||||
bool readonly = !!(propFlags & 1);
|
||||
|
||||
bool redeclared;
|
||||
if (!StaticBlockObject::addVar(cx, obj, id, readonly, i, &redeclared)) {
|
||||
if (!StaticBlockObject::addVar(cx, obj, id, i, &redeclared)) {
|
||||
MOZ_ASSERT(!redeclared);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool aliased = !!(propFlags >> 1);
|
||||
obj->setAliased(i, aliased);
|
||||
uint32_t aliased;
|
||||
if (!xdr->codeUint32(&aliased))
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(aliased == 0 || aliased == 1);
|
||||
obj->setAliased(i, !!aliased);
|
||||
}
|
||||
} else {
|
||||
AutoShapeVector shapes(cx);
|
||||
@ -815,10 +811,8 @@ js::XDRStaticBlockObject(XDRState<mode> *xdr, HandleObject enclosingScope,
|
||||
if (!XDRAtom(xdr, &atom))
|
||||
return false;
|
||||
|
||||
bool aliased = obj->isAliased(i);
|
||||
bool readonly = !shape->writable();
|
||||
uint32_t propFlags = (aliased << 1) | readonly;
|
||||
if (!xdr->codeUint32(&propFlags))
|
||||
uint32_t aliased = obj->isAliased(i);
|
||||
if (!xdr->codeUint32(&aliased))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -856,7 +850,7 @@ CloneStaticBlockObject(JSContext *cx, HandleObject enclosingScope, Handle<Static
|
||||
unsigned i = srcBlock->shapeToIndex(**p);
|
||||
|
||||
bool redeclared;
|
||||
if (!StaticBlockObject::addVar(cx, clone, id, !(*p)->writable(), i, &redeclared)) {
|
||||
if (!StaticBlockObject::addVar(cx, clone, id, i, &redeclared)) {
|
||||
MOZ_ASSERT(!redeclared);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -569,7 +569,7 @@ class StaticBlockObject : public BlockObject
|
||||
static const unsigned LOCAL_INDEX_LIMIT = JS_BIT(16);
|
||||
|
||||
static Shape *addVar(ExclusiveContext *cx, Handle<StaticBlockObject*> block, HandleId id,
|
||||
bool constant, unsigned index, bool *redeclared);
|
||||
unsigned index, bool *redeclared);
|
||||
};
|
||||
|
||||
class ClonedBlockObject : public BlockObject
|
||||
|
@ -34,7 +34,7 @@ namespace js {
|
||||
* Nightly) and without (all others). FIXME: Bug 1066322 - Enable ES6 symbols
|
||||
* in all builds.
|
||||
*/
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 192;
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 190;
|
||||
static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above");
|
||||
static const uint32_t XDR_BYTECODE_VERSION =
|
||||
uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND
|
||||
|
@ -19,18 +19,16 @@
|
||||
|
||||
// Boilerplate used to be able to import this module both from the main
|
||||
// thread and from worker threads.
|
||||
|
||||
// Since const is lexically scoped, hoist the
|
||||
// conditionally-useful definition ourselves.
|
||||
const Cu = typeof Components != "undefined" ? Components.utils : undefined;
|
||||
const Ci = typeof Components != "undefined" ? Components.interfaces : undefined;
|
||||
const Cc = typeof Components != "undefined" ? Components.classes : undefined;
|
||||
if (typeof Components != "undefined") {
|
||||
// Global definition of |exports|, to keep everybody happy.
|
||||
// In non-main thread, |exports| is provided by the module
|
||||
// loader.
|
||||
this.exports = {};
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm", this);
|
||||
}
|
||||
|
||||
|
@ -410,8 +410,9 @@ function shutdownPlaces(aKeepAliveConnection)
|
||||
}
|
||||
|
||||
const FILENAME_BOOKMARKS_HTML = "bookmarks.html";
|
||||
const FILENAME_BOOKMARKS_JSON = "bookmarks-" +
|
||||
(new Date().toLocaleFormat("%Y-%m-%d")) + ".json";
|
||||
let (backup_date = new Date().toLocaleFormat("%Y-%m-%d")) {
|
||||
const FILENAME_BOOKMARKS_JSON = "bookmarks-" + backup_date + ".json";
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a bookmarks.html file in the profile folder from a given source file.
|
||||
|
Loading…
Reference in New Issue
Block a user