зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1215341 - Make assignment to const errors runtime TypeErrors in the frontend and interpreter. (r=jandem)
This commit is contained in:
Родитель
cfa69d93e9
Коммит
53c5a76506
|
@ -1242,6 +1242,21 @@ UnaliasedVarOpToAliasedVarOp(JSOp op)
|
|||
}
|
||||
}
|
||||
|
||||
static inline JSOp
|
||||
CheckSetConstOp(JSOp op, ParseNode* pn)
|
||||
{
|
||||
if (pn->resolve()->isConst()) {
|
||||
switch (op) {
|
||||
case JSOP_GETLOCAL: case JSOP_GETALIASEDVAR: break;
|
||||
case JSOP_INITLEXICAL: case JSOP_INITALIASEDLEXICAL: break;
|
||||
case JSOP_SETLOCAL: return JSOP_THROWSETCONST;
|
||||
case JSOP_SETALIASEDVAR: return JSOP_THROWSETALIASEDCONST;
|
||||
default: MOZ_CRASH("unexpected set var op");
|
||||
}
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitVarOp(ParseNode* pn, JSOp op)
|
||||
{
|
||||
|
@ -1288,7 +1303,7 @@ BytecodeEmitter::emitVarOp(ParseNode* pn, JSOp op)
|
|||
ScopeCoordinate sc;
|
||||
sc.setHops(pn->pn_scopecoord.hops());
|
||||
sc.setSlot(pn->pn_scopecoord.slot());
|
||||
return emitAliasedVarOp(op, sc, NodeNeedsCheckLexical(pn));
|
||||
return emitAliasedVarOp(CheckSetConstOp(op, pn), sc, NodeNeedsCheckLexical(pn));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -1299,7 +1314,8 @@ BytecodeEmitter::emitVarOp(ParseNode* pn, JSOp op)
|
|||
#endif
|
||||
MOZ_ASSERT_IF(pn->isKind(PNK_NAME), IsArgOp(op) || IsLocalOp(op));
|
||||
MOZ_ASSERT(pn->isUsed() || pn->isDefn());
|
||||
return emitUnaliasedVarOp(op, pn->pn_scopecoord.slot(), NodeNeedsCheckLexical(pn));
|
||||
return emitUnaliasedVarOp(CheckSetConstOp(op, pn), pn->pn_scopecoord.slot(),
|
||||
NodeNeedsCheckLexical(pn));
|
||||
}
|
||||
|
||||
static JSOp
|
||||
|
@ -1705,20 +1721,6 @@ BytecodeEmitter::bindNameToSlotHelper(ParseNode* pn)
|
|||
return true;
|
||||
}
|
||||
|
||||
// Throw an error on attempts to mutate const-declared bindings.
|
||||
switch (op) {
|
||||
case JSOP_GETNAME:
|
||||
break;
|
||||
default:
|
||||
if (pn->isConst()) {
|
||||
JSAutoByteString name;
|
||||
if (!AtomToPrintableString(cx, pn->pn_atom, &name))
|
||||
return false;
|
||||
reportError(pn, JSMSG_BAD_CONST_ASSIGN, name.ptr());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (dn->pn_scopecoord.isFree()) {
|
||||
if (evalCaller) {
|
||||
MOZ_ASSERT(script->treatAsRunOnce() || sc->isFunctionBox());
|
||||
|
@ -4406,18 +4408,16 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs)
|
|||
if (lhs->pn_scopecoord.isFree()) {
|
||||
if (!makeAtomIndex(lhs->pn_atom, &atomIndex))
|
||||
return false;
|
||||
if (!lhs->isConst()) {
|
||||
JSOp bindOp;
|
||||
if (lhs->isOp(JSOP_SETNAME) || lhs->isOp(JSOP_STRICTSETNAME))
|
||||
bindOp = JSOP_BINDNAME;
|
||||
else if (lhs->isOp(JSOP_SETGNAME) || lhs->isOp(JSOP_STRICTSETGNAME))
|
||||
bindOp = JSOP_BINDGNAME;
|
||||
else
|
||||
bindOp = JSOP_BINDINTRINSIC;
|
||||
if (!emitIndex32(bindOp, atomIndex))
|
||||
return false;
|
||||
offset++;
|
||||
}
|
||||
JSOp bindOp;
|
||||
if (lhs->isOp(JSOP_SETNAME) || lhs->isOp(JSOP_STRICTSETNAME))
|
||||
bindOp = JSOP_BINDNAME;
|
||||
else if (lhs->isOp(JSOP_SETGNAME) || lhs->isOp(JSOP_STRICTSETGNAME))
|
||||
bindOp = JSOP_BINDGNAME;
|
||||
else
|
||||
bindOp = JSOP_BINDINTRINSIC;
|
||||
if (!emitIndex32(bindOp, atomIndex))
|
||||
return false;
|
||||
offset++;
|
||||
}
|
||||
break;
|
||||
case PNK_DOT:
|
||||
|
@ -4465,18 +4465,12 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs)
|
|||
MOZ_ASSERT(rhs);
|
||||
switch (lhs->getKind()) {
|
||||
case PNK_NAME:
|
||||
if (lhs->isConst()) {
|
||||
if (lhs->isOp(JSOP_CALLEE)) {
|
||||
if (!emit1(JSOP_CALLEE))
|
||||
return false;
|
||||
} else if (lhs->isOp(JSOP_GETNAME) || lhs->isOp(JSOP_GETGNAME)) {
|
||||
if (!emitIndex32(lhs->getOp(), atomIndex))
|
||||
return false;
|
||||
} else {
|
||||
MOZ_ASSERT(JOF_OPTYPE(lhs->getOp()) != JOF_ATOM);
|
||||
if (!emitVarOp(lhs, lhs->getOp()))
|
||||
return false;
|
||||
}
|
||||
if (lhs->isConst() && lhs->isOp(JSOP_CALLEE)) {
|
||||
if (!emit1(JSOP_CALLEE))
|
||||
return false;
|
||||
} else if (lhs->isConst() && (lhs->isOp(JSOP_GETNAME) || lhs->isOp(JSOP_GETGNAME))) {
|
||||
if (!emitIndex32(lhs->getOp(), atomIndex))
|
||||
return false;
|
||||
} else if (lhs->isOp(JSOP_SETNAME) || lhs->isOp(JSOP_STRICTSETNAME)) {
|
||||
if (!emit1(JSOP_DUP))
|
||||
return false;
|
||||
|
@ -4569,12 +4563,7 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs)
|
|||
|
||||
/* If += etc., emit the binary operator with a source note. */
|
||||
if (op != JSOP_NOP) {
|
||||
/*
|
||||
* Take care to avoid SRC_ASSIGNOP if the left-hand side is a const
|
||||
* declared in the current compilation unit, as in this case (just
|
||||
* a bit further below) we will avoid emitting the assignment op.
|
||||
*/
|
||||
if (!lhs->isKind(PNK_NAME) || !lhs->isConst()) {
|
||||
if (!lhs->isKind(PNK_NAME)) {
|
||||
if (!newSrcNote(SRC_ASSIGNOP))
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@ MSG_DEF(JSMSG_IN_NOT_OBJECT, 1, JSEXN_TYPEERR, "invalid 'in' operand {
|
|||
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_BAD_CONST_ASSIGN, 1, JSEXN_TYPEERR, "invalid assignment to const `{0}'")
|
||||
|
||||
// Date
|
||||
MSG_DEF(JSMSG_INVALID_DATE, 0, JSEXN_RANGEERR, "invalid date")
|
||||
|
@ -192,7 +193,6 @@ MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 0, JSEXN_TYPEERR, "anonymous generator
|
|||
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_CONST_ASSIGN, 1, JSEXN_SYNTAXERR, "invalid assignment to const {0}")
|
||||
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")
|
||||
|
|
|
@ -2229,11 +2229,17 @@ js::LookupNameUnqualified(JSContext* cx, HandlePropertyName name, HandleObject s
|
|||
break;
|
||||
}
|
||||
|
||||
// See note above UninitializedLexicalObject.
|
||||
if (pobj == scope && IsUninitializedLexicalSlot(scope, shape)) {
|
||||
scope = UninitializedLexicalObject::create(cx, scope);
|
||||
if (!scope)
|
||||
return false;
|
||||
// See note above RuntimeLexicalErrorObject.
|
||||
if (pobj == scope) {
|
||||
if (IsUninitializedLexicalSlot(scope, shape)) {
|
||||
scope = RuntimeLexicalErrorObject::create(cx, scope, JSMSG_UNINITIALIZED_LEXICAL);
|
||||
if (!scope)
|
||||
return false;
|
||||
} else if (scope->is<ScopeObject>() && !scope->is<DeclEnvObject>() && !shape->writable()) {
|
||||
scope = RuntimeLexicalErrorObject::create(cx, scope, JSMSG_BAD_CONST_ASSIGN);
|
||||
if (!scope)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
objp.set(scope);
|
||||
|
|
|
@ -422,6 +422,8 @@ BytecodeFallsThrough(JSOp op)
|
|||
case JSOP_RETRVAL:
|
||||
case JSOP_FINALYIELDRVAL:
|
||||
case JSOP_THROW:
|
||||
case JSOP_THROWSETCONST:
|
||||
case JSOP_THROWSETALIASEDCONST:
|
||||
case JSOP_TABLESWITCH:
|
||||
return false;
|
||||
case JSOP_GOSUB:
|
||||
|
|
|
@ -139,6 +139,18 @@ IsUninitializedLexicalSlot(HandleObject obj, HandleShape shape)
|
|||
return IsUninitializedLexical(obj->as<NativeObject>().getSlot(shape->slot()));
|
||||
}
|
||||
|
||||
static inline void
|
||||
ReportUninitializedLexical(JSContext* cx, HandlePropertyName name)
|
||||
{
|
||||
ReportRuntimeLexicalError(cx, JSMSG_UNINITIALIZED_LEXICAL, name);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ReportUninitializedLexical(JSContext* cx, HandleScript script, jsbytecode* pc)
|
||||
{
|
||||
ReportRuntimeLexicalError(cx, JSMSG_UNINITIALIZED_LEXICAL, script, pc);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
CheckUninitializedLexical(JSContext* cx, PropertyName* name_, HandleValue val)
|
||||
{
|
||||
|
@ -160,6 +172,18 @@ CheckUninitializedLexical(JSContext* cx, HandleScript script, jsbytecode* pc, Ha
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ReportRuntimeConstAssignment(JSContext* cx, HandlePropertyName name)
|
||||
{
|
||||
ReportRuntimeLexicalError(cx, JSMSG_BAD_CONST_ASSIGN, name);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ReportRuntimeConstAssignment(JSContext* cx, HandleScript script, jsbytecode* pc)
|
||||
{
|
||||
ReportRuntimeLexicalError(cx, JSMSG_BAD_CONST_ASSIGN, script, pc);
|
||||
}
|
||||
|
||||
inline bool
|
||||
GetLengthProperty(const Value& lval, MutableHandleValue vp)
|
||||
{
|
||||
|
@ -277,7 +301,7 @@ SetNameOperation(JSContext* cx, JSScript* script, jsbytecode* pc, HandleObject s
|
|||
!script->hasNonSyntacticScope(),
|
||||
scope == cx->global() ||
|
||||
scope == &cx->global()->lexicalScope() ||
|
||||
scope->is<UninitializedLexicalObject>());
|
||||
scope->is<RuntimeLexicalErrorObject>());
|
||||
|
||||
bool strict = *pc == JSOP_STRICTSETNAME || *pc == JSOP_STRICTSETGNAME;
|
||||
RootedPropertyName name(cx, script->getName(pc));
|
||||
|
|
|
@ -2098,8 +2098,6 @@ CASE(JSOP_NOP)
|
|||
CASE(JSOP_UNUSED2)
|
||||
CASE(JSOP_UNUSED14)
|
||||
CASE(JSOP_BACKPATCH)
|
||||
CASE(JSOP_UNUSED169)
|
||||
CASE(JSOP_UNUSED170)
|
||||
CASE(JSOP_UNUSED171)
|
||||
CASE(JSOP_UNUSED172)
|
||||
CASE(JSOP_UNUSED173)
|
||||
|
@ -3441,6 +3439,14 @@ CASE(JSOP_SETALIASEDVAR)
|
|||
}
|
||||
END_CASE(JSOP_SETALIASEDVAR)
|
||||
|
||||
CASE(JSOP_THROWSETCONST)
|
||||
CASE(JSOP_THROWSETALIASEDCONST)
|
||||
{
|
||||
ReportRuntimeConstAssignment(cx, script, REGS.pc);
|
||||
goto error;
|
||||
}
|
||||
END_CASE(JSOP_THROWSETCONST)
|
||||
|
||||
CASE(JSOP_CHECKLEXICAL)
|
||||
{
|
||||
uint32_t i = GET_LOCALNO(REGS.pc);
|
||||
|
@ -5008,21 +5014,28 @@ js::NewArrayOperationWithTemplate(JSContext* cx, HandleObject templateObject)
|
|||
}
|
||||
|
||||
void
|
||||
js::ReportUninitializedLexical(JSContext* cx, HandlePropertyName name)
|
||||
js::ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber, HandlePropertyName name)
|
||||
{
|
||||
MOZ_ASSERT(errorNumber == JSMSG_UNINITIALIZED_LEXICAL ||
|
||||
errorNumber == JSMSG_BAD_CONST_ASSIGN);
|
||||
JSAutoByteString printable;
|
||||
if (AtomToPrintableString(cx, name, &printable)) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_UNINITIALIZED_LEXICAL,
|
||||
printable.ptr());
|
||||
}
|
||||
if (AtomToPrintableString(cx, name, &printable))
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, errorNumber, printable.ptr());
|
||||
}
|
||||
|
||||
void
|
||||
js::ReportUninitializedLexical(JSContext* cx, HandleScript script, jsbytecode* pc)
|
||||
js::ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber,
|
||||
HandleScript script, jsbytecode* pc)
|
||||
{
|
||||
JSOp op = JSOp(*pc);
|
||||
MOZ_ASSERT(op == JSOP_CHECKLEXICAL ||
|
||||
op == JSOP_CHECKALIASEDLEXICAL ||
|
||||
op == JSOP_THROWSETCONST ||
|
||||
op == JSOP_THROWSETALIASEDCONST);
|
||||
|
||||
RootedPropertyName name(cx);
|
||||
|
||||
if (JSOp(*pc) == JSOP_CHECKLEXICAL) {
|
||||
if (IsLocalOp(op)) {
|
||||
uint32_t slot = GET_LOCALNO(pc);
|
||||
|
||||
// First search for a name among body-level lets.
|
||||
|
@ -5054,11 +5067,11 @@ js::ReportUninitializedLexical(JSContext* cx, HandleScript script, jsbytecode* p
|
|||
name = JSID_TO_ATOM(id)->asPropertyName();
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(JSOp(*pc) == JSOP_CHECKALIASEDLEXICAL);
|
||||
MOZ_ASSERT(IsAliasedVarOp(op));
|
||||
name = ScopeCoordinateName(cx->runtime()->scopeCoordinateNameCache, script, pc);
|
||||
}
|
||||
|
||||
ReportUninitializedLexical(cx, name);
|
||||
ReportRuntimeLexicalError(cx, errorNumber, name);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -474,10 +474,10 @@ JSObject*
|
|||
NewArrayOperationWithTemplate(JSContext* cx, HandleObject templateObject);
|
||||
|
||||
void
|
||||
ReportUninitializedLexical(JSContext* cx, HandlePropertyName name);
|
||||
ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber, HandlePropertyName name);
|
||||
|
||||
void
|
||||
ReportUninitializedLexical(JSContext* cx, HandleScript script, jsbytecode* pc);
|
||||
ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber, HandleScript script, jsbytecode* pc);
|
||||
|
||||
// The parser only reports redeclarations that occurs within a single
|
||||
// script. Due to the extensibility of the global lexical scope, we also check
|
||||
|
@ -485,6 +485,7 @@ ReportUninitializedLexical(JSContext* cx, HandleScript script, jsbytecode* pc);
|
|||
void
|
||||
ReportRuntimeRedeclaration(JSContext* cx, HandlePropertyName name,
|
||||
frontend::Definition::Kind declKind);
|
||||
|
||||
bool
|
||||
ThrowUninitializedThis(JSContext* cx, AbstractFramePtr frame);
|
||||
|
||||
|
|
|
@ -1727,8 +1727,26 @@
|
|||
* Stack: => constructor
|
||||
*/ \
|
||||
macro(JSOP_DERIVEDCONSTRUCTOR, 168,"derivedconstructor", NULL, 5, 1, 1, JOF_ATOM) \
|
||||
macro(JSOP_UNUSED169, 169,"unused169", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
macro(JSOP_UNUSED170, 170,"unused170", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
/*
|
||||
* Throws a runtime TypeError for invalid assignment to 'const'. The
|
||||
* localno is used for better error messages.
|
||||
*
|
||||
* Category: Variables and Scopes
|
||||
* Type: Local Variables
|
||||
* Operands: uint32_t localno
|
||||
* Stack: =>
|
||||
*/ \
|
||||
macro(JSOP_THROWSETCONST, 169, "throwsetconst", NULL, 4, 1, 1, JOF_LOCAL|JOF_NAME|JOF_SET|JOF_DETECTING) \
|
||||
/*
|
||||
* Throws a runtime TypeError for invalid assignment to 'const'. The
|
||||
* scope coordinate is used for better error messages.
|
||||
*
|
||||
* Category: Variables and Scopes
|
||||
* Type: Aliased Variables
|
||||
* Operands: uint8_t hops, uint24_t slot
|
||||
* Stack: =>
|
||||
*/ \
|
||||
macro(JSOP_THROWSETALIASEDCONST, 170, "throwsetaliasedconst", NULL, 5, 1, 1, JOF_SCOPECOORD|JOF_NAME|JOF_SET|JOF_DETECTING) \
|
||||
macro(JSOP_UNUSED171, 171,"unused171", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
macro(JSOP_UNUSED172, 172,"unused172", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
macro(JSOP_UNUSED173, 173,"unused173", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
|
|
|
@ -1218,78 +1218,79 @@ js::CloneNestedScopeObject(JSContext* cx, HandleObject enclosingScope, Handle<Ne
|
|||
}
|
||||
}
|
||||
|
||||
/* static */ UninitializedLexicalObject*
|
||||
UninitializedLexicalObject::create(JSContext* cx, HandleObject enclosing)
|
||||
/* static */ RuntimeLexicalErrorObject*
|
||||
RuntimeLexicalErrorObject::create(JSContext* cx, HandleObject enclosing, unsigned errorNumber)
|
||||
{
|
||||
UninitializedLexicalObject* obj =
|
||||
NewObjectWithNullTaggedProto<UninitializedLexicalObject>(cx, GenericObject,
|
||||
BaseShape::DELEGATE);
|
||||
RuntimeLexicalErrorObject* obj =
|
||||
NewObjectWithNullTaggedProto<RuntimeLexicalErrorObject>(cx, GenericObject,
|
||||
BaseShape::DELEGATE);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
obj->setEnclosingScope(enclosing);
|
||||
obj->setReservedSlot(ERROR_SLOT, Int32Value(int32_t(errorNumber)));
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void
|
||||
ReportUninitializedLexicalId(JSContext* cx, HandleId id)
|
||||
ReportRuntimeLexicalErrorId(JSContext* cx, unsigned errorNumber, HandleId id)
|
||||
{
|
||||
if (JSID_IS_ATOM(id)) {
|
||||
RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
|
||||
ReportUninitializedLexical(cx, name);
|
||||
ReportRuntimeLexicalError(cx, errorNumber, name);
|
||||
return;
|
||||
}
|
||||
MOZ_CRASH("UninitializedLexicalObject should only be used with property names");
|
||||
MOZ_CRASH("RuntimeLexicalErrorObject should only be used with property names");
|
||||
}
|
||||
|
||||
static bool
|
||||
uninitialized_LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
lexicalError_LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
{
|
||||
ReportUninitializedLexicalId(cx, id);
|
||||
ReportRuntimeLexicalErrorId(cx, obj->as<RuntimeLexicalErrorObject>().errorNumber(), id);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
uninitialized_HasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
|
||||
lexicalError_HasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
|
||||
{
|
||||
ReportUninitializedLexicalId(cx, id);
|
||||
ReportRuntimeLexicalErrorId(cx, obj->as<RuntimeLexicalErrorObject>().errorNumber(), id);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
uninitialized_GetProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp)
|
||||
lexicalError_GetProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
ReportUninitializedLexicalId(cx, id);
|
||||
ReportRuntimeLexicalErrorId(cx, obj->as<RuntimeLexicalErrorObject>().errorNumber(), id);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
uninitialized_SetProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||
HandleValue receiver, ObjectOpResult& result)
|
||||
lexicalError_SetProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||
HandleValue receiver, ObjectOpResult& result)
|
||||
{
|
||||
ReportUninitializedLexicalId(cx, id);
|
||||
ReportRuntimeLexicalErrorId(cx, obj->as<RuntimeLexicalErrorObject>().errorNumber(), id);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
uninitialized_GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc)
|
||||
lexicalError_GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc)
|
||||
{
|
||||
ReportUninitializedLexicalId(cx, id);
|
||||
ReportRuntimeLexicalErrorId(cx, obj->as<RuntimeLexicalErrorObject>().errorNumber(), id);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
uninitialized_DeleteProperty(JSContext* cx, HandleObject obj, HandleId id, ObjectOpResult& result)
|
||||
lexicalError_DeleteProperty(JSContext* cx, HandleObject obj, HandleId id, ObjectOpResult& result)
|
||||
{
|
||||
ReportUninitializedLexicalId(cx, id);
|
||||
ReportRuntimeLexicalErrorId(cx, obj->as<RuntimeLexicalErrorObject>().errorNumber(), id);
|
||||
return false;
|
||||
}
|
||||
|
||||
const Class UninitializedLexicalObject::class_ = {
|
||||
"UninitializedLexical",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(UninitializedLexicalObject::RESERVED_SLOTS) |
|
||||
const Class RuntimeLexicalErrorObject::class_ = {
|
||||
"RuntimeLexicalError",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(RuntimeLexicalErrorObject::RESERVED_SLOTS) |
|
||||
JSCLASS_IS_ANONYMOUS,
|
||||
nullptr, /* addProperty */
|
||||
nullptr, /* delProperty */
|
||||
|
@ -1306,13 +1307,13 @@ const Class UninitializedLexicalObject::class_ = {
|
|||
JS_NULL_CLASS_SPEC,
|
||||
JS_NULL_CLASS_EXT,
|
||||
{
|
||||
uninitialized_LookupProperty,
|
||||
lexicalError_LookupProperty,
|
||||
nullptr, /* defineProperty */
|
||||
uninitialized_HasProperty,
|
||||
uninitialized_GetProperty,
|
||||
uninitialized_SetProperty,
|
||||
uninitialized_GetOwnPropertyDescriptor,
|
||||
uninitialized_DeleteProperty,
|
||||
lexicalError_HasProperty,
|
||||
lexicalError_GetProperty,
|
||||
lexicalError_SetProperty,
|
||||
lexicalError_GetOwnPropertyDescriptor,
|
||||
lexicalError_DeleteProperty,
|
||||
nullptr, nullptr, /* watch/unwatch */
|
||||
nullptr, /* getElements */
|
||||
nullptr, /* enumerate (native enumeration of target doesn't work) */
|
||||
|
|
|
@ -915,7 +915,7 @@ class ClonedBlockObject : public BlockObject
|
|||
};
|
||||
|
||||
// Internal scope object used by JSOP_BINDNAME upon encountering an
|
||||
// uninitialized lexical slot.
|
||||
// uninitialized lexical slot or an assignment to a 'const' binding.
|
||||
//
|
||||
// ES6 lexical bindings cannot be accessed in any way (throwing
|
||||
// ReferenceErrors) until initialized. Normally, NAME operations
|
||||
|
@ -930,13 +930,23 @@ class ClonedBlockObject : public BlockObject
|
|||
// assignments. Instead, this sentinel scope object is pushed on the stack.
|
||||
// Attempting to access anything on this scope throws the appropriate
|
||||
// ReferenceError.
|
||||
class UninitializedLexicalObject : public ScopeObject
|
||||
//
|
||||
// ES6 'const' bindings induce a runtime assignment when assigned to outside
|
||||
// of initialization, regardless of strictness.
|
||||
class RuntimeLexicalErrorObject : public ScopeObject
|
||||
{
|
||||
static const unsigned ERROR_SLOT = 1;
|
||||
|
||||
public:
|
||||
static const unsigned RESERVED_SLOTS = 1;
|
||||
static const unsigned RESERVED_SLOTS = 2;
|
||||
static const Class class_;
|
||||
|
||||
static UninitializedLexicalObject* create(JSContext* cx, HandleObject enclosing);
|
||||
static RuntimeLexicalErrorObject* create(JSContext* cx, HandleObject enclosing,
|
||||
unsigned errorNumber);
|
||||
|
||||
unsigned errorNumber() {
|
||||
return getReservedSlot(ERROR_SLOT).toInt32();
|
||||
}
|
||||
};
|
||||
|
||||
template<XDRMode mode>
|
||||
|
@ -1256,7 +1266,7 @@ JSObject::is<js::ScopeObject>() const
|
|||
return is<js::CallObject>() ||
|
||||
is<js::DeclEnvObject>() ||
|
||||
is<js::NestedScopeObject>() ||
|
||||
is<js::UninitializedLexicalObject>() ||
|
||||
is<js::RuntimeLexicalErrorObject>() ||
|
||||
is<js::NonSyntacticVariablesObject>();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace js {
|
|||
*
|
||||
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
|
||||
*/
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 312;
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 313;
|
||||
static const uint32_t XDR_BYTECODE_VERSION =
|
||||
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче