Bug 1215341 - Make assignment to const errors runtime TypeErrors in the frontend and interpreter. (r=jandem)

This commit is contained in:
Shu-yu Guo 2015-10-16 17:54:47 -07:00
Родитель cfa69d93e9
Коммит 53c5a76506
11 изменённых файлов: 171 добавлений и 107 удалений

Просмотреть файл

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