mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 713311 - give the remaining scope objects typed interfaces (r=waldo)
--HG-- rename : js/src/vm/CallObject-inl.h => js/src/vm/ScopeObject-inl.h rename : js/src/vm/CallObject.cpp => js/src/vm/ScopeObject.cpp rename : js/src/vm/CallObject.h => js/src/vm/ScopeObject.h extra : rebase_source : 0efa6c9ac4ceb10f48fe7ee7b199333da2b54cd9
This commit is contained in:
parent
c9f5077db7
commit
6e9feca701
@ -157,7 +157,7 @@ CPPSRCS = \
|
||||
jsxml.cpp \
|
||||
prmjtime.cpp \
|
||||
sharkctl.cpp \
|
||||
CallObject.cpp \
|
||||
ScopeObject.cpp \
|
||||
Debugger.cpp \
|
||||
GlobalObject.cpp \
|
||||
Stack.cpp \
|
||||
|
@ -244,7 +244,7 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder,
|
||||
return false;
|
||||
}
|
||||
|
||||
RegExpObject *reobj = builder.build(sourceObj.asRegExp());
|
||||
RegExpObject *reobj = builder.build(&sourceObj.asRegExp());
|
||||
if (!reobj)
|
||||
return false;
|
||||
*rval = ObjectValue(*reobj);
|
||||
@ -300,7 +300,7 @@ regexp_compile(JSContext *cx, uintN argc, Value *vp)
|
||||
if (!obj)
|
||||
return ok;
|
||||
|
||||
RegExpObjectBuilder builder(cx, obj->asRegExp());
|
||||
RegExpObjectBuilder builder(cx, &obj->asRegExp());
|
||||
return CompileRegExpObject(cx, builder, args.length(), args.array(), &args.rval());
|
||||
}
|
||||
|
||||
@ -339,7 +339,7 @@ regexp_toString(JSContext *cx, uintN argc, Value *vp)
|
||||
if (!obj)
|
||||
return ok;
|
||||
|
||||
JSString *str = obj->asRegExp()->toString(cx);
|
||||
JSString *str = obj->asRegExp().toString(cx);
|
||||
if (!str)
|
||||
return false;
|
||||
|
||||
@ -453,14 +453,14 @@ js_InitRegExpClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
GlobalObject *global = &obj->asGlobal();
|
||||
|
||||
JSObject *proto = global->createBlankPrototype(cx, &RegExpClass);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
proto->setPrivate(NULL);
|
||||
|
||||
RegExpObject *reproto = proto->asRegExp();
|
||||
RegExpObject *reproto = &proto->asRegExp();
|
||||
RegExpObjectBuilder builder(cx, reproto);
|
||||
if (!builder.build(cx->runtime->emptyString, RegExpFlag(0)))
|
||||
return NULL;
|
||||
@ -514,7 +514,7 @@ ExecuteRegExp(JSContext *cx, Native native, uintN argc, Value *vp)
|
||||
if (!obj)
|
||||
return ok;
|
||||
|
||||
RegExpObject *reobj = obj->asRegExp();
|
||||
RegExpObject *reobj = &obj->asRegExp();
|
||||
|
||||
RegExpMatcher matcher(cx);
|
||||
if (reobj->startsWithAtomizedGreedyStar()) {
|
||||
|
@ -192,9 +192,9 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
|
||||
MUST_FLOW_THROUGH("out");
|
||||
|
||||
// We can specialize a bit for the given scope chain if that scope chain is the global object.
|
||||
JSObject *globalObj = scopeChain && scopeChain == scopeChain->getGlobal()
|
||||
? scopeChain->getGlobal()
|
||||
: NULL;
|
||||
JSObject *globalObj = scopeChain && scopeChain == &scopeChain->global()
|
||||
? &scopeChain->global()
|
||||
: NULL;
|
||||
|
||||
JS_ASSERT_IF(globalObj, globalObj->isNative());
|
||||
JS_ASSERT_IF(globalObj, JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(globalObj->getClass()));
|
||||
|
@ -190,12 +190,12 @@ EmitCheck(JSContext *cx, BytecodeEmitter *bce, ptrdiff_t delta)
|
||||
return offset;
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
static StaticBlockObject &
|
||||
CurrentBlock(BytecodeEmitter *bce)
|
||||
{
|
||||
JS_ASSERT(bce->topStmt->type == STMT_BLOCK || bce->topStmt->type == STMT_SWITCH);
|
||||
JS_ASSERT(bce->topStmt->blockObj->isStaticBlock());
|
||||
return bce->topStmt->blockObj;
|
||||
return *bce->topStmt->blockObj;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -225,11 +225,11 @@ UpdateDepth(JSContext *cx, BytecodeEmitter *bce, ptrdiff_t target)
|
||||
intN nuses, ndefs;
|
||||
if (op == JSOP_ENTERBLOCK) {
|
||||
nuses = 0;
|
||||
ndefs = OBJ_BLOCK_COUNT(cx, CurrentBlock(bce));
|
||||
ndefs = CurrentBlock(bce).slotCount();
|
||||
} else if (op == JSOP_ENTERLET0) {
|
||||
nuses = ndefs = OBJ_BLOCK_COUNT(cx, CurrentBlock(bce));
|
||||
nuses = ndefs = CurrentBlock(bce).slotCount();
|
||||
} else if (op == JSOP_ENTERLET1) {
|
||||
nuses = ndefs = OBJ_BLOCK_COUNT(cx, CurrentBlock(bce)) + 1;
|
||||
nuses = ndefs = CurrentBlock(bce).slotCount() + 1;
|
||||
} else {
|
||||
nuses = StackUses(NULL, pc);
|
||||
ndefs = StackDefs(NULL, pc);
|
||||
@ -1356,15 +1356,15 @@ frontend::PushStatement(TreeContext *tc, StmtInfo *stmt, StmtType type, ptrdiff_
|
||||
}
|
||||
|
||||
void
|
||||
frontend::PushBlockScope(TreeContext *tc, StmtInfo *stmt, JSObject *blockObj, ptrdiff_t top)
|
||||
frontend::PushBlockScope(TreeContext *tc, StmtInfo *stmt, StaticBlockObject &blockObj, ptrdiff_t top)
|
||||
{
|
||||
PushStatement(tc, stmt, STMT_BLOCK, top);
|
||||
stmt->flags |= SIF_SCOPE;
|
||||
blockObj->setStaticBlockScopeChain(tc->blockChain);
|
||||
blockObj.setEnclosingBlock(tc->blockChain);
|
||||
stmt->downScope = tc->topScopeStmt;
|
||||
tc->topScopeStmt = stmt;
|
||||
tc->blockChain = blockObj;
|
||||
stmt->blockObj = blockObj;
|
||||
tc->blockChain = &blockObj;
|
||||
stmt->blockObj = &blockObj;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1560,7 +1560,7 @@ EmitNonLocalJumpFixup(JSContext *cx, BytecodeEmitter *bce, StmtInfo *toStmt)
|
||||
|
||||
if (stmt->flags & SIF_SCOPE) {
|
||||
FLUSH_POPS();
|
||||
uintN blockObjCount = OBJ_BLOCK_COUNT(cx, stmt->blockObj);
|
||||
uintN blockObjCount = stmt->blockObj->slotCount();
|
||||
if (stmt->flags & SIF_FOR_BLOCK) {
|
||||
/*
|
||||
* For a for-let-in statement, pushing/popping the block is
|
||||
@ -1649,7 +1649,7 @@ frontend::PopStatementTC(TreeContext *tc)
|
||||
if (STMT_LINKS_SCOPE(stmt)) {
|
||||
tc->topScopeStmt = stmt->downScope;
|
||||
if (stmt->flags & SIF_SCOPE)
|
||||
tc->blockChain = stmt->blockObj->staticBlockScopeChain();
|
||||
tc->blockChain = stmt->blockObj->enclosingBlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1691,17 +1691,13 @@ frontend::LexicalLookup(TreeContext *tc, JSAtom *atom, jsint *slotp, StmtInfo *s
|
||||
if (!(stmt->flags & SIF_SCOPE))
|
||||
continue;
|
||||
|
||||
JSObject *obj = stmt->blockObj;
|
||||
JS_ASSERT(obj->isStaticBlock());
|
||||
|
||||
const Shape *shape = obj->nativeLookup(tc->parser->context, ATOM_TO_JSID(atom));
|
||||
StaticBlockObject &blockObj = *stmt->blockObj;
|
||||
const Shape *shape = blockObj.nativeLookup(tc->parser->context, ATOM_TO_JSID(atom));
|
||||
if (shape) {
|
||||
JS_ASSERT(shape->hasShortID());
|
||||
|
||||
if (slotp) {
|
||||
JS_ASSERT(obj->getSlot(JSSLOT_BLOCK_DEPTH).isInt32());
|
||||
*slotp = obj->getSlot(JSSLOT_BLOCK_DEPTH).toInt32() + shape->shortid();
|
||||
}
|
||||
if (slotp)
|
||||
*slotp = blockObj.stackDepth() + shape->shortid();
|
||||
return stmt;
|
||||
}
|
||||
}
|
||||
@ -1963,29 +1959,28 @@ EmitEnterBlock(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
|
||||
if (!EmitObjectOp(cx, pn->pn_objbox, op, bce))
|
||||
return false;
|
||||
|
||||
JSObject *blockObj = pn->pn_objbox->object;
|
||||
JS_ASSERT(blockObj->isStaticBlock());
|
||||
JS_ASSERT(blockObj->getSlot(JSSLOT_BLOCK_DEPTH).isUndefined());
|
||||
StaticBlockObject &blockObj = pn->pn_objbox->object->asStaticBlock();
|
||||
|
||||
int depth = bce->stackDepth -
|
||||
(OBJ_BLOCK_COUNT(cx, blockObj) + ((op == JSOP_ENTERLET1) ? 1 : 0));
|
||||
(blockObj.slotCount() + ((op == JSOP_ENTERLET1) ? 1 : 0));
|
||||
JS_ASSERT(depth >= 0);
|
||||
OBJ_SET_BLOCK_DEPTH(cx, blockObj, depth);
|
||||
|
||||
blockObj.setStackDepth(depth);
|
||||
|
||||
int depthPlusFixed = AdjustBlockSlot(cx, bce, depth);
|
||||
if (depthPlusFixed < 0)
|
||||
return false;
|
||||
|
||||
uintN base = JSSLOT_FREE(&BlockClass);
|
||||
for (uintN slot = base, limit = base + OBJ_BLOCK_COUNT(cx, blockObj); slot < limit; slot++) {
|
||||
const Value &v = blockObj->getSlot(slot);
|
||||
for (unsigned i = 0; i < blockObj.slotCount(); i++) {
|
||||
Definition *dn = blockObj.maybeDefinitionParseNode(i);
|
||||
blockObj.poisonDefinitionParseNode(i);
|
||||
|
||||
/* Beware the empty destructuring dummy. */
|
||||
if (v.isUndefined()) {
|
||||
JS_ASSERT(slot + 1 <= limit);
|
||||
if (!dn) {
|
||||
JS_ASSERT(i + 1 <= blockObj.slotCount());
|
||||
continue;
|
||||
}
|
||||
|
||||
Definition *dn = (Definition *) v.toPrivate();
|
||||
JS_ASSERT(dn->isDefn());
|
||||
JS_ASSERT(uintN(dn->frameSlot() + depthPlusFixed) < JS_BIT(16));
|
||||
dn->pn_cookie.set(dn->pn_cookie.level(), uint16_t(dn->frameSlot() + depthPlusFixed));
|
||||
@ -1996,14 +1991,6 @@ EmitEnterBlock(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
|
||||
JS_ASSERT(pnu->pn_cookie.isFree());
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If this variable is closed over, and |eval| is not present, then
|
||||
* then set a bit in dslots so the Method JIT can deoptimize this
|
||||
* slot.
|
||||
*/
|
||||
bool isClosed = bce->shouldNoteClosedName(dn);
|
||||
blockObj->setSlot(slot, BooleanValue(isClosed));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2013,10 +2000,10 @@ EmitEnterBlock(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
|
||||
*/
|
||||
if ((bce->flags & TCF_FUN_EXTENSIBLE_SCOPE) ||
|
||||
bce->bindings.extensibleParents()) {
|
||||
Shape *newShape = Shape::setExtensibleParents(cx, blockObj->lastProperty());
|
||||
Shape *newShape = Shape::setExtensibleParents(cx, blockObj.lastProperty());
|
||||
if (!newShape)
|
||||
return false;
|
||||
blockObj->setLastPropertyInfallible(newShape);
|
||||
blockObj.setLastPropertyInfallible(newShape);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -3227,10 +3214,10 @@ EmitSwitch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
* If there are hoisted let declarations, their stack slots go under the
|
||||
* discriminant's value so push their slots now and enter the block later.
|
||||
*/
|
||||
uint32_t blockCount = 0;
|
||||
uint32_t blockObjCount = 0;
|
||||
if (pn2->isKind(PNK_LEXICALSCOPE)) {
|
||||
blockCount = OBJ_BLOCK_COUNT(cx, pn2->pn_objbox->object);
|
||||
for (uint32_t i = 0; i < blockCount; ++i) {
|
||||
blockObjCount = pn2->pn_objbox->object->asStaticBlock().slotCount();
|
||||
for (uint32_t i = 0; i < blockObjCount; ++i) {
|
||||
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
|
||||
return JS_FALSE;
|
||||
}
|
||||
@ -3243,7 +3230,7 @@ EmitSwitch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
|
||||
#if JS_HAS_BLOCK_SCOPE
|
||||
if (pn2->isKind(PNK_LEXICALSCOPE)) {
|
||||
PushBlockScope(bce, &stmtInfo, pn2->pn_objbox->object, -1);
|
||||
PushBlockScope(bce, &stmtInfo, pn2->pn_objbox->object->asStaticBlock(), -1);
|
||||
stmtInfo.type = STMT_SWITCH;
|
||||
if (!EmitEnterBlock(cx, bce, pn2, JSOP_ENTERLET1))
|
||||
return JS_FALSE;
|
||||
@ -3710,7 +3697,7 @@ out:
|
||||
|
||||
#if JS_HAS_BLOCK_SCOPE
|
||||
if (ok && pn->pn_right->isKind(PNK_LEXICALSCOPE))
|
||||
EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, blockCount);
|
||||
EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, blockObjCount);
|
||||
#endif
|
||||
}
|
||||
return ok;
|
||||
@ -5124,7 +5111,7 @@ EmitTry(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
* guardJump at the next catch (the guard mismatch case).
|
||||
*/
|
||||
JS_ASSERT(pn3->isKind(PNK_LEXICALSCOPE));
|
||||
count = OBJ_BLOCK_COUNT(cx, pn3->pn_objbox->object);
|
||||
count = pn3->pn_objbox->object->asStaticBlock().slotCount();
|
||||
if (!EmitTree(cx, bce, pn3))
|
||||
return false;
|
||||
|
||||
@ -5363,8 +5350,7 @@ EmitLet(JSContext *cx, BytecodeEmitter *bce, ParseNode *pnLet)
|
||||
JS_ASSERT(varList->isArity(PN_LIST));
|
||||
ParseNode *letBody = pnLet->pn_right;
|
||||
JS_ASSERT(letBody->isLet() && letBody->isKind(PNK_LEXICALSCOPE));
|
||||
JSObject *blockObj = letBody->pn_objbox->object;
|
||||
JS_ASSERT(blockObj->isStaticBlock());
|
||||
StaticBlockObject &blockObj = letBody->pn_objbox->object->asStaticBlock();
|
||||
|
||||
ptrdiff_t letHeadOffset = bce->offset();
|
||||
intN letHeadDepth = bce->stackDepth;
|
||||
@ -5375,7 +5361,7 @@ EmitLet(JSContext *cx, BytecodeEmitter *bce, ParseNode *pnLet)
|
||||
|
||||
/* Push storage for hoisted let decls (e.g. 'let (x) { let y }'). */
|
||||
uint32_t alreadyPushed = uintN(bce->stackDepth - letHeadDepth);
|
||||
uint32_t blockObjCount = OBJ_BLOCK_COUNT(cx, blockObj);
|
||||
uint32_t blockObjCount = blockObj.slotCount();
|
||||
for (uint32_t i = alreadyPushed; i < blockObjCount; ++i) {
|
||||
/* Tell the decompiler not to print the decl in the let head. */
|
||||
if (NewSrcNote(cx, bce, SRC_CONTINUE) < 0)
|
||||
@ -5408,7 +5394,7 @@ EmitLet(JSContext *cx, BytecodeEmitter *bce, ParseNode *pnLet)
|
||||
}
|
||||
|
||||
JS_ASSERT(leaveOp == JSOP_LEAVEBLOCK || leaveOp == JSOP_LEAVEBLOCKEXPR);
|
||||
EMIT_UINT16_IMM_OP(leaveOp, OBJ_BLOCK_COUNT(cx, blockObj));
|
||||
EMIT_UINT16_IMM_OP(leaveOp, blockObj.slotCount());
|
||||
|
||||
ptrdiff_t bodyEnd = bce->offset();
|
||||
JS_ASSERT(bodyEnd > bodyBegin);
|
||||
@ -5506,8 +5492,7 @@ EmitLexicalScope(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
|
||||
StmtInfo stmtInfo;
|
||||
ObjectBox *objbox = pn->pn_objbox;
|
||||
JSObject *blockObj = objbox->object;
|
||||
JS_ASSERT(blockObj->isStaticBlock());
|
||||
StaticBlockObject &blockObj = objbox->object->asStaticBlock();
|
||||
PushBlockScope(bce, &stmtInfo, blockObj, bce->offset());
|
||||
|
||||
/*
|
||||
@ -5546,7 +5531,7 @@ EmitLexicalScope(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
return false;
|
||||
}
|
||||
|
||||
EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, OBJ_BLOCK_COUNT(cx, blockObj));
|
||||
EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, blockObj.slotCount());
|
||||
|
||||
return PopStatementBCE(cx, bce);
|
||||
}
|
||||
@ -5618,8 +5603,8 @@ EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
||||
bool letDecl = pn1 && pn1->isKind(PNK_LEXICALSCOPE);
|
||||
JS_ASSERT_IF(letDecl, pn1->isLet());
|
||||
|
||||
JSObject *blockObj = letDecl ? pn1->pn_objbox->object : NULL;
|
||||
uint32_t blockObjCount = blockObj ? OBJ_BLOCK_COUNT(cx, blockObj) : 0;
|
||||
StaticBlockObject *blockObj = letDecl ? &pn1->pn_objbox->object->asStaticBlock() : NULL;
|
||||
uint32_t blockObjCount = blockObj ? blockObj->slotCount() : 0;
|
||||
|
||||
if (letDecl) {
|
||||
/*
|
||||
@ -5676,7 +5661,7 @@ EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
||||
/* Enter the block before the loop body, after evaluating the obj. */
|
||||
StmtInfo letStmt;
|
||||
if (letDecl) {
|
||||
PushBlockScope(bce, &letStmt, blockObj, bce->offset());
|
||||
PushBlockScope(bce, &letStmt, *blockObj, bce->offset());
|
||||
letStmt.flags |= SIF_FOR_BLOCK;
|
||||
if (!EmitEnterBlock(cx, bce, pn1, JSOP_ENTERLET1))
|
||||
return false;
|
||||
|
@ -138,7 +138,7 @@ struct StmtInfo {
|
||||
ptrdiff_t continues; /* offset of last continue in loop */
|
||||
union {
|
||||
JSAtom *label; /* name of LABEL */
|
||||
JSObject *blockObj; /* block scope object */
|
||||
StaticBlockObject *blockObj;/* block scope object */
|
||||
};
|
||||
StmtInfo *down; /* info for enclosing statement */
|
||||
StmtInfo *downScope; /* next enclosing lexical scope */
|
||||
@ -299,7 +299,7 @@ struct TreeContext { /* tree context for semantic checks */
|
||||
at non-zero depth in current paren tree */
|
||||
StmtInfo *topStmt; /* top of statement info stack */
|
||||
StmtInfo *topScopeStmt; /* top lexical scope statement */
|
||||
JSObject *blockChain; /* compile time block scope chain (NB: one
|
||||
StaticBlockObject *blockChain; /* compile block scope chain (NB: one
|
||||
deeper than the topScopeStmt/downScope
|
||||
chain when in head of let block/expr) */
|
||||
ParseNode *blockNode; /* parse node for a block with let declarations
|
||||
@ -834,7 +834,7 @@ PushStatement(TreeContext *tc, StmtInfo *stmt, StmtType type, ptrdiff_t top);
|
||||
* (if generating code), PopStatementBCE.
|
||||
*/
|
||||
void
|
||||
PushBlockScope(TreeContext *tc, StmtInfo *stmt, JSObject *blockObj, ptrdiff_t top);
|
||||
PushBlockScope(TreeContext *tc, StmtInfo *stmt, StaticBlockObject &blockObj, ptrdiff_t top);
|
||||
|
||||
/*
|
||||
* Pop tc->topStmt. If the top StmtInfo struct is not stack-allocated, it
|
||||
|
@ -179,8 +179,6 @@ Parser::setPrincipals(JSPrincipals *prin, JSPrincipals *originPrin)
|
||||
ObjectBox *
|
||||
Parser::newObjectBox(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj);
|
||||
|
||||
/*
|
||||
* We use JSContext.tempLifoAlloc to allocate parsed objects and place them
|
||||
* on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
|
||||
@ -853,18 +851,18 @@ struct BindData {
|
||||
union {
|
||||
struct {
|
||||
VarContext varContext;
|
||||
JSObject *blockObj;
|
||||
StaticBlockObject *blockObj;
|
||||
uintN overflow;
|
||||
} let;
|
||||
};
|
||||
bool fresh;
|
||||
|
||||
void initLet(VarContext varContext, JSObject *blockObj, uintN overflow) {
|
||||
void initLet(VarContext varContext, StaticBlockObject &blockObj, uintN overflow) {
|
||||
this->pn = NULL;
|
||||
this->op = JSOP_NOP;
|
||||
this->binder = BindLet;
|
||||
this->let.varContext = varContext;
|
||||
this->let.blockObj = blockObj;
|
||||
this->let.blockObj = &blockObj;
|
||||
this->let.overflow = overflow;
|
||||
}
|
||||
|
||||
@ -1930,8 +1928,8 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, TreeContext *tc)
|
||||
if (!CheckStrictBinding(cx, tc, atom->asPropertyName(), pn))
|
||||
return false;
|
||||
|
||||
JSObject *blockObj = data->let.blockObj;
|
||||
uintN blockCount = OBJ_BLOCK_COUNT(cx, blockObj);
|
||||
StaticBlockObject &blockObj = *data->let.blockObj;
|
||||
uintN blockCount = blockObj.slotCount();
|
||||
if (blockCount == JS_BIT(16)) {
|
||||
ReportCompileErrorNumber(cx, TS(tc->parser), pn,
|
||||
JSREPORT_ERROR, data->let.overflow);
|
||||
@ -1968,26 +1966,23 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, TreeContext *tc)
|
||||
*/
|
||||
bool redeclared;
|
||||
jsid id = ATOM_TO_JSID(atom);
|
||||
const Shape *shape = blockObj->defineBlockVariable(cx, id, blockCount, &redeclared);
|
||||
const Shape *shape = blockObj.addVar(cx, id, blockCount, &redeclared);
|
||||
if (!shape) {
|
||||
if (redeclared)
|
||||
ReportRedeclaration(cx, tc, pn, false, atom);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store pn temporarily in the shape-mapped slots in the static block
|
||||
* object. This value is clobbered in EmitEnterBlock.
|
||||
*/
|
||||
blockObj->setSlot(shape->slot(), PrivateValue(pn));
|
||||
/* Store pn in the static block object. */
|
||||
blockObj.setDefinitionParseNode(blockCount, reinterpret_cast<Definition *>(pn));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Op>
|
||||
static inline bool
|
||||
ForEachLetDef(TreeContext *tc, JSObject *blockObj, Op op)
|
||||
ForEachLetDef(TreeContext *tc, StaticBlockObject &blockObj, Op op)
|
||||
{
|
||||
for (Shape::Range r = blockObj->lastProperty()->all(); !r.empty(); r.popFront()) {
|
||||
for (Shape::Range r = blockObj.lastProperty()->all(); !r.empty(); r.popFront()) {
|
||||
const Shape &shape = r.front();
|
||||
|
||||
/* Beware the destructuring dummy slots. */
|
||||
@ -2001,7 +1996,7 @@ ForEachLetDef(TreeContext *tc, JSObject *blockObj, Op op)
|
||||
}
|
||||
|
||||
struct RemoveDecl {
|
||||
bool operator()(TreeContext *tc, JSObject *, const Shape &, JSAtom *atom) {
|
||||
bool operator()(TreeContext *tc, StaticBlockObject &, const Shape &, JSAtom *atom) {
|
||||
tc->decls.remove(atom);
|
||||
return true;
|
||||
}
|
||||
@ -2011,9 +2006,9 @@ static void
|
||||
PopStatement(TreeContext *tc)
|
||||
{
|
||||
if (tc->topStmt->flags & SIF_SCOPE) {
|
||||
JSObject *obj = tc->topStmt->blockObj;
|
||||
JS_ASSERT(!obj->inDictionaryMode());
|
||||
ForEachLetDef(tc, obj, RemoveDecl());
|
||||
StaticBlockObject &blockObj = *tc->topStmt->blockObj;
|
||||
JS_ASSERT(!blockObj.inDictionaryMode());
|
||||
ForEachLetDef(tc, blockObj, RemoveDecl());
|
||||
}
|
||||
PopStatementTC(tc);
|
||||
}
|
||||
@ -2587,8 +2582,8 @@ CheckDestructuring(JSContext *cx, BindData *data, ParseNode *left, TreeContext *
|
||||
return false;
|
||||
}
|
||||
|
||||
JSObject *blockObj = data && data->binder == BindLet ? data->let.blockObj : NULL;
|
||||
uint32_t blockCountBefore = blockObj ? OBJ_BLOCK_COUNT(cx, blockObj) : 0;
|
||||
StaticBlockObject *blockObj = data && data->binder == BindLet ? data->let.blockObj : NULL;
|
||||
uint32_t blockCountBefore = blockObj ? blockObj->slotCount() : 0;
|
||||
|
||||
if (left->isKind(PNK_RB)) {
|
||||
for (ParseNode *pn = left->pn_head; pn; pn = pn->pn_next) {
|
||||
@ -2658,7 +2653,7 @@ CheckDestructuring(JSContext *cx, BindData *data, ParseNode *left, TreeContext *
|
||||
* corresponding dummy property to the block object) for each initializer
|
||||
* that doesn't introduce at least one binding.
|
||||
*/
|
||||
if (toplevel && blockObj && blockCountBefore == OBJ_BLOCK_COUNT(cx, blockObj)) {
|
||||
if (toplevel && blockObj && blockCountBefore == blockObj->slotCount()) {
|
||||
if (!DefineNativeProperty(cx, blockObj,
|
||||
INT_TO_JSID(blockCountBefore),
|
||||
UndefinedValue(), NULL, NULL,
|
||||
@ -2666,7 +2661,7 @@ CheckDestructuring(JSContext *cx, BindData *data, ParseNode *left, TreeContext *
|
||||
Shape::HAS_SHORTID, blockCountBefore)) {
|
||||
return false;
|
||||
}
|
||||
JS_ASSERT(OBJ_BLOCK_COUNT(cx, blockObj) == blockCountBefore + 1);
|
||||
JS_ASSERT(blockObj->slotCount() == blockCountBefore + 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -2811,13 +2806,13 @@ Parser::returnOrYield(bool useAssignExpr)
|
||||
}
|
||||
|
||||
static ParseNode *
|
||||
PushLexicalScope(JSContext *cx, TreeContext *tc, JSObject *obj, StmtInfo *stmt)
|
||||
PushLexicalScope(JSContext *cx, TreeContext *tc, StaticBlockObject &obj, StmtInfo *stmt)
|
||||
{
|
||||
ParseNode *pn = LexicalScopeNode::create(PNK_LEXICALSCOPE, tc);
|
||||
if (!pn)
|
||||
return NULL;
|
||||
|
||||
ObjectBox *blockbox = tc->parser->newObjectBox(obj);
|
||||
ObjectBox *blockbox = tc->parser->newObjectBox(&obj);
|
||||
if (!blockbox)
|
||||
return NULL;
|
||||
|
||||
@ -2835,11 +2830,11 @@ PushLexicalScope(JSContext *cx, TreeContext *tc, JSObject *obj, StmtInfo *stmt)
|
||||
static ParseNode *
|
||||
PushLexicalScope(JSContext *cx, TreeContext *tc, StmtInfo *stmt)
|
||||
{
|
||||
JSObject *obj = js_NewBlockObject(cx);
|
||||
if (!obj)
|
||||
StaticBlockObject *blockObj = StaticBlockObject::create(cx);
|
||||
if (!blockObj)
|
||||
return NULL;
|
||||
|
||||
return PushLexicalScope(cx, tc, obj, stmt);
|
||||
return PushLexicalScope(cx, tc, *blockObj, stmt);
|
||||
}
|
||||
|
||||
#if JS_HAS_BLOCK_SCOPE
|
||||
@ -2850,16 +2845,16 @@ struct AddDecl
|
||||
|
||||
AddDecl(uint32_t blockid) : blockid(blockid) {}
|
||||
|
||||
bool operator()(TreeContext *tc, JSObject *blockObj, const Shape &shape, JSAtom *atom)
|
||||
bool operator()(TreeContext *tc, StaticBlockObject &blockObj, const Shape &shape, JSAtom *atom)
|
||||
{
|
||||
ParseNode *def = (ParseNode *) blockObj->getSlot(shape.slot()).toPrivate();
|
||||
ParseNode *def = (ParseNode *) blockObj.getSlot(shape.slot()).toPrivate();
|
||||
def->pn_blockid = blockid;
|
||||
return Define(def, atom, tc, true);
|
||||
}
|
||||
};
|
||||
|
||||
static ParseNode *
|
||||
PushLetScope(JSContext *cx, TreeContext *tc, JSObject *blockObj, StmtInfo *stmt)
|
||||
PushLetScope(JSContext *cx, TreeContext *tc, StaticBlockObject &blockObj, StmtInfo *stmt)
|
||||
{
|
||||
ParseNode *pn = PushLexicalScope(cx, tc, blockObj, stmt);
|
||||
if (!pn)
|
||||
@ -2889,7 +2884,7 @@ Parser::letBlock(LetContext letContext)
|
||||
if (!pnlet)
|
||||
return NULL;
|
||||
|
||||
JSObject *blockObj = js_NewBlockObject(context);
|
||||
StaticBlockObject *blockObj = StaticBlockObject::create(context);
|
||||
if (!blockObj)
|
||||
return NULL;
|
||||
|
||||
@ -2902,7 +2897,7 @@ Parser::letBlock(LetContext letContext)
|
||||
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_LET);
|
||||
|
||||
StmtInfo stmtInfo;
|
||||
ParseNode *block = PushLetScope(context, tc, blockObj, &stmtInfo);
|
||||
ParseNode *block = PushLetScope(context, tc, *blockObj, &stmtInfo);
|
||||
if (!block)
|
||||
return NULL;
|
||||
|
||||
@ -2969,7 +2964,7 @@ PushBlocklikeStatement(StmtInfo *stmt, StmtType type, TreeContext *tc)
|
||||
}
|
||||
|
||||
static ParseNode *
|
||||
NewBindingNode(JSAtom *atom, TreeContext *tc, JSObject *blockObj = NULL,
|
||||
NewBindingNode(JSAtom *atom, TreeContext *tc, StaticBlockObject *blockObj = NULL,
|
||||
VarContext varContext = HoistVars)
|
||||
{
|
||||
/*
|
||||
@ -3169,7 +3164,7 @@ Parser::forStatement()
|
||||
bool forDecl = false;
|
||||
|
||||
/* Non-null when forDecl is true for a 'for (let ...)' statement. */
|
||||
JSObject *blockObj = NULL;
|
||||
StaticBlockObject *blockObj = NULL;
|
||||
|
||||
/* Set to 'x' in 'for (x ;... ;...)' or 'for (x in ...)'. */
|
||||
ParseNode *pn1;
|
||||
@ -3210,7 +3205,7 @@ Parser::forStatement()
|
||||
pn1 = letBlock(LetExpresion);
|
||||
} else {
|
||||
forDecl = true;
|
||||
blockObj = js_NewBlockObject(context);
|
||||
blockObj = StaticBlockObject::create(context);
|
||||
if (!blockObj)
|
||||
return NULL;
|
||||
pn1 = variables(PNK_LET, blockObj, DontHoistVars);
|
||||
@ -3371,7 +3366,7 @@ Parser::forStatement()
|
||||
* created by PushLetScope around the for's initializer. This also
|
||||
* serves to indicate the let-decl to the emitter.
|
||||
*/
|
||||
ParseNode *block = PushLetScope(context, tc, blockObj, &letStmt);
|
||||
ParseNode *block = PushLetScope(context, tc, *blockObj, &letStmt);
|
||||
if (!block)
|
||||
return NULL;
|
||||
letStmt.flags |= SIF_FOR_BLOCK;
|
||||
@ -3428,7 +3423,7 @@ Parser::forStatement()
|
||||
* Desugar 'for (let A; B; C) D' into 'let (A) { for (; B; C) D }'
|
||||
* to induce the correct scoping for A.
|
||||
*/
|
||||
ParseNode *block = PushLetScope(context, tc, blockObj, &letStmt);
|
||||
ParseNode *block = PushLetScope(context, tc, *blockObj, &letStmt);
|
||||
if (!block)
|
||||
return NULL;
|
||||
letStmt.flags |= SIF_FOR_BLOCK;
|
||||
@ -3588,7 +3583,7 @@ Parser::tryStatement()
|
||||
* scoped, not a property of a new Object instance. This is
|
||||
* an intentional change that anticipates ECMA Ed. 4.
|
||||
*/
|
||||
data.initLet(HoistVars, tc->blockChain, JSMSG_TOO_MANY_CATCH_VARS);
|
||||
data.initLet(HoistVars, *tc->blockChain, JSMSG_TOO_MANY_CATCH_VARS);
|
||||
JS_ASSERT(data.let.blockObj && data.let.blockObj == pnblock->pn_objbox->object);
|
||||
|
||||
tt = tokenStream.getToken();
|
||||
@ -3792,11 +3787,11 @@ Parser::letStatement()
|
||||
JS_ASSERT(!stmt->downScope);
|
||||
|
||||
/* Convert the block statement into a scope statement. */
|
||||
JSObject *obj = js_NewBlockObject(tc->parser->context);
|
||||
if (!obj)
|
||||
StaticBlockObject *blockObj = StaticBlockObject::create(tc->parser->context);
|
||||
if (!blockObj)
|
||||
return NULL;
|
||||
|
||||
ObjectBox *blockbox = tc->parser->newObjectBox(obj);
|
||||
ObjectBox *blockbox = tc->parser->newObjectBox(blockObj);
|
||||
if (!blockbox)
|
||||
return NULL;
|
||||
|
||||
@ -3810,9 +3805,9 @@ Parser::letStatement()
|
||||
stmt->downScope = tc->topScopeStmt;
|
||||
tc->topScopeStmt = stmt;
|
||||
|
||||
obj->setStaticBlockScopeChain(tc->blockChain);
|
||||
tc->blockChain = obj;
|
||||
stmt->blockObj = obj;
|
||||
blockObj->setEnclosingBlock(tc->blockChain);
|
||||
tc->blockChain = blockObj;
|
||||
stmt->blockObj = blockObj;
|
||||
|
||||
#ifdef DEBUG
|
||||
ParseNode *tmp = tc->blockNode;
|
||||
@ -4283,7 +4278,7 @@ Parser::statement()
|
||||
* context, and the let-initializer of a for-statement.
|
||||
*/
|
||||
ParseNode *
|
||||
Parser::variables(ParseNodeKind kind, JSObject *blockObj, VarContext varContext)
|
||||
Parser::variables(ParseNodeKind kind, StaticBlockObject *blockObj, VarContext varContext)
|
||||
{
|
||||
/*
|
||||
* The four options here are:
|
||||
@ -4308,7 +4303,7 @@ Parser::variables(ParseNodeKind kind, JSObject *blockObj, VarContext varContext)
|
||||
*/
|
||||
BindData data;
|
||||
if (blockObj)
|
||||
data.initLet(varContext, blockObj, JSMSG_TOO_MANY_LOCALS);
|
||||
data.initLet(varContext, *blockObj, JSMSG_TOO_MANY_LOCALS);
|
||||
else
|
||||
data.initVarOrConst(pn->getOp());
|
||||
|
||||
@ -5369,7 +5364,7 @@ Parser::comprehensionTail(ParseNode *kid, uintN blockid, bool isGenexp,
|
||||
transplanter.transplant(kid);
|
||||
|
||||
JS_ASSERT(tc->blockChain && tc->blockChain == pn->pn_objbox->object);
|
||||
data.initLet(HoistVars, tc->blockChain, JSMSG_ARRAY_INIT_TOO_BIG);
|
||||
data.initLet(HoistVars, *tc->blockChain, JSMSG_ARRAY_INIT_TOO_BIG);
|
||||
|
||||
do {
|
||||
/*
|
||||
|
@ -60,6 +60,8 @@ typedef struct BindData BindData;
|
||||
|
||||
namespace js {
|
||||
|
||||
class StaticBlockObject;
|
||||
|
||||
enum FunctionSyntaxKind { Expression, Statement };
|
||||
enum LetContext { LetExpresion, LetStatement };
|
||||
enum VarContext { HoistVars, DontHoistVars };
|
||||
@ -198,7 +200,8 @@ struct Parser : private AutoGCRooter
|
||||
ParseNode *letStatement();
|
||||
#endif
|
||||
ParseNode *expressionStatement();
|
||||
ParseNode *variables(ParseNodeKind kind, JSObject *blockObj = NULL, VarContext varContext = HoistVars);
|
||||
ParseNode *variables(ParseNodeKind kind, StaticBlockObject *blockObj = NULL,
|
||||
VarContext varContext = HoistVars);
|
||||
ParseNode *expr();
|
||||
ParseNode *assignExpr();
|
||||
ParseNode *condExpr1();
|
||||
|
@ -86,14 +86,14 @@ ExhaustiveTest(const char funcode[])
|
||||
EVAL(funcode, &v);
|
||||
|
||||
EVAL(CALL_CODES[ArgCount], &v);
|
||||
ArgumentsObject *argsobj = JSVAL_TO_OBJECT(v)->asArguments();
|
||||
ArgumentsObject &argsobj = JSVAL_TO_OBJECT(v)->asArguments();
|
||||
|
||||
Value elems[MAX_ELEMS];
|
||||
|
||||
for (size_t i = 0; i <= ArgCount; i++) {
|
||||
for (size_t j = 0; j <= ArgCount - i; j++) {
|
||||
ClearElements(elems);
|
||||
CHECK(argsobj->getElements(i, j, elems));
|
||||
CHECK(argsobj.getElements(i, j, elems));
|
||||
for (size_t k = 0; k < j; k++)
|
||||
CHECK_SAME(elems[k], INT_TO_JSVAL(i + k));
|
||||
for (size_t k = j; k < MAX_ELEMS - 1; k++)
|
||||
|
@ -1403,7 +1403,7 @@ JS_EnterCrossCompartmentCallStackFrame(JSContext *cx, JSStackFrame *target)
|
||||
AssertNoGC(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
return JS_EnterCrossCompartmentCall(cx, Valueify(target)->scopeChain().getGlobal());
|
||||
return JS_EnterCrossCompartmentCall(cx, &Valueify(target)->scopeChain().global());
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
@ -1743,7 +1743,7 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj)
|
||||
|
||||
assertSameCompartment(cx, obj);
|
||||
|
||||
return obj->asGlobal()->initStandardClasses(cx);
|
||||
return obj->global().initStandardClasses(cx);
|
||||
}
|
||||
|
||||
#define CLASP(name) (&name##Class)
|
||||
@ -2168,7 +2168,7 @@ JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
AssertNoGC(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
return obj->getGlobal();
|
||||
return &obj->global();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
@ -3223,7 +3223,7 @@ JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetParent(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(!obj->isInternalScope());
|
||||
JS_ASSERT(!obj->isScope());
|
||||
assertSameCompartment(cx, obj);
|
||||
return obj->getParent();
|
||||
}
|
||||
@ -3233,7 +3233,7 @@ JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
|
||||
{
|
||||
AssertNoGC(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
JS_ASSERT(!obj->isInternalScope());
|
||||
JS_ASSERT(!obj->isScope());
|
||||
JS_ASSERT(parent || !obj->getParent());
|
||||
assertSameCompartment(cx, obj, parent);
|
||||
return obj->setParent(cx, parent);
|
||||
@ -3727,14 +3727,14 @@ DefineProperty(JSContext *cx, JSObject *obj, const char *name, const Value &valu
|
||||
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
|
||||
attrs &= ~JSPROP_NATIVE_ACCESSORS;
|
||||
if (getter) {
|
||||
JSObject *getobj = JS_NewFunction(cx, (Native) getter, 0, 0, obj->getGlobal(), NULL);
|
||||
JSObject *getobj = JS_NewFunction(cx, (Native) getter, 0, 0, &obj->global(), NULL);
|
||||
if (!getobj)
|
||||
return false;
|
||||
getter = JS_DATA_TO_FUNC_PTR(PropertyOp, getobj);
|
||||
attrs |= JSPROP_GETTER;
|
||||
}
|
||||
if (setter) {
|
||||
JSObject *setobj = JS_NewFunction(cx, (Native) setter, 1, 0, obj->getGlobal(), NULL);
|
||||
JSObject *setobj = JS_NewFunction(cx, (Native) setter, 1, 0, &obj->global(), NULL);
|
||||
if (!setobj)
|
||||
return false;
|
||||
setter = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setobj);
|
||||
@ -4214,7 +4214,7 @@ JS_ClearScope(JSContext *cx, JSObject *obj)
|
||||
|
||||
/* Clear cached class objects on the global object. */
|
||||
if (obj->isGlobal())
|
||||
obj->asGlobal()->clear(cx);
|
||||
obj->asGlobal().clear(cx);
|
||||
|
||||
js_InitRandom(cx);
|
||||
}
|
||||
@ -4603,7 +4603,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
|
||||
JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
|
||||
return NULL;
|
||||
}
|
||||
obj = obj->scopeChain();
|
||||
obj = obj->enclosingScope();
|
||||
}
|
||||
|
||||
Value v;
|
||||
@ -6289,7 +6289,7 @@ JS_NewRegExpObject(JSContext *cx, JSObject *obj, char *bytes, size_t length, uin
|
||||
if (!chars)
|
||||
return NULL;
|
||||
|
||||
RegExpStatics *res = obj->asGlobal()->getRegExpStatics();
|
||||
RegExpStatics *res = obj->asGlobal().getRegExpStatics();
|
||||
RegExpObject *reobj = RegExpObject::create(cx, res, chars, length, RegExpFlag(flags), NULL);
|
||||
cx->free_(chars);
|
||||
return reobj;
|
||||
@ -6300,7 +6300,7 @@ JS_NewUCRegExpObject(JSContext *cx, JSObject *obj, jschar *chars, size_t length,
|
||||
{
|
||||
AssertNoGC(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
RegExpStatics *res = obj->asGlobal()->getRegExpStatics();
|
||||
RegExpStatics *res = obj->asGlobal().getRegExpStatics();
|
||||
return RegExpObject::create(cx, res, chars, length, RegExpFlag(flags), NULL);
|
||||
}
|
||||
|
||||
@ -6311,7 +6311,7 @@ JS_SetRegExpInput(JSContext *cx, JSObject *obj, JSString *input, JSBool multilin
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, input);
|
||||
|
||||
obj->asGlobal()->getRegExpStatics()->reset(cx, input, !!multiline);
|
||||
obj->asGlobal().getRegExpStatics()->reset(cx, input, !!multiline);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
@ -6321,7 +6321,7 @@ JS_ClearRegExpStatics(JSContext *cx, JSObject *obj)
|
||||
CHECK_REQUEST(cx);
|
||||
JS_ASSERT(obj);
|
||||
|
||||
obj->asGlobal()->getRegExpStatics()->clear();
|
||||
obj->asGlobal().getRegExpStatics()->clear();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
@ -6331,8 +6331,8 @@ JS_ExecuteRegExp(JSContext *cx, JSObject *obj, JSObject *reobj, jschar *chars, s
|
||||
AssertNoGC(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
RegExpStatics *res = obj->asGlobal()->getRegExpStatics();
|
||||
return ExecuteRegExp(cx, res, reobj->asRegExp(), NULL, chars, length,
|
||||
RegExpStatics *res = obj->asGlobal().getRegExpStatics();
|
||||
return ExecuteRegExp(cx, res, &reobj->asRegExp(), NULL, chars, length,
|
||||
indexp, test ? RegExpTest : RegExpExec, rval);
|
||||
}
|
||||
|
||||
@ -6364,7 +6364,7 @@ JS_ExecuteRegExpNoStatics(JSContext *cx, JSObject *obj, jschar *chars, size_t le
|
||||
AssertNoGC(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
return ExecuteRegExp(cx, NULL, obj->asRegExp(), NULL, chars, length, indexp,
|
||||
return ExecuteRegExp(cx, NULL, &obj->asRegExp(), NULL, chars, length, indexp,
|
||||
test ? RegExpTest : RegExpExec, rval);
|
||||
}
|
||||
|
||||
@ -6382,7 +6382,7 @@ JS_GetRegExpFlags(JSContext *cx, JSObject *obj)
|
||||
AssertNoGC(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
return obj->asRegExp()->getFlags();
|
||||
return obj->asRegExp().getFlags();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString *)
|
||||
@ -6391,7 +6391,7 @@ JS_GetRegExpSource(JSContext *cx, JSObject *obj)
|
||||
AssertNoGC(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
return obj->asRegExp()->getSource();
|
||||
return obj->asRegExp().getSource();
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
@ -156,9 +156,9 @@ js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
|
||||
}
|
||||
|
||||
if (obj->isArguments()) {
|
||||
ArgumentsObject *argsobj = obj->asArguments();
|
||||
if (!argsobj->hasOverriddenLength()) {
|
||||
*lengthp = argsobj->initialLength();
|
||||
ArgumentsObject &argsobj = obj->asArguments();
|
||||
if (!argsobj.hasOverriddenLength()) {
|
||||
*lengthp = argsobj.initialLength();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -415,7 +415,7 @@ GetElement(JSContext *cx, JSObject *obj, IndexType index, JSBool *hole, Value *v
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (obj->isArguments()) {
|
||||
if (obj->asArguments()->getElement(uint32_t(index), vp)) {
|
||||
if (obj->asArguments().getElement(uint32_t(index), vp)) {
|
||||
*hole = JS_FALSE;
|
||||
return true;
|
||||
}
|
||||
@ -452,9 +452,9 @@ GetElements(JSContext *cx, JSObject *aobj, jsuint length, Value *vp)
|
||||
}
|
||||
|
||||
if (aobj->isArguments()) {
|
||||
ArgumentsObject *argsobj = aobj->asArguments();
|
||||
if (!argsobj->hasOverriddenLength()) {
|
||||
if (argsobj->getElements(0, length, vp))
|
||||
ArgumentsObject &argsobj = aobj->asArguments();
|
||||
if (!argsobj.hasOverriddenLength()) {
|
||||
if (argsobj.getElements(0, length, vp))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -3586,7 +3586,7 @@ js_InitArrayClass(JSContext *cx, JSObject *obj)
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
RootedVar<GlobalObject*> global(cx);
|
||||
global = obj->asGlobal();
|
||||
global = &obj->asGlobal();
|
||||
|
||||
RootedVarObject arrayProto(cx);
|
||||
arrayProto = global->createBlankPrototype(cx, &SlowArrayClass);
|
||||
|
@ -153,7 +153,7 @@ js_InitBooleanClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
GlobalObject *global = &obj->asGlobal();
|
||||
|
||||
JSObject *booleanProto = global->createBlankPrototype(cx, &BooleanClass);
|
||||
if (!booleanProto)
|
||||
|
@ -523,9 +523,9 @@ JSStructuredCloneWriter::startWrite(const js::Value &v)
|
||||
} else if (v.isObject()) {
|
||||
JSObject *obj = &v.toObject();
|
||||
if (obj->isRegExp()) {
|
||||
RegExpObject *reobj = obj->asRegExp();
|
||||
return out.writePair(SCTAG_REGEXP_OBJECT, reobj->getFlags()) &&
|
||||
writeString(SCTAG_STRING, reobj->getSource());
|
||||
RegExpObject &reobj = obj->asRegExp();
|
||||
return out.writePair(SCTAG_REGEXP_OBJECT, reobj.getFlags()) &&
|
||||
writeString(SCTAG_STRING, reobj.getSource());
|
||||
} else if (obj->isDate()) {
|
||||
jsdouble d = js_DateGetMsecSinceEpoch(context(), obj);
|
||||
return out.writePair(SCTAG_DATE_OBJECT, 0) && out.writeDouble(d);
|
||||
|
@ -76,12 +76,12 @@ static inline GlobalObject *
|
||||
GetGlobalForScopeChain(JSContext *cx)
|
||||
{
|
||||
if (cx->hasfp())
|
||||
return cx->fp()->scopeChain().getGlobal();
|
||||
return &cx->fp()->scopeChain().global();
|
||||
|
||||
JSObject *scope = JS_ObjectToInnerObject(cx, cx->globalObject);
|
||||
if (!scope)
|
||||
return NULL;
|
||||
return scope->asGlobal();
|
||||
return &scope->asGlobal();
|
||||
}
|
||||
|
||||
inline GSNCache *
|
||||
|
@ -200,7 +200,7 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
|
||||
*/
|
||||
JSObject *global;
|
||||
if (cx->hasfp()) {
|
||||
global = cx->fp()->scopeChain().getGlobal();
|
||||
global = &cx->fp()->scopeChain().global();
|
||||
} else {
|
||||
global = JS_ObjectToInnerObject(cx, cx->globalObject);
|
||||
if (!global)
|
||||
|
@ -2647,7 +2647,7 @@ js_InitDateClass(JSContext *cx, JSObject *obj)
|
||||
/* Set the static LocalTZA. */
|
||||
LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
GlobalObject *global = &obj->asGlobal();
|
||||
|
||||
JSObject *dateProto = global->createBlankPrototype(cx, &DateClass);
|
||||
if (!dateProto)
|
||||
|
@ -647,7 +647,7 @@ JS_GetScriptFunction(JSContext *cx, JSScript *script)
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetParentOrScopeChain(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return obj->scopeChain();
|
||||
return obj->enclosingScope();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
|
@ -1030,7 +1030,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
|
||||
JS_ASSERT(obj->isGlobal());
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
GlobalObject *global = &obj->asGlobal();
|
||||
|
||||
JSObject *objectProto;
|
||||
if (!js_GetClassPrototype(cx, global, JSProto_Object, &objectProto))
|
||||
@ -1333,7 +1333,7 @@ js_CopyErrorObject(JSContext *cx, JSObject *errobj, JSObject *scope)
|
||||
|
||||
// Create the Error object.
|
||||
JSObject *proto;
|
||||
if (!js_GetClassPrototype(cx, scope->getGlobal(), GetExceptionProtoKey(copy->exnType), &proto))
|
||||
if (!js_GetClassPrototype(cx, &scope->global(), GetExceptionProtoKey(copy->exnType), &proto))
|
||||
return NULL;
|
||||
JSObject *copyobj = NewObjectWithGivenProto(cx, &ErrorClass, proto, NULL);
|
||||
SetExnPrivate(cx, copyobj, copy);
|
||||
|
@ -92,7 +92,7 @@ JS_GetObjectFunction(JSObject *obj)
|
||||
JS_FRIEND_API(JSObject *)
|
||||
JS_GetGlobalForFrame(JSStackFrame *fp)
|
||||
{
|
||||
return Valueify(fp)->scopeChain().getGlobal();
|
||||
return &Valueify(fp)->scopeChain().global();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
@ -197,25 +197,25 @@ js::IsSystemCompartment(const JSCompartment *c)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
js::IsScopeObject(const JSObject *obj)
|
||||
js::IsScopeObject(JSObject *obj)
|
||||
{
|
||||
return obj->isInternalScope();
|
||||
return obj->isScope();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
js::GetObjectParentMaybeScope(const JSObject *obj)
|
||||
js::GetObjectParentMaybeScope(JSObject *obj)
|
||||
{
|
||||
return obj->scopeChain();
|
||||
return obj->enclosingScope();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
js::GetGlobalForObjectCrossCompartment(JSObject *obj)
|
||||
{
|
||||
return obj->getGlobal();
|
||||
return &obj->global();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint32_t)
|
||||
js::GetObjectSlotSpan(const JSObject *obj)
|
||||
js::GetObjectSlotSpan(JSObject *obj)
|
||||
{
|
||||
return obj->slotSpan();
|
||||
}
|
||||
|
@ -285,7 +285,6 @@ extern JS_FRIEND_DATA(js::Class) NamespaceClass;
|
||||
extern JS_FRIEND_DATA(js::Class) OuterWindowProxyClass;
|
||||
extern JS_FRIEND_DATA(js::Class) ObjectProxyClass;
|
||||
extern JS_FRIEND_DATA(js::Class) QNameClass;
|
||||
extern JS_FRIEND_DATA(js::Class) ScriptClass;
|
||||
extern JS_FRIEND_DATA(js::Class) XMLClass;
|
||||
extern JS_FRIEND_DATA(js::Class) ObjectClass;
|
||||
|
||||
@ -302,17 +301,17 @@ GetObjectJSClass(const JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
IsScopeObject(const JSObject *obj);
|
||||
IsScopeObject(JSObject *obj);
|
||||
|
||||
inline JSObject *
|
||||
GetObjectParent(const JSObject *obj)
|
||||
GetObjectParent(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(!IsScopeObject(obj));
|
||||
return reinterpret_cast<const shadow::Object*>(obj)->shape->base->parent;
|
||||
return reinterpret_cast<shadow::Object*>(obj)->shape->base->parent;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
GetObjectParentMaybeScope(const JSObject *obj);
|
||||
GetObjectParentMaybeScope(JSObject *obj);
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
GetGlobalForObjectCrossCompartment(JSObject *obj);
|
||||
@ -345,13 +344,13 @@ JS_FRIEND_API(void)
|
||||
SetFunctionNativeReserved(JSObject *fun, size_t which, const Value &val);
|
||||
|
||||
inline JSObject *
|
||||
GetObjectProto(const JSObject *obj)
|
||||
GetObjectProto(JSObject *obj)
|
||||
{
|
||||
return reinterpret_cast<const shadow::Object*>(obj)->type->proto;
|
||||
}
|
||||
|
||||
inline void *
|
||||
GetObjectPrivate(const JSObject *obj)
|
||||
GetObjectPrivate(JSObject *obj)
|
||||
{
|
||||
const shadow::Object *nobj = reinterpret_cast<const shadow::Object*>(obj);
|
||||
void **addr = reinterpret_cast<void**>(&nobj->fixedSlots()[nobj->numFixedSlots()]);
|
||||
@ -377,17 +376,17 @@ SetReservedSlot(JSObject *obj, size_t slot, const Value &value)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint32_t)
|
||||
GetObjectSlotSpan(const JSObject *obj);
|
||||
GetObjectSlotSpan(JSObject *obj);
|
||||
|
||||
inline const Value &
|
||||
GetObjectSlot(const JSObject *obj, size_t slot)
|
||||
GetObjectSlot(JSObject *obj, size_t slot)
|
||||
{
|
||||
JS_ASSERT(slot < GetObjectSlotSpan(obj));
|
||||
return reinterpret_cast<const shadow::Object *>(obj)->slotRef(slot);
|
||||
}
|
||||
|
||||
inline Shape *
|
||||
GetObjectShape(const JSObject *obj)
|
||||
GetObjectShape(JSObject *obj)
|
||||
{
|
||||
shadow::Shape *shape = reinterpret_cast<const shadow::Object*>(obj)->shape;
|
||||
return reinterpret_cast<Shape *>(shape);
|
||||
|
183
js/src/jsfun.cpp
183
js/src/jsfun.cpp
@ -72,7 +72,7 @@
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "frontend/BytecodeEmitter.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "vm/CallObject.h"
|
||||
#include "vm/ScopeObject.h"
|
||||
#include "vm/Debugger.h"
|
||||
|
||||
#if JS_HAS_GENERATORS
|
||||
@ -92,7 +92,7 @@
|
||||
#include "jsinferinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
#include "jsscriptinlines.h"
|
||||
#include "vm/CallObject-inl.h"
|
||||
#include "vm/ScopeObject-inl.h"
|
||||
#include "vm/ArgumentsObject-inl.h"
|
||||
#include "vm/Stack-inl.h"
|
||||
|
||||
@ -104,7 +104,7 @@ using namespace js::types;
|
||||
inline JSObject *
|
||||
JSObject::getThrowTypeError() const
|
||||
{
|
||||
return getGlobal()->getThrowTypeError();
|
||||
return global().getThrowTypeError();
|
||||
}
|
||||
|
||||
JSBool
|
||||
@ -127,7 +127,7 @@ ArgumentsObject::create(JSContext *cx, uint32_t argc, JSObject &callee, StackFra
|
||||
{
|
||||
JS_ASSERT(argc <= StackSpace::ARGS_LENGTH_MAX);
|
||||
|
||||
JSObject *proto = callee.getGlobal()->getOrCreateObjectPrototype(cx);
|
||||
JSObject *proto = callee.global().getOrCreateObjectPrototype(cx);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
|
||||
@ -161,17 +161,17 @@ ArgumentsObject::create(JSContext *cx, uint32_t argc, JSObject &callee, StackFra
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
ArgumentsObject *argsobj = obj->asArguments();
|
||||
ArgumentsObject &argsobj = obj->asArguments();
|
||||
|
||||
JS_ASSERT(UINT32_MAX > (uint64_t(argc) << PACKED_BITS_COUNT));
|
||||
argsobj->initInitialLength(argc);
|
||||
argsobj->initData(data);
|
||||
argsobj->setStackFrame(strict ? NULL : fp);
|
||||
argsobj.initInitialLength(argc);
|
||||
argsobj.initData(data);
|
||||
argsobj.setStackFrame(strict ? NULL : fp);
|
||||
|
||||
JS_ASSERT(argsobj->numFixedSlots() >= NormalArgumentsObject::RESERVED_SLOTS);
|
||||
JS_ASSERT(argsobj->numFixedSlots() >= StrictArgumentsObject::RESERVED_SLOTS);
|
||||
JS_ASSERT(argsobj.numFixedSlots() >= NormalArgumentsObject::RESERVED_SLOTS);
|
||||
JS_ASSERT(argsobj.numFixedSlots() >= StrictArgumentsObject::RESERVED_SLOTS);
|
||||
|
||||
return argsobj;
|
||||
return &argsobj;
|
||||
}
|
||||
|
||||
struct STATIC_SKIP_INFERENCE PutArg
|
||||
@ -251,15 +251,15 @@ js_PutArgsObject(StackFrame *fp)
|
||||
static JSBool
|
||||
args_delProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
{
|
||||
ArgumentsObject *argsobj = obj->asArguments();
|
||||
ArgumentsObject &argsobj = obj->asArguments();
|
||||
if (JSID_IS_INT(id)) {
|
||||
uintN arg = uintN(JSID_TO_INT(id));
|
||||
if (arg < argsobj->initialLength())
|
||||
argsobj->setElement(arg, MagicValue(JS_ARGS_HOLE));
|
||||
if (arg < argsobj.initialLength())
|
||||
argsobj.setElement(arg, MagicValue(JS_ARGS_HOLE));
|
||||
} else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
|
||||
argsobj->markLengthOverridden();
|
||||
argsobj.markLengthOverridden();
|
||||
} else if (JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom)) {
|
||||
argsobj->asNormalArguments()->clearCallee();
|
||||
argsobj.asNormalArguments().clearCallee();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -270,26 +270,26 @@ ArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
if (!obj->isNormalArguments())
|
||||
return true;
|
||||
|
||||
NormalArgumentsObject *argsobj = obj->asNormalArguments();
|
||||
NormalArgumentsObject &argsobj = obj->asNormalArguments();
|
||||
if (JSID_IS_INT(id)) {
|
||||
/*
|
||||
* arg can exceed the number of arguments if a script changed the
|
||||
* prototype to point to another Arguments object with a bigger argc.
|
||||
*/
|
||||
uintN arg = uintN(JSID_TO_INT(id));
|
||||
if (arg < argsobj->initialLength()) {
|
||||
JS_ASSERT(!argsobj->element(arg).isMagic(JS_ARGS_HOLE));
|
||||
if (StackFrame *fp = argsobj->maybeStackFrame())
|
||||
if (arg < argsobj.initialLength()) {
|
||||
JS_ASSERT(!argsobj.element(arg).isMagic(JS_ARGS_HOLE));
|
||||
if (StackFrame *fp = argsobj.maybeStackFrame())
|
||||
*vp = fp->canonicalActualArg(arg);
|
||||
else
|
||||
*vp = argsobj->element(arg);
|
||||
*vp = argsobj.element(arg);
|
||||
}
|
||||
} else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
|
||||
if (!argsobj->hasOverriddenLength())
|
||||
vp->setInt32(argsobj->initialLength());
|
||||
if (!argsobj.hasOverriddenLength())
|
||||
vp->setInt32(argsobj.initialLength());
|
||||
} else {
|
||||
JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom));
|
||||
const Value &v = argsobj->callee();
|
||||
const Value &v = argsobj.callee();
|
||||
if (!v.isMagic(JS_ARGS_HOLE))
|
||||
*vp = v;
|
||||
}
|
||||
@ -302,12 +302,12 @@ ArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
if (!obj->isNormalArguments())
|
||||
return true;
|
||||
|
||||
NormalArgumentsObject *argsobj = obj->asNormalArguments();
|
||||
NormalArgumentsObject &argsobj = obj->asNormalArguments();
|
||||
|
||||
if (JSID_IS_INT(id)) {
|
||||
uintN arg = uintN(JSID_TO_INT(id));
|
||||
if (arg < argsobj->initialLength()) {
|
||||
if (StackFrame *fp = argsobj->maybeStackFrame()) {
|
||||
if (arg < argsobj.initialLength()) {
|
||||
if (StackFrame *fp = argsobj.maybeStackFrame()) {
|
||||
JSScript *script = fp->functionScript();
|
||||
if (script->usesArguments) {
|
||||
if (arg < fp->numFormalArgs())
|
||||
@ -331,8 +331,8 @@ ArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
* that has a setter for this id.
|
||||
*/
|
||||
AutoValueRooter tvr(cx);
|
||||
return js_DeleteProperty(cx, argsobj, id, tvr.addr(), false) &&
|
||||
js_DefineProperty(cx, argsobj, id, vp, NULL, NULL, JSPROP_ENUMERATE);
|
||||
return js_DeleteProperty(cx, &argsobj, id, tvr.addr(), false) &&
|
||||
js_DefineProperty(cx, &argsobj, id, vp, NULL, NULL, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -341,44 +341,44 @@ args_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
{
|
||||
*objp = NULL;
|
||||
|
||||
NormalArgumentsObject *argsobj = obj->asNormalArguments();
|
||||
NormalArgumentsObject &argsobj = obj->asNormalArguments();
|
||||
|
||||
uintN attrs = JSPROP_SHARED | JSPROP_SHADOWABLE;
|
||||
if (JSID_IS_INT(id)) {
|
||||
uint32_t arg = uint32_t(JSID_TO_INT(id));
|
||||
if (arg >= argsobj->initialLength() || argsobj->element(arg).isMagic(JS_ARGS_HOLE))
|
||||
if (arg >= argsobj.initialLength() || argsobj.element(arg).isMagic(JS_ARGS_HOLE))
|
||||
return true;
|
||||
|
||||
attrs |= JSPROP_ENUMERATE;
|
||||
} else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
|
||||
if (argsobj->hasOverriddenLength())
|
||||
if (argsobj.hasOverriddenLength())
|
||||
return true;
|
||||
} else {
|
||||
if (!JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom))
|
||||
return true;
|
||||
|
||||
if (argsobj->callee().isMagic(JS_ARGS_HOLE))
|
||||
if (argsobj.callee().isMagic(JS_ARGS_HOLE))
|
||||
return true;
|
||||
}
|
||||
|
||||
Value undef = UndefinedValue();
|
||||
if (!js_DefineProperty(cx, argsobj, id, &undef, ArgGetter, ArgSetter, attrs))
|
||||
if (!js_DefineProperty(cx, &argsobj, id, &undef, ArgGetter, ArgSetter, attrs))
|
||||
return JS_FALSE;
|
||||
|
||||
*objp = argsobj;
|
||||
*objp = &argsobj;
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
args_enumerate(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
NormalArgumentsObject *argsobj = obj->asNormalArguments();
|
||||
NormalArgumentsObject &argsobj = obj->asNormalArguments();
|
||||
|
||||
/*
|
||||
* Trigger reflection in args_resolve using a series of js_LookupProperty
|
||||
* calls.
|
||||
*/
|
||||
int argc = int(argsobj->initialLength());
|
||||
int argc = int(argsobj.initialLength());
|
||||
for (int i = -2; i != argc; i++) {
|
||||
jsid id = (i == -2)
|
||||
? ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)
|
||||
@ -388,7 +388,7 @@ args_enumerate(JSContext *cx, JSObject *obj)
|
||||
|
||||
JSObject *pobj;
|
||||
JSProperty *prop;
|
||||
if (!js_LookupProperty(cx, argsobj, id, &pobj, &prop))
|
||||
if (!js_LookupProperty(cx, &argsobj, id, &pobj, &prop))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -400,7 +400,7 @@ StrictArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
if (!obj->isStrictArguments())
|
||||
return true;
|
||||
|
||||
StrictArgumentsObject *argsobj = obj->asStrictArguments();
|
||||
StrictArgumentsObject &argsobj = obj->asStrictArguments();
|
||||
|
||||
if (JSID_IS_INT(id)) {
|
||||
/*
|
||||
@ -408,15 +408,15 @@ StrictArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
* prototype to point to another Arguments object with a bigger argc.
|
||||
*/
|
||||
uintN arg = uintN(JSID_TO_INT(id));
|
||||
if (arg < argsobj->initialLength()) {
|
||||
const Value &v = argsobj->element(arg);
|
||||
if (arg < argsobj.initialLength()) {
|
||||
const Value &v = argsobj.element(arg);
|
||||
if (!v.isMagic(JS_ARGS_HOLE))
|
||||
*vp = v;
|
||||
}
|
||||
} else {
|
||||
JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom));
|
||||
if (!argsobj->hasOverriddenLength())
|
||||
vp->setInt32(argsobj->initialLength());
|
||||
if (!argsobj.hasOverriddenLength())
|
||||
vp->setInt32(argsobj.initialLength());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -427,12 +427,12 @@ StrictArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
if (!obj->isStrictArguments())
|
||||
return true;
|
||||
|
||||
StrictArgumentsObject *argsobj = obj->asStrictArguments();
|
||||
StrictArgumentsObject &argsobj = obj->asStrictArguments();
|
||||
|
||||
if (JSID_IS_INT(id)) {
|
||||
uintN arg = uintN(JSID_TO_INT(id));
|
||||
if (arg < argsobj->initialLength()) {
|
||||
argsobj->setElement(arg, *vp);
|
||||
if (arg < argsobj.initialLength()) {
|
||||
argsobj.setElement(arg, *vp);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
@ -446,8 +446,8 @@ StrictArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
* collect its value.
|
||||
*/
|
||||
AutoValueRooter tvr(cx);
|
||||
return js_DeleteProperty(cx, argsobj, id, tvr.addr(), strict) &&
|
||||
js_SetPropertyHelper(cx, argsobj, id, 0, vp, strict);
|
||||
return js_DeleteProperty(cx, &argsobj, id, tvr.addr(), strict) &&
|
||||
js_SetPropertyHelper(cx, &argsobj, id, 0, vp, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -455,7 +455,7 @@ strictargs_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject
|
||||
{
|
||||
*objp = NULL;
|
||||
|
||||
StrictArgumentsObject *argsobj = obj->asStrictArguments();
|
||||
StrictArgumentsObject &argsobj = obj->asStrictArguments();
|
||||
|
||||
uintN attrs = JSPROP_SHARED | JSPROP_SHADOWABLE;
|
||||
PropertyOp getter = StrictArgGetter;
|
||||
@ -463,12 +463,12 @@ strictargs_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject
|
||||
|
||||
if (JSID_IS_INT(id)) {
|
||||
uint32_t arg = uint32_t(JSID_TO_INT(id));
|
||||
if (arg >= argsobj->initialLength() || argsobj->element(arg).isMagic(JS_ARGS_HOLE))
|
||||
if (arg >= argsobj.initialLength() || argsobj.element(arg).isMagic(JS_ARGS_HOLE))
|
||||
return true;
|
||||
|
||||
attrs |= JSPROP_ENUMERATE;
|
||||
} else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
|
||||
if (argsobj->hasOverriddenLength())
|
||||
if (argsobj.hasOverriddenLength())
|
||||
return true;
|
||||
} else {
|
||||
if (!JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom) &&
|
||||
@ -477,22 +477,22 @@ strictargs_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject
|
||||
}
|
||||
|
||||
attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED;
|
||||
getter = CastAsPropertyOp(argsobj->getThrowTypeError());
|
||||
setter = CastAsStrictPropertyOp(argsobj->getThrowTypeError());
|
||||
getter = CastAsPropertyOp(argsobj.getThrowTypeError());
|
||||
setter = CastAsStrictPropertyOp(argsobj.getThrowTypeError());
|
||||
}
|
||||
|
||||
Value undef = UndefinedValue();
|
||||
if (!js_DefineProperty(cx, argsobj, id, &undef, getter, setter, attrs))
|
||||
if (!js_DefineProperty(cx, &argsobj, id, &undef, getter, setter, attrs))
|
||||
return false;
|
||||
|
||||
*objp = argsobj;
|
||||
*objp = &argsobj;
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
strictargs_enumerate(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
StrictArgumentsObject *argsobj = obj->asStrictArguments();
|
||||
StrictArgumentsObject *argsobj = &obj->asStrictArguments();
|
||||
|
||||
/*
|
||||
* Trigger reflection in strictargs_resolve using a series of
|
||||
@ -524,16 +524,16 @@ strictargs_enumerate(JSContext *cx, JSObject *obj)
|
||||
static void
|
||||
args_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
cx->free_(reinterpret_cast<void *>(obj->asArguments()->data()));
|
||||
cx->free_(reinterpret_cast<void *>(obj->asArguments().data()));
|
||||
}
|
||||
|
||||
static void
|
||||
args_trace(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
ArgumentsObject *argsobj = obj->asArguments();
|
||||
ArgumentsData *data = argsobj->data();
|
||||
ArgumentsObject &argsobj = obj->asArguments();
|
||||
ArgumentsData *data = argsobj.data();
|
||||
MarkValue(trc, data->callee, js_callee_str);
|
||||
MarkValueRange(trc, argsobj->initialLength(), data->slots, js_arguments_str);
|
||||
MarkValueRange(trc, argsobj.initialLength(), data->slots, js_arguments_str);
|
||||
|
||||
/*
|
||||
* If a generator's arguments or call object escapes, and the generator
|
||||
@ -545,7 +545,7 @@ args_trace(JSTracer *trc, JSObject *obj)
|
||||
* JSGenerator.
|
||||
*/
|
||||
#if JS_HAS_GENERATORS
|
||||
StackFrame *fp = argsobj->maybeStackFrame();
|
||||
StackFrame *fp = argsobj.maybeStackFrame();
|
||||
if (fp && fp->isFloatingGenerator())
|
||||
MarkObject(trc, js_FloatingFrameToGenerator(fp)->obj, "generator object");
|
||||
#endif
|
||||
@ -606,53 +606,6 @@ Class js::StrictArgumentsObjectClass = {
|
||||
args_trace
|
||||
};
|
||||
|
||||
/*
|
||||
* A Declarative Environment object stores its active StackFrame pointer in
|
||||
* its private slot, just as Call and Arguments objects do.
|
||||
*/
|
||||
Class js::DeclEnvClass = {
|
||||
js_Object_str,
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(CallObject::DECL_ENV_RESERVED_SLOTS) |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub
|
||||
};
|
||||
|
||||
static inline JSObject *
|
||||
NewDeclEnvObject(JSContext *cx, StackFrame *fp)
|
||||
{
|
||||
RootedVarTypeObject type(cx);
|
||||
type = cx->compartment->getEmptyType(cx);
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
JSObject *parent = fp->scopeChain().getGlobal();
|
||||
|
||||
RootedVarShape emptyDeclEnvShape(cx);
|
||||
emptyDeclEnvShape =
|
||||
EmptyShape::getInitialShape(cx, &DeclEnvClass, NULL,
|
||||
parent, CallObject::DECL_ENV_FINALIZE_KIND);
|
||||
if (!emptyDeclEnvShape)
|
||||
return NULL;
|
||||
|
||||
JSObject *envobj = JSObject::create(cx, CallObject::DECL_ENV_FINALIZE_KIND,
|
||||
emptyDeclEnvShape, type, NULL);
|
||||
if (!envobj)
|
||||
return NULL;
|
||||
envobj->setPrivate(fp);
|
||||
|
||||
if (!envobj->setInternalScopeChain(cx, &fp->scopeChain()))
|
||||
return NULL;
|
||||
|
||||
return envobj;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
CallObject *
|
||||
@ -670,7 +623,7 @@ CreateFunCallObject(JSContext *cx, StackFrame *fp)
|
||||
* object holding function's name.
|
||||
*/
|
||||
if (JSAtom *lambdaName = CallObjectLambdaName(fp->fun())) {
|
||||
scopeChain = NewDeclEnvObject(cx, fp);
|
||||
scopeChain = DeclEnvObject::create(cx, fp);
|
||||
if (!scopeChain)
|
||||
return NULL;
|
||||
|
||||
@ -789,11 +742,9 @@ js_PutCallObject(StackFrame *fp)
|
||||
|
||||
/* Clear private pointers to fp, which is about to go away. */
|
||||
if (js_IsNamedLambda(fun)) {
|
||||
JSObject *env = callobj.internalScopeChain();
|
||||
|
||||
JS_ASSERT(env->isDeclEnv());
|
||||
JS_ASSERT(env->getPrivate() == fp);
|
||||
env->setPrivate(NULL);
|
||||
JSObject &env = callobj.enclosingScope();
|
||||
JS_ASSERT(env.asDeclEnv().maybeStackFrame() == fp);
|
||||
env.setPrivate(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1955,7 +1906,7 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
||||
|
||||
/* Block this call if security callbacks forbid it. */
|
||||
RootedVar<GlobalObject*> global(cx);
|
||||
global = args.callee().getGlobal();
|
||||
global = &args.callee().global();
|
||||
if (!global->isRuntimeCodeGenEnabled(cx)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_FUNCTION);
|
||||
return false;
|
||||
@ -2250,7 +2201,7 @@ js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
|
||||
if (!cscript)
|
||||
return NULL;
|
||||
|
||||
cscript->globalObject = clone->getGlobal();
|
||||
cscript->globalObject = &clone->global();
|
||||
clone->setScript(cscript);
|
||||
if (!cscript->typeSetFunction(cx, clone))
|
||||
return NULL;
|
||||
|
@ -45,6 +45,8 @@
|
||||
|
||||
#include "vm/GlobalObject.h"
|
||||
|
||||
#include "vm/ScopeObject-inl.h"
|
||||
|
||||
inline bool
|
||||
JSFunction::inStrictMode() const
|
||||
{
|
||||
@ -351,8 +353,8 @@ SkipScopeParent(JSObject *parent)
|
||||
{
|
||||
if (!parent)
|
||||
return NULL;
|
||||
while (parent->isInternalScope())
|
||||
parent = parent->scopeChain();
|
||||
while (parent->isScope())
|
||||
parent = &parent->asScope().enclosingScope();
|
||||
return parent;
|
||||
}
|
||||
|
||||
@ -361,7 +363,7 @@ CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
|
||||
gc::AllocKind kind = JSFunction::FinalizeKind)
|
||||
{
|
||||
JS_ASSERT(parent);
|
||||
JSObject *proto = parent->getGlobal()->getOrCreateFunctionPrototype(cx);
|
||||
JSObject *proto = parent->global().getOrCreateFunctionPrototype(cx);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
|
||||
@ -395,7 +397,7 @@ CloneFunctionObject(JSContext *cx, JSFunction *fun)
|
||||
* Variant which makes an exact clone of fun, preserving parent and proto.
|
||||
* Calling the above version CloneFunctionObject(cx, fun, fun->getParent())
|
||||
* is not equivalent: API clients, including XPConnect, can reparent
|
||||
* objects so that fun->getGlobal() != fun->getProto()->getGlobal().
|
||||
* objects so that fun->global() != fun->getProto()->global().
|
||||
* See ReparentWrapperIfFound.
|
||||
*/
|
||||
JS_ASSERT(fun->getParent() && fun->getProto());
|
||||
|
@ -96,7 +96,7 @@
|
||||
#include "jsinterpinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "vm/CallObject-inl.h"
|
||||
#include "vm/ScopeObject-inl.h"
|
||||
#include "vm/String-inl.h"
|
||||
|
||||
#ifdef MOZ_VALGRIND
|
||||
|
@ -1891,7 +1891,7 @@ TypeHasGlobal(Type type, JSObject *global)
|
||||
return false;
|
||||
|
||||
if (type.isSingleObject())
|
||||
return type.singleObject()->getGlobal() == global;
|
||||
return &type.singleObject()->global() == global;
|
||||
|
||||
if (type.isTypeObject())
|
||||
return type.typeObject()->getGlobal() == global;
|
||||
@ -5199,8 +5199,8 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_ASSERT_IF(fun && scope, fun->getGlobal() == scope->getGlobal());
|
||||
script->types->global = fun ? fun->getGlobal() : scope->getGlobal();
|
||||
JS_ASSERT_IF(fun && scope, fun->global() == scope->global());
|
||||
script->types->global = fun ? &fun->global() : &scope->global();
|
||||
|
||||
/*
|
||||
* Update the parent in the script's bindings. The bindings are created
|
||||
@ -5231,7 +5231,7 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
|
||||
* the script is nested inside.
|
||||
*/
|
||||
while (!scope->isCall())
|
||||
scope = scope->internalScopeChain();
|
||||
scope = &scope->asScope().enclosingScope();
|
||||
|
||||
CallObject &call = scope->asCall();
|
||||
|
||||
@ -5264,9 +5264,9 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
|
||||
if (!parent->ensureHasTypes(cx))
|
||||
return false;
|
||||
if (!parent->types->hasScope()) {
|
||||
if (!SetScope(cx, parent, scope->internalScopeChain()))
|
||||
if (!SetScope(cx, parent, &call.enclosingScope()))
|
||||
return false;
|
||||
parent->nesting()->activeCall = scope;
|
||||
parent->nesting()->activeCall = &call;
|
||||
parent->nesting()->argArray = Valueify(call.argArray());
|
||||
parent->nesting()->varArray = Valueify(call.varArray());
|
||||
}
|
||||
@ -5359,7 +5359,7 @@ CheckNestingParent(JSContext *cx, JSObject *scope, JSScript *script)
|
||||
JS_ASSERT(parent);
|
||||
|
||||
while (!scope->isCall() || scope->asCall().getCalleeFunction()->script() != parent)
|
||||
scope = scope->internalScopeChain();
|
||||
scope = &scope->asScope().enclosingScope();
|
||||
|
||||
if (scope != parent->nesting()->activeCall) {
|
||||
parent->reentrantOuterFunction = true;
|
||||
@ -5374,7 +5374,7 @@ CheckNestingParent(JSContext *cx, JSObject *scope, JSScript *script)
|
||||
* parent.
|
||||
*/
|
||||
if (parent->nesting()->parent) {
|
||||
scope = scope->internalScopeChain();
|
||||
scope = &scope->asScope().enclosingScope();
|
||||
script = parent;
|
||||
goto restart;
|
||||
}
|
||||
|
@ -1250,9 +1250,9 @@ inline JSObject *
|
||||
TypeObject::getGlobal()
|
||||
{
|
||||
if (singleton)
|
||||
return singleton->getGlobal();
|
||||
return &singleton->global();
|
||||
if (interpretedFunction && interpretedFunction->script()->compileAndGo)
|
||||
return interpretedFunction->getGlobal();
|
||||
return &interpretedFunction->global();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ using namespace js::types;
|
||||
JSObject *
|
||||
js::GetScopeChain(JSContext *cx, StackFrame *fp)
|
||||
{
|
||||
JSObject *sharedBlock = fp->maybeBlockChain();
|
||||
StaticBlockObject *sharedBlock = fp->maybeBlockChain();
|
||||
|
||||
if (!sharedBlock) {
|
||||
/*
|
||||
@ -175,7 +175,7 @@ js::GetScopeChain(JSContext *cx, StackFrame *fp)
|
||||
*/
|
||||
limitClone = &fp->scopeChain();
|
||||
while (limitClone->isWith())
|
||||
limitClone = limitClone->internalScopeChain();
|
||||
limitClone = &limitClone->asWith().enclosingScope();
|
||||
JS_ASSERT(limitClone);
|
||||
|
||||
/*
|
||||
@ -207,10 +207,9 @@ js::GetScopeChain(JSContext *cx, StackFrame *fp)
|
||||
* Special-case cloning the innermost block; this doesn't have enough in
|
||||
* common with subsequent steps to include in the loop.
|
||||
*
|
||||
* js_CloneBlockObject leaves the clone's parent slot uninitialized. We
|
||||
* populate it below.
|
||||
* create() leaves the clone's enclosingScope unset. We set it below.
|
||||
*/
|
||||
JSObject *innermostNewChild = js_CloneBlockObject(cx, sharedBlock, fp);
|
||||
ClonedBlockObject *innermostNewChild = ClonedBlockObject::create(cx, *sharedBlock, fp);
|
||||
if (!innermostNewChild)
|
||||
return NULL;
|
||||
|
||||
@ -218,25 +217,25 @@ js::GetScopeChain(JSContext *cx, StackFrame *fp)
|
||||
* Clone our way towards outer scopes until we reach the innermost
|
||||
* enclosing function, or the innermost block we've already cloned.
|
||||
*/
|
||||
JSObject *newChild = innermostNewChild;
|
||||
ClonedBlockObject *newChild = innermostNewChild;
|
||||
for (;;) {
|
||||
JS_ASSERT(newChild->getProto() == sharedBlock);
|
||||
sharedBlock = sharedBlock->staticBlockScopeChain();
|
||||
sharedBlock = sharedBlock->enclosingBlock();
|
||||
|
||||
/* Sometimes limitBlock will be NULL, so check that first. */
|
||||
if (sharedBlock == limitBlock || !sharedBlock)
|
||||
break;
|
||||
|
||||
/* As in the call above, we don't know the real parent yet. */
|
||||
JSObject *clone = js_CloneBlockObject(cx, sharedBlock, fp);
|
||||
ClonedBlockObject *clone = ClonedBlockObject::create(cx, *sharedBlock, fp);
|
||||
if (!clone)
|
||||
return NULL;
|
||||
|
||||
if (!newChild->setInternalScopeChain(cx, clone))
|
||||
if (!newChild->setEnclosingScope(cx, *clone))
|
||||
return NULL;
|
||||
newChild = clone;
|
||||
}
|
||||
if (!newChild->setInternalScopeChain(cx, &fp->scopeChain()))
|
||||
if (!newChild->setEnclosingScope(cx, fp->scopeChain()))
|
||||
return NULL;
|
||||
|
||||
|
||||
@ -245,7 +244,7 @@ js::GetScopeChain(JSContext *cx, StackFrame *fp)
|
||||
* found it in blockChain.
|
||||
*/
|
||||
JS_ASSERT_IF(limitBlock &&
|
||||
limitBlock->isBlock() &&
|
||||
limitBlock->isClonedBlock() &&
|
||||
limitClone->getPrivate() == js_FloatingFrameIfGenerator(cx, fp),
|
||||
sharedBlock);
|
||||
|
||||
@ -327,7 +326,7 @@ js::BoxNonStrictThis(JSContext *cx, const CallReceiver &call)
|
||||
#endif
|
||||
|
||||
if (thisv.isNullOrUndefined()) {
|
||||
JSObject *thisp = call.callee().getGlobal()->thisObject(cx);
|
||||
JSObject *thisp = call.callee().global().thisObject(cx);
|
||||
if (!thisp)
|
||||
return false;
|
||||
call.thisv().setObject(*thisp);
|
||||
@ -459,7 +458,7 @@ js::RunScript(JSContext *cx, JSScript *script, StackFrame *fp)
|
||||
|
||||
/* FIXME: Once bug 470510 is fixed, make this an assert. */
|
||||
if (script->compileAndGo) {
|
||||
if (fp->scopeChain().getGlobal()->isCleared()) {
|
||||
if (fp->scopeChain().global().isCleared()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CLEARED_SCOPE);
|
||||
return false;
|
||||
}
|
||||
@ -1088,8 +1087,8 @@ EnterWith(JSContext *cx, jsint stackIndex)
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
|
||||
JSObject *withobj = js_NewWithObject(cx, obj, parent,
|
||||
sp + stackIndex - fp->base());
|
||||
JSObject *withobj = WithObject::create(cx, fp, *obj, *parent,
|
||||
sp + stackIndex - fp->base());
|
||||
if (!withobj)
|
||||
return JS_FALSE;
|
||||
|
||||
@ -1100,22 +1099,19 @@ EnterWith(JSContext *cx, jsint stackIndex)
|
||||
static void
|
||||
LeaveWith(JSContext *cx)
|
||||
{
|
||||
JSObject *withobj;
|
||||
|
||||
withobj = &cx->fp()->scopeChain();
|
||||
JS_ASSERT(withobj->getClass() == &WithClass);
|
||||
JS_ASSERT(withobj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()));
|
||||
JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0);
|
||||
withobj->setPrivate(NULL);
|
||||
cx->fp()->setScopeChainNoCallObj(*withobj->internalScopeChain());
|
||||
WithObject &withobj = cx->fp()->scopeChain().asWith();
|
||||
JS_ASSERT(withobj.maybeStackFrame() == js_FloatingFrameIfGenerator(cx, cx->fp()));
|
||||
JS_ASSERT(withobj.stackDepth() >= 0);
|
||||
withobj.setStackFrame(NULL);
|
||||
cx->fp()->setScopeChainNoCallObj(withobj.enclosingScope());
|
||||
}
|
||||
|
||||
bool
|
||||
js::IsActiveWithOrBlock(JSContext *cx, JSObject &obj, int stackDepth)
|
||||
js::IsActiveWithOrBlock(JSContext *cx, JSObject &obj, uint32_t stackDepth)
|
||||
{
|
||||
return (obj.isWith() || obj.isBlock()) &&
|
||||
obj.getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()) &&
|
||||
OBJ_BLOCK_DEPTH(cx, &obj) >= stackDepth;
|
||||
obj.asNestedScope().stackDepth() >= stackDepth;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1123,28 +1119,26 @@ js::IsActiveWithOrBlock(JSContext *cx, JSObject &obj, int stackDepth)
|
||||
* fp->sp on return to stackDepth.
|
||||
*/
|
||||
bool
|
||||
js::UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind)
|
||||
js::UnwindScope(JSContext *cx, uint32_t stackDepth, JSBool normalUnwind)
|
||||
{
|
||||
JS_ASSERT(stackDepth >= 0);
|
||||
JS_ASSERT(cx->fp()->base() + stackDepth <= cx->regs().sp);
|
||||
|
||||
StackFrame *fp = cx->fp();
|
||||
JSObject *obj = fp->maybeBlockChain();
|
||||
while (obj) {
|
||||
JS_ASSERT(obj->isStaticBlock());
|
||||
if (OBJ_BLOCK_DEPTH(cx, obj) < stackDepth)
|
||||
StaticBlockObject *block = fp->maybeBlockChain();
|
||||
while (block) {
|
||||
if (block->stackDepth() < stackDepth)
|
||||
break;
|
||||
obj = obj->staticBlockScopeChain();
|
||||
block = block->enclosingBlock();
|
||||
}
|
||||
fp->setBlockChain(obj);
|
||||
fp->setBlockChain(block);
|
||||
|
||||
for (;;) {
|
||||
JSObject &scopeChain = fp->scopeChain();
|
||||
if (!IsActiveWithOrBlock(cx, scopeChain, stackDepth))
|
||||
break;
|
||||
if (scopeChain.isBlock()) {
|
||||
if (scopeChain.isClonedBlock()) {
|
||||
/* Don't fail until after we've updated all stacks. */
|
||||
normalUnwind &= js_PutBlockObject(cx, normalUnwind);
|
||||
normalUnwind &= scopeChain.asClonedBlock().put(cx, normalUnwind);
|
||||
} else {
|
||||
LeaveWith(cx);
|
||||
}
|
||||
@ -1922,17 +1916,17 @@ BEGIN_CASE(JSOP_POPN)
|
||||
regs.sp -= GET_UINT16(regs.pc);
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(regs.fp()->base() <= regs.sp);
|
||||
JSObject *obj = regs.fp()->maybeBlockChain();
|
||||
JS_ASSERT_IF(obj,
|
||||
OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
|
||||
StaticBlockObject *block = regs.fp()->maybeBlockChain();
|
||||
JS_ASSERT_IF(block,
|
||||
block->stackDepth() + block->slotCount()
|
||||
<= (size_t) (regs.sp - regs.fp()->base()));
|
||||
for (obj = ®s.fp()->scopeChain(); obj; obj = obj->scopeChain()) {
|
||||
for (JSObject *obj = ®s.fp()->scopeChain(); obj; obj = obj->enclosingScope()) {
|
||||
if (!obj->isBlock() || !obj->isWith())
|
||||
continue;
|
||||
if (obj->getPrivate() != js_FloatingFrameIfGenerator(cx, regs.fp()))
|
||||
break;
|
||||
JS_ASSERT(regs.fp()->base() + OBJ_BLOCK_DEPTH(cx, obj)
|
||||
+ (obj->isBlock() ? OBJ_BLOCK_COUNT(cx, obj) : 1)
|
||||
JS_ASSERT(regs.fp()->base() + obj->asBlock().stackDepth()
|
||||
+ (obj->isBlock() ? obj->asBlock().slotCount() : 1)
|
||||
<= regs.sp);
|
||||
}
|
||||
#endif
|
||||
@ -2345,7 +2339,7 @@ END_CASE(JSOP_ENUMCONSTELEM)
|
||||
#endif
|
||||
|
||||
BEGIN_CASE(JSOP_BINDGNAME)
|
||||
PUSH_OBJECT(*regs.fp()->scopeChain().getGlobal());
|
||||
PUSH_OBJECT(regs.fp()->scopeChain().global());
|
||||
END_CASE(JSOP_BINDGNAME)
|
||||
|
||||
BEGIN_CASE(JSOP_BINDNAME)
|
||||
@ -2979,9 +2973,9 @@ BEGIN_CASE(JSOP_LENGTH)
|
||||
}
|
||||
|
||||
if (obj->isArguments()) {
|
||||
ArgumentsObject *argsobj = obj->asArguments();
|
||||
if (!argsobj->hasOverriddenLength()) {
|
||||
uint32_t length = argsobj->initialLength();
|
||||
ArgumentsObject &argsobj = obj->asArguments();
|
||||
if (!argsobj.hasOverriddenLength()) {
|
||||
uint32_t length = argsobj.initialLength();
|
||||
JS_ASSERT(length < INT32_MAX);
|
||||
rval = Int32Value(int32_t(length));
|
||||
break;
|
||||
@ -3038,14 +3032,14 @@ BEGIN_CASE(JSOP_CALLPROP)
|
||||
if (lval.isObject()) {
|
||||
objv = lval;
|
||||
} else {
|
||||
GlobalObject *global = regs.fp()->scopeChain().getGlobal();
|
||||
GlobalObject &global = regs.fp()->scopeChain().global();
|
||||
JSObject *pobj;
|
||||
if (lval.isString()) {
|
||||
pobj = global->getOrCreateStringPrototype(cx);
|
||||
pobj = global.getOrCreateStringPrototype(cx);
|
||||
} else if (lval.isNumber()) {
|
||||
pobj = global->getOrCreateNumberPrototype(cx);
|
||||
pobj = global.getOrCreateNumberPrototype(cx);
|
||||
} else if (lval.isBoolean()) {
|
||||
pobj = global->getOrCreateBooleanPrototype(cx);
|
||||
pobj = global.getOrCreateBooleanPrototype(cx);
|
||||
} else {
|
||||
JS_ASSERT(lval.isNull() || lval.isUndefined());
|
||||
js_ReportIsNullOrUndefined(cx, -1, lval, NULL);
|
||||
@ -3125,7 +3119,7 @@ BEGIN_CASE(JSOP_SETMETHOD)
|
||||
JSObject *obj;
|
||||
VALUE_TO_OBJECT(cx, &lref, obj);
|
||||
|
||||
JS_ASSERT_IF(op == JSOP_SETGNAME, obj == regs.fp()->scopeChain().getGlobal());
|
||||
JS_ASSERT_IF(op == JSOP_SETGNAME, obj == ®s.fp()->scopeChain().global());
|
||||
|
||||
do {
|
||||
PropertyCache *cache = &JS_PROPERTY_CACHE(cx);
|
||||
@ -3258,7 +3252,7 @@ BEGIN_CASE(JSOP_GETELEM)
|
||||
goto end_getelem;
|
||||
}
|
||||
} else if (obj->isArguments()) {
|
||||
if (obj->asArguments()->getElement(index, &rval))
|
||||
if (obj->asArguments().getElement(index, &rval))
|
||||
goto end_getelem;
|
||||
}
|
||||
|
||||
@ -3506,7 +3500,7 @@ BEGIN_CASE(JSOP_CALLNAME)
|
||||
|
||||
bool global = js_CodeSpec[op].format & JOF_GNAME;
|
||||
if (global)
|
||||
obj = obj->getGlobal();
|
||||
obj = &obj->global();
|
||||
|
||||
Value rval;
|
||||
|
||||
@ -3552,8 +3546,8 @@ BEGIN_CASE(JSOP_CALLNAME)
|
||||
} else {
|
||||
Shape *shape = (Shape *)prop;
|
||||
JSObject *normalized = obj;
|
||||
if (normalized->getClass() == &WithClass && !shape->hasDefaultGetter())
|
||||
normalized = js_UnwrapWithObject(cx, normalized);
|
||||
if (normalized->isWith() && !shape->hasDefaultGetter())
|
||||
normalized = &normalized->asWith().object();
|
||||
NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval);
|
||||
}
|
||||
|
||||
@ -3632,7 +3626,7 @@ BEGIN_CASE(JSOP_REGEXP)
|
||||
* bytecode at pc.
|
||||
*/
|
||||
jsatomid index = GET_FULL_INDEX(0);
|
||||
JSObject *proto = regs.fp()->scopeChain().getGlobal()->getOrCreateRegExpPrototype(cx);
|
||||
JSObject *proto = regs.fp()->scopeChain().global().getOrCreateRegExpPrototype(cx);
|
||||
if (!proto)
|
||||
goto error;
|
||||
JSObject *obj = js_CloneRegExpObject(cx, script->getRegExp(index), proto);
|
||||
@ -5102,7 +5096,7 @@ BEGIN_CASE(JSOP_GETFUNNS)
|
||||
JS_ASSERT(!script->strictModeCode);
|
||||
|
||||
Value rval;
|
||||
if (!cx->fp()->scopeChain().getGlobal()->getFunctionNamespace(cx, &rval))
|
||||
if (!cx->fp()->scopeChain().global().getFunctionNamespace(cx, &rval))
|
||||
goto error;
|
||||
PUSH_COPY(rval);
|
||||
}
|
||||
@ -5115,26 +5109,26 @@ BEGIN_CASE(JSOP_ENTERLET1)
|
||||
{
|
||||
JSObject *obj;
|
||||
LOAD_OBJECT(0, obj);
|
||||
JS_ASSERT(obj->isStaticBlock());
|
||||
JS_ASSERT(regs.fp()->maybeBlockChain() == obj->staticBlockScopeChain());
|
||||
StaticBlockObject &blockObj = obj->asStaticBlock();
|
||||
JS_ASSERT(regs.fp()->maybeBlockChain() == blockObj.enclosingBlock());
|
||||
|
||||
if (op == JSOP_ENTERBLOCK) {
|
||||
JS_ASSERT(regs.fp()->base() + OBJ_BLOCK_DEPTH(cx, obj) == regs.sp);
|
||||
Value *vp = regs.sp + OBJ_BLOCK_COUNT(cx, obj);
|
||||
JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp);
|
||||
Value *vp = regs.sp + blockObj.slotCount();
|
||||
JS_ASSERT(regs.sp < vp);
|
||||
JS_ASSERT(vp <= regs.fp()->slots() + script->nslots);
|
||||
SetValueRangeToUndefined(regs.sp, vp);
|
||||
regs.sp = vp;
|
||||
} else if (op == JSOP_ENTERLET0) {
|
||||
JS_ASSERT(regs.fp()->base() + OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
|
||||
JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
|
||||
== regs.sp);
|
||||
} else if (op == JSOP_ENTERLET1) {
|
||||
JS_ASSERT(regs.fp()->base() + OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
|
||||
JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
|
||||
== regs.sp - 1);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(regs.fp()->maybeBlockChain() == obj->staticBlockScopeChain());
|
||||
JS_ASSERT(regs.fp()->maybeBlockChain() == blockObj.enclosingBlock());
|
||||
|
||||
/*
|
||||
* The young end of fp->scopeChain may omit blocks if we haven't closed
|
||||
@ -5145,19 +5139,18 @@ BEGIN_CASE(JSOP_ENTERLET1)
|
||||
*/
|
||||
JSObject *obj2 = ®s.fp()->scopeChain();
|
||||
while (obj2->isWith())
|
||||
obj2 = obj2->internalScopeChain();
|
||||
obj2 = &obj2->asWith().enclosingScope();
|
||||
if (obj2->isBlock() &&
|
||||
obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, regs.fp()))
|
||||
{
|
||||
JSObject *youngestProto = obj2->getProto();
|
||||
JS_ASSERT(youngestProto->isStaticBlock());
|
||||
JSObject *parent = obj;
|
||||
while ((parent = parent->scopeChain()) != youngestProto)
|
||||
StaticBlockObject &youngestProto = obj2->asClonedBlock().staticBlock();
|
||||
StaticBlockObject *parent = &blockObj;
|
||||
while ((parent = parent->enclosingBlock()) != &youngestProto)
|
||||
JS_ASSERT(parent);
|
||||
}
|
||||
#endif
|
||||
|
||||
regs.fp()->setBlockChain(obj);
|
||||
regs.fp()->setBlockChain(&blockObj);
|
||||
}
|
||||
END_CASE(JSOP_ENTERBLOCK)
|
||||
|
||||
@ -5165,33 +5158,29 @@ BEGIN_CASE(JSOP_LEAVEBLOCK)
|
||||
BEGIN_CASE(JSOP_LEAVEFORLETIN)
|
||||
BEGIN_CASE(JSOP_LEAVEBLOCKEXPR)
|
||||
{
|
||||
JS_ASSERT(regs.fp()->blockChain().isStaticBlock());
|
||||
DebugOnly<uintN> blockDepth = OBJ_BLOCK_DEPTH(cx, ®s.fp()->blockChain());
|
||||
JS_ASSERT(blockDepth <= StackDepth(script));
|
||||
StaticBlockObject &blockObj = regs.fp()->blockChain();
|
||||
JS_ASSERT(blockObj.stackDepth() <= StackDepth(script));
|
||||
|
||||
/*
|
||||
* If we're about to leave the dynamic scope of a block that has been
|
||||
* cloned onto fp->scopeChain, clear its private data, move its locals from
|
||||
* the stack into the clone, and pop it off the chain.
|
||||
*/
|
||||
JSObject &obj = regs.fp()->scopeChain();
|
||||
if (obj.getProto() == ®s.fp()->blockChain()) {
|
||||
JS_ASSERT(obj.isClonedBlock());
|
||||
if (!js_PutBlockObject(cx, JS_TRUE))
|
||||
goto error;
|
||||
}
|
||||
JSObject &scope = regs.fp()->scopeChain();
|
||||
if (scope.getProto() == &blockObj && !scope.asClonedBlock().put(cx, JS_TRUE))
|
||||
goto error;
|
||||
|
||||
regs.fp()->setBlockChain(regs.fp()->blockChain().staticBlockScopeChain());
|
||||
regs.fp()->setBlockChain(blockObj.enclosingBlock());
|
||||
|
||||
if (op == JSOP_LEAVEBLOCK) {
|
||||
/* Pop the block's slots. */
|
||||
regs.sp -= GET_UINT16(regs.pc);
|
||||
JS_ASSERT(regs.fp()->base() + blockDepth == regs.sp);
|
||||
JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp);
|
||||
} else if (op == JSOP_LEAVEBLOCKEXPR) {
|
||||
/* Pop the block's slots maintaining the topmost expr. */
|
||||
Value *vp = ®s.sp[-1];
|
||||
regs.sp -= GET_UINT16(regs.pc);
|
||||
JS_ASSERT(regs.fp()->base() + blockDepth == regs.sp - 1);
|
||||
JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp - 1);
|
||||
regs.sp[-1] = *vp;
|
||||
} else {
|
||||
/* Another op will pop; nothing to do here. */
|
||||
|
@ -324,13 +324,13 @@ class InterpreterFrames {
|
||||
* fp->sp on return to stackDepth.
|
||||
*/
|
||||
extern bool
|
||||
UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind);
|
||||
UnwindScope(JSContext *cx, uint32_t stackDepth, JSBool normalUnwind);
|
||||
|
||||
extern bool
|
||||
OnUnknownMethod(JSContext *cx, js::Value *vp);
|
||||
|
||||
extern bool
|
||||
IsActiveWithOrBlock(JSContext *cx, JSObject &obj, int stackDepth);
|
||||
IsActiveWithOrBlock(JSContext *cx, JSObject &obj, uint32_t stackDepth);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
|
@ -1278,7 +1278,7 @@ js_NewGenerator(JSContext *cx)
|
||||
JS_ASSERT(stackfp->base() == cx->regs().sp);
|
||||
JS_ASSERT(stackfp->actualArgs() <= stackfp->formalArgs());
|
||||
|
||||
GlobalObject *global = stackfp->scopeChain().getGlobal();
|
||||
GlobalObject *global = &stackfp->scopeChain().global();
|
||||
JSObject *proto = global->getOrCreateGeneratorPrototype(cx);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
@ -1622,7 +1622,7 @@ js_InitIteratorClasses(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
GlobalObject *global = &obj->asGlobal();
|
||||
|
||||
/*
|
||||
* Bail if Iterator has already been initialized. We test for Iterator
|
||||
|
@ -1012,12 +1012,12 @@ js_InitNumberClass(JSContext *cx, JSObject *obj)
|
||||
/* XXX must do at least once per new thread, so do it per JSContext... */
|
||||
FIX_FPU();
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
GlobalObject *global = &obj->asGlobal();
|
||||
|
||||
JSObject *numberProto = global->createBlankPrototype(cx, &NumberClass);
|
||||
if (!numberProto)
|
||||
return NULL;
|
||||
numberProto->asNumber()->setPrimitiveValue(0);
|
||||
numberProto->asNumber().setPrimitiveValue(0);
|
||||
|
||||
JSFunction *ctor = global->createConstructor(cx, Number, &NumberClass,
|
||||
CLASS_ATOM(cx, Number), 1);
|
||||
|
638
js/src/jsobj.cpp
638
js/src/jsobj.cpp
@ -948,7 +948,7 @@ static void
|
||||
AssertInnerizedScopeChain(JSContext *cx, JSObject &scopeobj)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (JSObject *o = &scopeobj; o; o = o->scopeChain()) {
|
||||
for (JSObject *o = &scopeobj; o; o = o->enclosingScope()) {
|
||||
if (JSObjectOp op = o->getClass()->ext.innerObject)
|
||||
JS_ASSERT(op(cx, o) == o);
|
||||
}
|
||||
@ -1133,7 +1133,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c
|
||||
JS_ASSERT((evalType == INDIRECT_EVAL) == (caller == NULL));
|
||||
AssertInnerizedScopeChain(cx, scopeobj);
|
||||
|
||||
if (!scopeobj.getGlobal()->isRuntimeCodeGenEnabled(cx)) {
|
||||
if (!scopeobj.global().isRuntimeCodeGenEnabled(cx)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_EVAL);
|
||||
return false;
|
||||
}
|
||||
@ -1175,7 +1175,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c
|
||||
JS_ASSERT(callerPC && JSOp(*callerPC) == JSOP_EVAL);
|
||||
#endif
|
||||
} else {
|
||||
JS_ASSERT(args.callee().getGlobal() == &scopeobj);
|
||||
JS_ASSERT(args.callee().global() == scopeobj);
|
||||
staticLevel = 0;
|
||||
|
||||
/* Use the global as 'this', modulo outerization. */
|
||||
@ -1305,7 +1305,7 @@ eval(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return WarnOnTooManyArgs(cx, args) &&
|
||||
EvalKernel(cx, args, INDIRECT_EVAL, NULL, *args.callee().getGlobal());
|
||||
EvalKernel(cx, args, INDIRECT_EVAL, NULL, args.callee().global());
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1332,7 +1332,7 @@ DirectEval(JSContext *cx, const CallArgs &args)
|
||||
bool
|
||||
IsBuiltinEvalForScope(JSObject *scopeChain, const Value &v)
|
||||
{
|
||||
return scopeChain->getGlobal()->getOriginalEval() == v;
|
||||
return scopeChain->global().getOriginalEval() == v;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2612,7 +2612,7 @@ obj_create(JSContext *cx, uintN argc, Value *vp)
|
||||
* Use the callee's global as the parent of the new object to avoid dynamic
|
||||
* scoping (i.e., using the caller's global).
|
||||
*/
|
||||
JSObject *obj = NewObjectWithGivenProto(cx, &ObjectClass, proto, vp->toObject().getGlobal());
|
||||
JSObject *obj = NewObjectWithGivenProto(cx, &ObjectClass, proto, &vp->toObject().global());
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
vp->setObject(*obj); /* Root and prepare for eventual return. */
|
||||
@ -3003,7 +3003,7 @@ js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JS
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (parent->isGlobal() && protoKey != JSProto_Null) {
|
||||
if (cache.lookupGlobal(clasp, parent->asGlobal(), kind, &entry))
|
||||
if (cache.lookupGlobal(clasp, &parent->asGlobal(), kind, &entry))
|
||||
return cache.newObjectFromHit(cx, entry);
|
||||
}
|
||||
|
||||
@ -3021,7 +3021,7 @@ js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JS
|
||||
return NULL;
|
||||
|
||||
if (entry != -1 && !obj->hasDynamicSlots())
|
||||
cache.fillGlobal(entry, clasp, parent->asGlobal(), kind, obj);
|
||||
cache.fillGlobal(entry, clasp, &parent->asGlobal(), kind, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
@ -3276,457 +3276,6 @@ js_InferFlags(JSContext *cx, uintN defaultFlags)
|
||||
return flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* ObjectOps and Class for with-statement stack objects.
|
||||
*/
|
||||
static JSBool
|
||||
with_LookupGeneric(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, JSProperty **propp)
|
||||
{
|
||||
/* Fixes bug 463997 */
|
||||
uintN flags = cx->resolveFlags;
|
||||
if (flags == RESOLVE_INFER)
|
||||
flags = js_InferFlags(cx, flags);
|
||||
flags |= JSRESOLVE_WITH;
|
||||
JSAutoResolveFlags rf(cx, flags);
|
||||
return obj->getProto()->lookupGeneric(cx, id, objp, propp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_LookupProperty(JSContext *cx, JSObject *obj, PropertyName *name, JSObject **objp, JSProperty **propp)
|
||||
{
|
||||
return with_LookupGeneric(cx, obj, ATOM_TO_JSID(name), objp, propp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_LookupElement(JSContext *cx, JSObject *obj, uint32_t index, JSObject **objp,
|
||||
JSProperty **propp)
|
||||
{
|
||||
jsid id;
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
return with_LookupGeneric(cx, obj, id, objp, propp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_LookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp, JSProperty **propp)
|
||||
{
|
||||
return with_LookupGeneric(cx, obj, SPECIALID_TO_JSID(sid), objp, propp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
|
||||
{
|
||||
return obj->getProto()->getGeneric(cx, id, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp)
|
||||
{
|
||||
return with_GetGeneric(cx, obj, receiver, ATOM_TO_JSID(name), vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp)
|
||||
{
|
||||
jsid id;
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
return with_GetGeneric(cx, obj, receiver, id, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
|
||||
{
|
||||
return with_GetGeneric(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
|
||||
{
|
||||
return obj->getProto()->setGeneric(cx, id, vp, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict)
|
||||
{
|
||||
return obj->getProto()->setProperty(cx, name, vp, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetElement(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict)
|
||||
{
|
||||
return obj->getProto()->setElement(cx, index, vp, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
|
||||
{
|
||||
return obj->getProto()->setSpecial(cx, sid, vp, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
|
||||
{
|
||||
return obj->getProto()->getGenericAttributes(cx, id, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
|
||||
{
|
||||
return obj->getProto()->getPropertyAttributes(cx, name, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, uintN *attrsp)
|
||||
{
|
||||
return obj->getProto()->getElementAttributes(cx, index, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
|
||||
{
|
||||
return obj->getProto()->getSpecialAttributes(cx, sid, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
|
||||
{
|
||||
return obj->getProto()->setGenericAttributes(cx, id, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
|
||||
{
|
||||
return obj->getProto()->setPropertyAttributes(cx, name, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, uintN *attrsp)
|
||||
{
|
||||
return obj->getProto()->setElementAttributes(cx, index, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
|
||||
{
|
||||
return obj->getProto()->setSpecialAttributes(cx, sid, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
|
||||
{
|
||||
return obj->getProto()->deleteGeneric(cx, id, rval, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_DeleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
|
||||
{
|
||||
return obj->getProto()->deleteProperty(cx, name, rval, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict)
|
||||
{
|
||||
return obj->getProto()->deleteElement(cx, index, rval, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_DeleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
|
||||
{
|
||||
return obj->getProto()->deleteSpecial(cx, sid, rval, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
Value *statep, jsid *idp)
|
||||
{
|
||||
return obj->getProto()->enumerate(cx, enum_op, statep, idp);
|
||||
}
|
||||
|
||||
static JSType
|
||||
with_TypeOf(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return JSTYPE_OBJECT;
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
with_ThisObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return obj->getWithThis();
|
||||
}
|
||||
|
||||
Class js::WithClass = {
|
||||
"With",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(3) | JSCLASS_IS_ANONYMOUS,
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub,
|
||||
NULL, /* finalize */
|
||||
NULL, /* reserved */
|
||||
NULL, /* checkAccess */
|
||||
NULL, /* call */
|
||||
NULL, /* construct */
|
||||
NULL, /* xdrObject */
|
||||
NULL, /* hasInstance */
|
||||
NULL, /* trace */
|
||||
JS_NULL_CLASS_EXT,
|
||||
{
|
||||
with_LookupGeneric,
|
||||
with_LookupProperty,
|
||||
with_LookupElement,
|
||||
with_LookupSpecial,
|
||||
NULL, /* defineGeneric */
|
||||
NULL, /* defineProperty */
|
||||
NULL, /* defineElement */
|
||||
NULL, /* defineSpecial */
|
||||
with_GetGeneric,
|
||||
with_GetProperty,
|
||||
with_GetElement,
|
||||
NULL, /* getElementIfPresent */
|
||||
with_GetSpecial,
|
||||
with_SetGeneric,
|
||||
with_SetProperty,
|
||||
with_SetElement,
|
||||
with_SetSpecial,
|
||||
with_GetGenericAttributes,
|
||||
with_GetPropertyAttributes,
|
||||
with_GetElementAttributes,
|
||||
with_GetSpecialAttributes,
|
||||
with_SetGenericAttributes,
|
||||
with_SetPropertyAttributes,
|
||||
with_SetElementAttributes,
|
||||
with_SetSpecialAttributes,
|
||||
with_DeleteGeneric,
|
||||
with_DeleteProperty,
|
||||
with_DeleteElement,
|
||||
with_DeleteSpecial,
|
||||
with_Enumerate,
|
||||
with_TypeOf,
|
||||
NULL, /* fix */
|
||||
with_ThisObject,
|
||||
NULL, /* clear */
|
||||
}
|
||||
};
|
||||
|
||||
static const gc::AllocKind WITH_FINALIZE_KIND = gc::FINALIZE_OBJECT4;
|
||||
|
||||
JS_REQUIRES_STACK JSObject *
|
||||
js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
RootedVarTypeObject type(cx);
|
||||
type = proto->getNewType(cx);
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
StackFrame *priv = js_FloatingFrameIfGenerator(cx, cx->fp());
|
||||
|
||||
RootedVarShape emptyWithShape(cx);
|
||||
emptyWithShape = EmptyShape::getInitialShape(cx, &WithClass, proto,
|
||||
parent->getGlobal(),
|
||||
WITH_FINALIZE_KIND);
|
||||
if (!emptyWithShape)
|
||||
return NULL;
|
||||
|
||||
obj = JSObject::create(cx, WITH_FINALIZE_KIND, emptyWithShape, type, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
OBJ_SET_BLOCK_DEPTH(cx, obj, depth);
|
||||
|
||||
if (!obj->setInternalScopeChain(cx, parent))
|
||||
return NULL;
|
||||
obj->setPrivate(priv);
|
||||
|
||||
JSObject *thisp = proto->thisObject(cx);
|
||||
if (!thisp)
|
||||
return NULL;
|
||||
|
||||
assertSameCompartment(cx, obj, thisp);
|
||||
|
||||
obj->setWithThis(thisp);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static const uint32_t BLOCK_RESERVED_SLOTS = 2;
|
||||
static const gc::AllocKind BLOCK_FINALIZE_KIND = gc::FINALIZE_OBJECT4;
|
||||
|
||||
JSObject *
|
||||
js_NewBlockObject(JSContext *cx)
|
||||
{
|
||||
RootedVarTypeObject type(cx);
|
||||
type = cx->compartment->getEmptyType(cx);
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
RootedVarShape emptyBlockShape(cx);
|
||||
emptyBlockShape = EmptyShape::getInitialShape(cx, &BlockClass, NULL, NULL,
|
||||
BLOCK_FINALIZE_KIND);
|
||||
if (!emptyBlockShape)
|
||||
return NULL;
|
||||
|
||||
return JSObject::create(cx, FINALIZE_OBJECT4, emptyBlockShape, type, NULL);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_CloneBlockObject(JSContext *cx, JSObject *proto, StackFrame *fp)
|
||||
{
|
||||
JS_ASSERT(proto->isStaticBlock());
|
||||
|
||||
RootedVarTypeObject type(cx);
|
||||
type = proto->getNewType(cx);
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
HeapValue *slots;
|
||||
if (!PreallocateObjectDynamicSlots(cx, proto->lastProperty(), &slots))
|
||||
return NULL;
|
||||
|
||||
RootedVarShape shape(cx);
|
||||
shape = proto->lastProperty();
|
||||
|
||||
JSObject *clone = JSObject::create(cx, BLOCK_FINALIZE_KIND,
|
||||
shape, type, slots);
|
||||
if (!clone)
|
||||
return NULL;
|
||||
|
||||
/* Set the parent if necessary, as for call objects. */
|
||||
JSObject *global = fp->scopeChain().getGlobal();
|
||||
if (global != clone->getParent()) {
|
||||
JS_ASSERT(clone->getParent() == NULL);
|
||||
if (!clone->setParent(cx, global))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_ASSERT(!clone->inDictionaryMode());
|
||||
JS_ASSERT(clone->isClonedBlock());
|
||||
JS_ASSERT(clone->slotSpan() >= OBJ_BLOCK_COUNT(cx, proto) + BLOCK_RESERVED_SLOTS);
|
||||
|
||||
clone->setPrivate(js_FloatingFrameIfGenerator(cx, fp));
|
||||
clone->setSlot(JSSLOT_BLOCK_DEPTH, proto->getSlot(JSSLOT_BLOCK_DEPTH));
|
||||
|
||||
if (clone->lastProperty()->extensibleParents() && !clone->generateOwnShape(cx))
|
||||
return NULL;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK JSBool
|
||||
js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
|
||||
{
|
||||
StackFrame *const fp = cx->fp();
|
||||
JSObject *obj = &fp->scopeChain();
|
||||
JS_ASSERT(obj->isClonedBlock());
|
||||
JS_ASSERT(obj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()));
|
||||
|
||||
/* Block objects should have all reserved slots allocated early. */
|
||||
uintN count = OBJ_BLOCK_COUNT(cx, obj);
|
||||
JS_ASSERT(obj->slotSpan() >= JSSLOT_BLOCK_DEPTH + 1 + count);
|
||||
|
||||
/* The block and its locals must be on the current stack for GC safety. */
|
||||
uintN depth = OBJ_BLOCK_DEPTH(cx, obj);
|
||||
JS_ASSERT(depth <= size_t(cx->regs().sp - fp->base()));
|
||||
JS_ASSERT(count <= size_t(cx->regs().sp - fp->base() - depth));
|
||||
|
||||
/* See comments in CheckDestructuring in frontend/Parser.cpp. */
|
||||
JS_ASSERT(count >= 1);
|
||||
|
||||
if (normalUnwind) {
|
||||
uintN slot = JSSLOT_BLOCK_FIRST_FREE_SLOT;
|
||||
depth += fp->numFixed();
|
||||
obj->copySlotRange(slot, fp->slots() + depth, count);
|
||||
}
|
||||
|
||||
/* We must clear the private slot even with errors. */
|
||||
obj->setPrivate(NULL);
|
||||
fp->setScopeChainNoCallObj(*obj->internalScopeChain());
|
||||
return normalUnwind;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
block_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
{
|
||||
/*
|
||||
* Block objects are never exposed to script, and the engine handles them
|
||||
* with care. So unlike other getters, this one can assert (rather than
|
||||
* check) certain invariants about obj.
|
||||
*/
|
||||
JS_ASSERT(obj->isClonedBlock());
|
||||
uintN index = (uintN) JSID_TO_INT(id);
|
||||
JS_ASSERT(index < OBJ_BLOCK_COUNT(cx, obj));
|
||||
|
||||
StackFrame *fp = (StackFrame *) obj->getPrivate();
|
||||
if (fp) {
|
||||
fp = js_LiveFrameIfGenerator(fp);
|
||||
index += fp->numFixed() + OBJ_BLOCK_DEPTH(cx, obj);
|
||||
JS_ASSERT(index < fp->numSlots());
|
||||
*vp = fp->slots()[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Values are in slots immediately following the class-reserved ones. */
|
||||
JS_ASSERT(obj->getSlot(JSSLOT_FREE(&BlockClass) + index) == *vp);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
block_setProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
{
|
||||
JS_ASSERT(obj->isClonedBlock());
|
||||
uintN index = (uintN) JSID_TO_INT(id);
|
||||
JS_ASSERT(index < OBJ_BLOCK_COUNT(cx, obj));
|
||||
|
||||
StackFrame *fp = (StackFrame *) obj->getPrivate();
|
||||
if (fp) {
|
||||
fp = js_LiveFrameIfGenerator(fp);
|
||||
index += fp->numFixed() + OBJ_BLOCK_DEPTH(cx, obj);
|
||||
JS_ASSERT(index < fp->numSlots());
|
||||
fp->slots()[index] = *vp;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The value in *vp will be written back to the slot in obj that was
|
||||
* allocated when this let binding was defined.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
const Shape *
|
||||
JSObject::defineBlockVariable(JSContext *cx, jsid id, intN index, bool *redeclared)
|
||||
{
|
||||
JS_ASSERT(isStaticBlock());
|
||||
|
||||
*redeclared = false;
|
||||
|
||||
RootedVarObject self(cx, this);
|
||||
|
||||
/* Inline JSObject::addProperty in order to trap the redefinition case. */
|
||||
Shape **spp;
|
||||
Shape *shape = Shape::search(cx, lastProperty(), id, &spp, true);
|
||||
if (shape) {
|
||||
*redeclared = true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't convert this object to dictionary mode so that we can clone the
|
||||
* block's shape later.
|
||||
*/
|
||||
uint32_t slot = JSSLOT_FREE(&BlockClass) + index;
|
||||
shape = self->addPropertyInternal(cx, id, block_getProperty, block_setProperty,
|
||||
slot, JSPROP_ENUMERATE | JSPROP_PERMANENT,
|
||||
Shape::HAS_SHORTID, index, spp,
|
||||
/* allowDictionary = */ false);
|
||||
if (!shape)
|
||||
return NULL;
|
||||
return shape;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JSObject::nonNativeSetProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict)
|
||||
{
|
||||
@ -4128,153 +3677,6 @@ JSObject::swap(JSContext *cx, JSObject *other)
|
||||
return true;
|
||||
}
|
||||
|
||||
#if JS_HAS_XDR
|
||||
|
||||
#define NO_PARENT_INDEX UINT32_MAX
|
||||
|
||||
uint32_t
|
||||
FindObjectIndex(JSObjectArray *array, JSObject *obj)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (array) {
|
||||
i = array->length;
|
||||
do {
|
||||
|
||||
if (array->vector[--i] == obj)
|
||||
return i;
|
||||
} while (i != 0);
|
||||
}
|
||||
|
||||
return NO_PARENT_INDEX;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_XDRBlockObject(JSXDRState *xdr, JSObject **objp)
|
||||
{
|
||||
JSContext *cx;
|
||||
uint32_t parentId;
|
||||
JSObject *obj, *parent;
|
||||
uintN depth, count;
|
||||
uint32_t depthAndCount;
|
||||
const Shape *shape;
|
||||
|
||||
cx = xdr->cx;
|
||||
#ifdef __GNUC__
|
||||
obj = NULL; /* quell GCC overwarning */
|
||||
#endif
|
||||
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
obj = *objp;
|
||||
parent = obj->staticBlockScopeChain();
|
||||
parentId = JSScript::isValidOffset(xdr->script->objectsOffset)
|
||||
? FindObjectIndex(xdr->script->objects(), parent)
|
||||
: NO_PARENT_INDEX;
|
||||
depth = uint16_t(OBJ_BLOCK_DEPTH(cx, obj));
|
||||
count = uint16_t(OBJ_BLOCK_COUNT(cx, obj));
|
||||
depthAndCount = uint32_t(depth << 16) | count;
|
||||
}
|
||||
#ifdef __GNUC__ /* suppress bogus gcc warnings */
|
||||
else count = 0;
|
||||
#endif
|
||||
|
||||
/* First, XDR the parent atomid. */
|
||||
if (!JS_XDRUint32(xdr, &parentId))
|
||||
return JS_FALSE;
|
||||
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
obj = js_NewBlockObject(cx);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
*objp = obj;
|
||||
|
||||
/*
|
||||
* If there's a parent id, then get the parent out of our script's
|
||||
* object array. We know that we XDR block object in outer-to-inner
|
||||
* order, which means that getting the parent now will work.
|
||||
*/
|
||||
if (parentId == NO_PARENT_INDEX)
|
||||
parent = NULL;
|
||||
else
|
||||
parent = xdr->script->getObject(parentId);
|
||||
obj->setStaticBlockScopeChain(parent);
|
||||
}
|
||||
|
||||
if (!JS_XDRUint32(xdr, &depthAndCount))
|
||||
return false;
|
||||
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
depth = uint16_t(depthAndCount >> 16);
|
||||
count = uint16_t(depthAndCount);
|
||||
obj->setSlot(JSSLOT_BLOCK_DEPTH, Value(Int32Value(depth)));
|
||||
|
||||
/*
|
||||
* XDR the block object's properties. We know that there are 'count'
|
||||
* properties to XDR, stored as id/shortid pairs.
|
||||
*/
|
||||
for (uintN i = 0; i < count; i++) {
|
||||
JSAtom *atom;
|
||||
|
||||
/* XDR the real id. */
|
||||
if (!js_XDRAtom(xdr, &atom))
|
||||
return false;
|
||||
|
||||
bool redeclared;
|
||||
if (!obj->defineBlockVariable(cx, ATOM_TO_JSID(atom), i, &redeclared)) {
|
||||
JS_ASSERT(!redeclared);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
AutoShapeVector shapes(cx);
|
||||
shapes.growBy(count);
|
||||
|
||||
for (Shape::Range r(obj->lastProperty()); !r.empty(); r.popFront()) {
|
||||
shape = &r.front();
|
||||
shapes[shape->shortid()] = shape;
|
||||
}
|
||||
|
||||
/*
|
||||
* XDR the block object's properties. We know that there are 'count'
|
||||
* properties to XDR, stored as id/shortid pairs.
|
||||
*/
|
||||
for (uintN i = 0; i < count; i++) {
|
||||
shape = shapes[i];
|
||||
JS_ASSERT(shape->getter() == block_getProperty);
|
||||
|
||||
jsid propid = shape->propid();
|
||||
JS_ASSERT(JSID_IS_ATOM(propid));
|
||||
JSAtom *atom = JSID_TO_ATOM(propid);
|
||||
|
||||
#ifdef DEBUG
|
||||
uint16_t shortid = uint16_t(shape->shortid());
|
||||
JS_ASSERT(shortid == i);
|
||||
#endif
|
||||
|
||||
/* XDR the real id. */
|
||||
if (!js_XDRAtom(xdr, &atom))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Class js::BlockClass = {
|
||||
"Block",
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(BLOCK_RESERVED_SLOTS) |
|
||||
JSCLASS_IS_ANONYMOUS,
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub
|
||||
};
|
||||
|
||||
static bool
|
||||
DefineStandardSlot(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
|
||||
const Value &v, uint32_t attrs, bool &named)
|
||||
@ -5030,7 +4432,7 @@ js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
|
||||
{
|
||||
RootObject objRoot(cx, &obj);
|
||||
|
||||
obj = obj->getGlobal();
|
||||
obj = &obj->global();
|
||||
if (!obj->isGlobal()) {
|
||||
*objp = NULL;
|
||||
return true;
|
||||
@ -5074,7 +4476,7 @@ js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey protoKey,
|
||||
RootedVarObject obj(cx);
|
||||
|
||||
if (start) {
|
||||
obj = start->getGlobal();
|
||||
obj = &start->global();
|
||||
OBJ_TO_INNER_OBJECT(cx, *obj.address());
|
||||
} else {
|
||||
obj = GetGlobalForScopeChain(cx);
|
||||
@ -5286,7 +4688,7 @@ js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj, jsid id)
|
||||
* may gain such properties via eval introducing new vars; see bug 490364.
|
||||
*/
|
||||
if (obj->isCall()) {
|
||||
while ((obj = obj->scopeChain()) != NULL) {
|
||||
while ((obj = obj->enclosingScope()) != NULL) {
|
||||
if (!PurgeProtoChain(cx, obj, id))
|
||||
return false;
|
||||
}
|
||||
@ -5724,13 +5126,13 @@ js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
|
||||
* the actual behavior even if the id could be found on the scope chain
|
||||
* before the global object.
|
||||
*/
|
||||
scopeChain = scopeChain->getGlobal();
|
||||
scopeChain = &scopeChain->global();
|
||||
}
|
||||
|
||||
/* Scan entries on the scope chain that we can cache across. */
|
||||
entry = JS_NO_PROP_CACHE_FILL;
|
||||
obj = scopeChain;
|
||||
parent = obj->scopeChain();
|
||||
parent = obj->enclosingScope();
|
||||
for (scopeIndex = 0;
|
||||
parent
|
||||
? IsCacheableNonGlobalScope(obj)
|
||||
@ -5776,7 +5178,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
|
||||
goto out;
|
||||
}
|
||||
obj = parent;
|
||||
parent = obj->scopeChain();
|
||||
parent = obj->enclosingScope();
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@ -5791,7 +5193,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
|
||||
* We conservatively assume that a resolve hook could mutate the scope
|
||||
* chain during JSObject::lookupGeneric. So we read parent here again.
|
||||
*/
|
||||
parent = obj->scopeChain();
|
||||
parent = obj->enclosingScope();
|
||||
if (!parent) {
|
||||
pobj = NULL;
|
||||
break;
|
||||
@ -5825,7 +5227,7 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id)
|
||||
* This function should not be called for a global object or from the
|
||||
* trace and should have a valid cache entry for native scopeChain.
|
||||
*/
|
||||
JS_ASSERT(scopeChain->scopeChain() != NULL);
|
||||
JS_ASSERT(scopeChain->enclosingScope() != NULL);
|
||||
|
||||
JSObject *obj = scopeChain;
|
||||
|
||||
@ -5850,14 +5252,14 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id)
|
||||
JS_ASSERT(obj->isGlobal());
|
||||
return obj;
|
||||
}
|
||||
JS_ASSERT_IF(obj->isInternalScope(), pobj->getClass() == obj->getClass());
|
||||
JS_ASSERT_IF(obj->isScope(), pobj->getClass() == obj->getClass());
|
||||
DebugOnly<PropertyCacheEntry*> entry =
|
||||
JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, (Shape *) prop);
|
||||
JS_ASSERT(entry);
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSObject *parent = obj->scopeChain();
|
||||
JSObject *parent = obj->enclosingScope();
|
||||
if (!parent)
|
||||
return obj;
|
||||
obj = parent;
|
||||
@ -5877,7 +5279,7 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id)
|
||||
* chain during JSObject::lookupGeneric. So we must check if parent is
|
||||
* not null here even if it wasn't before the lookup.
|
||||
*/
|
||||
JSObject *parent = obj->scopeChain();
|
||||
JSObject *parent = obj->enclosingScope();
|
||||
if (!parent)
|
||||
break;
|
||||
obj = parent;
|
||||
@ -6863,7 +6265,7 @@ js_GetClassPrototype(JSContext *cx, JSObject *scopeobj, JSProtoKey protoKey,
|
||||
if (protoKey != JSProto_Null) {
|
||||
GlobalObject *global;
|
||||
if (scopeobj) {
|
||||
global = scopeobj->getGlobal();
|
||||
global = &scopeobj->global();
|
||||
} else {
|
||||
global = GetCurrentGlobal(cx);
|
||||
if (!global) {
|
||||
|
256
js/src/jsobj.h
256
js/src/jsobj.h
@ -343,13 +343,20 @@ extern Class WithClass;
|
||||
extern Class XMLFilterClass;
|
||||
|
||||
class ArgumentsObject;
|
||||
class BlockObject;
|
||||
class BooleanObject;
|
||||
class ClonedBlockObject;
|
||||
class DeclEnvObject;
|
||||
class GlobalObject;
|
||||
class NestedScopeObject;
|
||||
class NormalArgumentsObject;
|
||||
class NumberObject;
|
||||
class ScopeObject;
|
||||
class StaticBlockObject;
|
||||
class StrictArgumentsObject;
|
||||
class StringObject;
|
||||
class RegExpObject;
|
||||
class WithObject;
|
||||
|
||||
/*
|
||||
* Header structure for object element arrays. This structure is immediately
|
||||
@ -775,10 +782,8 @@ struct JSObject : js::gc::Cell
|
||||
inline void nativeSetSlot(uintN slot, const js::Value &value);
|
||||
inline void nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value);
|
||||
|
||||
inline js::Value getReservedSlot(uintN index) const;
|
||||
inline const js::Value &getReservedSlot(uintN index) const;
|
||||
inline js::HeapValue &getReservedSlotRef(uintN index);
|
||||
|
||||
/* Call this only after the appropriate ensure{Class,Instance}ReservedSlots call. */
|
||||
inline void setReservedSlot(uintN index, const js::Value &v);
|
||||
|
||||
/* For slots which are known to always be fixed, due to the way they are allocated. */
|
||||
@ -873,11 +878,11 @@ struct JSObject : js::gc::Cell
|
||||
*
|
||||
* Except for the non-script-accessible builtins, the global with which an
|
||||
* object is associated can be reached by following parent links to that
|
||||
* global (see getGlobal()).
|
||||
* global (see global()).
|
||||
*
|
||||
* The scope chain of an object is the link in the search path when a
|
||||
* script does a name lookup on a scope object. For JS internal scope
|
||||
* objects --- Call, Block, DeclEnv and With --- the chain is stored in
|
||||
* objects --- Call, DeclEnv and block --- the chain is stored in
|
||||
* the first fixed slot of the object, and the object's parent is the
|
||||
* associated global. For other scope objects, the chain is stored in the
|
||||
* object's parent.
|
||||
@ -893,30 +898,14 @@ struct JSObject : js::gc::Cell
|
||||
inline JSObject *getParent() const;
|
||||
bool setParent(JSContext *cx, JSObject *newParent);
|
||||
|
||||
/* Get the scope chain of an arbitrary scope object. */
|
||||
inline JSObject *scopeChain() const;
|
||||
|
||||
inline bool isGlobal() const;
|
||||
inline js::GlobalObject *asGlobal();
|
||||
inline js::GlobalObject *getGlobal() const;
|
||||
|
||||
inline bool isInternalScope() const;
|
||||
|
||||
/* Access the scope chain of an internal scope object. */
|
||||
inline JSObject *internalScopeChain() const;
|
||||
inline bool setInternalScopeChain(JSContext *cx, JSObject *obj);
|
||||
static inline size_t offsetOfInternalScopeChain();
|
||||
|
||||
/*
|
||||
* Access the scope chain of a static block object. These do not appear
|
||||
* on scope chains but mirror their structure, and can have a NULL
|
||||
* scope chain.
|
||||
* Get the enclosing scope of an object. When called on non-scope object,
|
||||
* this will just be the global (the name "enclosing scope" still applies
|
||||
* in this situation because non-scope objects can be on the scope chain).
|
||||
*/
|
||||
inline JSObject *staticBlockScopeChain() const;
|
||||
inline void setStaticBlockScopeChain(JSObject *obj);
|
||||
inline JSObject *enclosingScope();
|
||||
|
||||
/* Common fixed slot for the scope chain of internal scope objects. */
|
||||
static const uint32_t SCOPE_CHAIN_SLOT = 0;
|
||||
inline js::GlobalObject &global() const;
|
||||
|
||||
/* Private data accessors. */
|
||||
|
||||
@ -981,12 +970,6 @@ struct JSObject : js::gc::Cell
|
||||
return getFixedSlotOffset(JSSLOT_PRIMITIVE_THIS);
|
||||
}
|
||||
|
||||
public:
|
||||
inline js::BooleanObject *asBoolean();
|
||||
inline js::NumberObject *asNumber();
|
||||
inline js::StringObject *asString();
|
||||
inline js::RegExpObject *asRegExp();
|
||||
|
||||
/* Accessors for elements. */
|
||||
|
||||
js::ObjectElements *getElementsHeader() const {
|
||||
@ -1079,14 +1062,6 @@ struct JSObject : js::gc::Cell
|
||||
inline uint32_t arrayBufferByteLength();
|
||||
inline uint8_t * arrayBufferDataOffset();
|
||||
|
||||
public:
|
||||
inline js::ArgumentsObject *asArguments();
|
||||
inline js::NormalArgumentsObject *asNormalArguments();
|
||||
inline js::StrictArgumentsObject *asStrictArguments();
|
||||
|
||||
public:
|
||||
inline js::CallObject &asCall();
|
||||
|
||||
public:
|
||||
/*
|
||||
* Date-specific getters and setters.
|
||||
@ -1178,12 +1153,6 @@ struct JSObject : js::gc::Cell
|
||||
*/
|
||||
inline js::Wrapper *getWrapperHandler() const;
|
||||
|
||||
/*
|
||||
* With object-specific getters and setters.
|
||||
*/
|
||||
inline JSObject *getWithThis() const;
|
||||
inline void setWithThis(JSObject *thisp);
|
||||
|
||||
/*
|
||||
* Back to generic stuff.
|
||||
*/
|
||||
@ -1220,6 +1189,7 @@ struct JSObject : js::gc::Cell
|
||||
private:
|
||||
js::Shape *getChildProperty(JSContext *cx, js::Shape *parent, js::StackShape &child);
|
||||
|
||||
protected:
|
||||
/*
|
||||
* Internal helper that adds a shape not yet mapped by this object.
|
||||
*
|
||||
@ -1233,6 +1203,7 @@ struct JSObject : js::gc::Cell
|
||||
uintN flags, intN shortid, js::Shape **spp,
|
||||
bool allowDictionary);
|
||||
|
||||
private:
|
||||
bool toDictionaryMode(JSContext *cx);
|
||||
|
||||
struct TradeGutsReserved;
|
||||
@ -1345,46 +1316,6 @@ struct JSObject : js::gc::Cell
|
||||
|
||||
bool swap(JSContext *cx, JSObject *other);
|
||||
|
||||
const js::Shape *defineBlockVariable(JSContext *cx, jsid id, intN index, bool *redeclared);
|
||||
|
||||
inline bool isArguments() const;
|
||||
inline bool isArrayBuffer() const;
|
||||
inline bool isNormalArguments() const;
|
||||
inline bool isStrictArguments() const;
|
||||
inline bool isArray() const;
|
||||
inline bool isDenseArray() const;
|
||||
inline bool isSlowArray() const;
|
||||
inline bool isNumber() const;
|
||||
inline bool isBoolean() const;
|
||||
inline bool isString() const;
|
||||
inline bool isPrimitive() const;
|
||||
inline bool isDate() const;
|
||||
inline bool isFunction() const;
|
||||
inline bool isObject() const;
|
||||
inline bool isWith() const;
|
||||
inline bool isBlock() const;
|
||||
inline bool isStaticBlock() const;
|
||||
inline bool isClonedBlock() const;
|
||||
inline bool isCall() const;
|
||||
inline bool isDeclEnv() const;
|
||||
inline bool isRegExp() const;
|
||||
inline bool isScript() const;
|
||||
inline bool isGenerator() const;
|
||||
inline bool isIterator() const;
|
||||
inline bool isStopIteration() const;
|
||||
inline bool isError() const;
|
||||
inline bool isXML() const;
|
||||
inline bool isNamespace() const;
|
||||
inline bool isWeakMap() const;
|
||||
inline bool isFunctionProxy() const;
|
||||
inline bool isProxy() const;
|
||||
|
||||
inline bool isXMLId() const;
|
||||
inline bool isQName() const;
|
||||
|
||||
inline bool isWrapper() const;
|
||||
inline bool isCrossCompartmentWrapper() const;
|
||||
|
||||
inline void initArrayClass();
|
||||
|
||||
static inline void writeBarrierPre(JSObject *obj);
|
||||
@ -1392,6 +1323,99 @@ struct JSObject : js::gc::Cell
|
||||
inline void privateWriteBarrierPre(void **oldval);
|
||||
inline void privateWriteBarrierPost(void **oldval);
|
||||
|
||||
/*
|
||||
* In addition to the generic object interface provided by JSObject,
|
||||
* specific types of objects may provide additional operations. To access,
|
||||
* these addition operations, callers should use the pattern:
|
||||
*
|
||||
* if (obj.isX()) {
|
||||
* XObject &x = obj.asX();
|
||||
* x.foo();
|
||||
* }
|
||||
*
|
||||
* These XObject classes form a hierarchy. For example, for a cloned block
|
||||
* object, the following predicates are true: isClonedBlock, isBlock,
|
||||
* isNestedScope and isScope. Each of these has a respective class that
|
||||
* derives and adds operations.
|
||||
*
|
||||
* A class XObject is defined in a vm/XObject{.h, .cpp, -inl.h} file
|
||||
* triplet (along with any class YObject that derives XObject).
|
||||
*
|
||||
* Note that X represents a low-level representation and does not query the
|
||||
* [[Class]] property of object defined by the spec (for this, see
|
||||
* js::ObjectClassIs).
|
||||
*
|
||||
* SpiderMonkey has not been completely switched to the isX/asX/XObject
|
||||
* pattern so in some cases there is no XObject class and the engine
|
||||
* instead pokes directly at reserved slots and getPrivate. In such cases,
|
||||
* consider adding the missing XObject class.
|
||||
*/
|
||||
|
||||
/* Direct subtypes of JSObject: */
|
||||
inline bool isArguments() const;
|
||||
inline bool isArrayBuffer() const;
|
||||
inline bool isArray() const;
|
||||
inline bool isDate() const;
|
||||
inline bool isDenseArray() const;
|
||||
inline bool isError() const;
|
||||
inline bool isFunction() const;
|
||||
inline bool isGenerator() const;
|
||||
inline bool isGlobal() const;
|
||||
inline bool isIterator() const;
|
||||
inline bool isNamespace() const;
|
||||
inline bool isObject() const;
|
||||
inline bool isQName() const;
|
||||
inline bool isPrimitive() const;
|
||||
inline bool isProxy() const;
|
||||
inline bool isRegExp() const;
|
||||
inline bool isScope() const;
|
||||
inline bool isScript() const;
|
||||
inline bool isSlowArray() const;
|
||||
inline bool isStopIteration() const;
|
||||
inline bool isWeakMap() const;
|
||||
inline bool isXML() const;
|
||||
inline bool isXMLId() const;
|
||||
|
||||
/* Subtypes of ScopeObject. */
|
||||
inline bool isBlock() const;
|
||||
inline bool isCall() const;
|
||||
inline bool isDeclEnv() const;
|
||||
inline bool isNestedScope() const;
|
||||
inline bool isWith() const;
|
||||
inline bool isClonedBlock() const;
|
||||
inline bool isStaticBlock() const;
|
||||
|
||||
/* Subtypes of PrimitiveObject. */
|
||||
inline bool isBoolean() const;
|
||||
inline bool isNumber() const;
|
||||
inline bool isString() const;
|
||||
|
||||
/* Subtypes of ArgumentsObject. */
|
||||
inline bool isNormalArguments() const;
|
||||
inline bool isStrictArguments() const;
|
||||
|
||||
/* Subtypes of Proxy. */
|
||||
inline bool isWrapper() const;
|
||||
inline bool isFunctionProxy() const;
|
||||
inline bool isCrossCompartmentWrapper() const;
|
||||
|
||||
inline js::ArgumentsObject &asArguments();
|
||||
inline js::BlockObject &asBlock();
|
||||
inline js::BooleanObject &asBoolean();
|
||||
inline js::CallObject &asCall();
|
||||
inline js::ClonedBlockObject &asClonedBlock();
|
||||
inline js::DeclEnvObject &asDeclEnv();
|
||||
inline js::GlobalObject &asGlobal();
|
||||
inline js::NestedScopeObject &asNestedScope();
|
||||
inline js::NormalArgumentsObject &asNormalArguments();
|
||||
inline js::NumberObject &asNumber();
|
||||
inline js::RegExpObject &asRegExp();
|
||||
inline js::ScopeObject &asScope();
|
||||
inline js::StrictArgumentsObject &asStrictArguments();
|
||||
inline js::StaticBlockObject &asStaticBlock();
|
||||
inline js::StringObject &asString();
|
||||
inline js::WithObject &asWith();
|
||||
|
||||
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_OBJECT; }
|
||||
|
||||
private:
|
||||
@ -1484,66 +1508,6 @@ class ValueArray {
|
||||
ValueArray(js::Value *v, size_t c) : array(v), length(c) {}
|
||||
};
|
||||
|
||||
/*
|
||||
* Block scope object macros. The slots reserved by BlockClass are:
|
||||
*
|
||||
* private StackFrame * active frame pointer or null
|
||||
* JSSLOT_SCOPE_CHAIN JSObject * scope chain, as for other scopes
|
||||
* JSSLOT_BLOCK_DEPTH int depth of block slots in frame
|
||||
*
|
||||
* After JSSLOT_BLOCK_DEPTH come one or more slots for the block locals.
|
||||
*
|
||||
* A With object is like a Block object, in that both have a reserved slot
|
||||
* telling the stack depth of the relevant slots (the slot whose value is the
|
||||
* object named in the with statement, the slots containing the block's local
|
||||
* variables); and both have a private slot referring to the StackFrame in
|
||||
* whose activation they were created (or null if the with or block object
|
||||
* outlives the frame).
|
||||
*/
|
||||
static const uint32_t JSSLOT_BLOCK_DEPTH = 1;
|
||||
static const uint32_t JSSLOT_BLOCK_FIRST_FREE_SLOT = JSSLOT_BLOCK_DEPTH + 1;
|
||||
|
||||
static const uint32_t JSSLOT_WITH_THIS = 2;
|
||||
|
||||
#define OBJ_BLOCK_COUNT(cx,obj) \
|
||||
(obj)->propertyCount()
|
||||
#define OBJ_BLOCK_DEPTH(cx,obj) \
|
||||
(obj)->getFixedSlot(JSSLOT_BLOCK_DEPTH).toInt32()
|
||||
#define OBJ_SET_BLOCK_DEPTH(cx,obj,depth) \
|
||||
(obj)->setFixedSlot(JSSLOT_BLOCK_DEPTH, Value(Int32Value(depth)))
|
||||
|
||||
/*
|
||||
* To make sure this slot is well-defined, always call js_NewWithObject to
|
||||
* create a With object, don't call js_NewObject directly. When creating a
|
||||
* With object that does not correspond to a stack slot, pass -1 for depth.
|
||||
*
|
||||
* When popping the stack across this object's "with" statement, client code
|
||||
* must call withobj->setPrivate(NULL).
|
||||
*/
|
||||
extern JS_REQUIRES_STACK JSObject *
|
||||
js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth);
|
||||
|
||||
inline JSObject *
|
||||
js_UnwrapWithObject(JSContext *cx, JSObject *withobj);
|
||||
|
||||
/*
|
||||
* Create a new block scope object not linked to any proto or parent object.
|
||||
* Blocks are created by the compiler to reify let blocks and comprehensions.
|
||||
* Only when dynamic scope is captured do they need to be cloned and spliced
|
||||
* into an active scope chain.
|
||||
*/
|
||||
extern JSObject *
|
||||
js_NewBlockObject(JSContext *cx);
|
||||
|
||||
extern JSObject *
|
||||
js_CloneBlockObject(JSContext *cx, JSObject *proto, js::StackFrame *fp);
|
||||
|
||||
extern JS_REQUIRES_STACK JSBool
|
||||
js_PutBlockObject(JSContext *cx, JSBool normalUnwind);
|
||||
|
||||
JSBool
|
||||
js_XDRBlockObject(JSXDRState *xdr, JSObject **objp);
|
||||
|
||||
/* For manipulating JSContext::sharpObjectMap. */
|
||||
#define SHARP_BIT ((jsatomid) 1)
|
||||
#define BUSY_BIT ((jsatomid) 2)
|
||||
|
@ -44,29 +44,24 @@
|
||||
#include <new>
|
||||
|
||||
#include "jsarray.h"
|
||||
#include "jsbool.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsdate.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsgcmark.h"
|
||||
#include "jsiter.h"
|
||||
#include "jslock.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsprobes.h"
|
||||
#include "jspropertytree.h"
|
||||
#include "jsproxy.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsstr.h"
|
||||
#include "jstypedarray.h"
|
||||
#include "jsxml.h"
|
||||
#include "jswrapper.h"
|
||||
|
||||
/* Headers included for inline implementations used by this header. */
|
||||
#include "jsbool.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsinferinlines.h"
|
||||
#include "jsscopeinlines.h"
|
||||
#include "jsscriptinlines.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "js/TemplateLib.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
@ -74,7 +69,9 @@
|
||||
#include "jsatominlines.h"
|
||||
#include "jsfuninlines.h"
|
||||
#include "jsgcinlines.h"
|
||||
#include "jsinferinlines.h"
|
||||
#include "jsscopeinlines.h"
|
||||
#include "jsscriptinlines.h"
|
||||
|
||||
#include "gc/Barrier-inl.h"
|
||||
#include "vm/String-inl.h"
|
||||
@ -288,53 +285,10 @@ JSObject::getParent() const
|
||||
return lastProperty()->getObjectParent();
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::isInternalScope() const
|
||||
{
|
||||
return isCall() || isDeclEnv() || isBlock() || isWith();
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
JSObject::internalScopeChain() const
|
||||
JSObject::enclosingScope()
|
||||
{
|
||||
JS_ASSERT(isInternalScope());
|
||||
return &getFixedSlot(SCOPE_CHAIN_SLOT).toObject();
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::setInternalScopeChain(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(isInternalScope());
|
||||
if (!obj->setDelegate(cx))
|
||||
return false;
|
||||
setFixedSlot(SCOPE_CHAIN_SLOT, JS::ObjectValue(*obj));
|
||||
return true;
|
||||
}
|
||||
|
||||
/*static*/ inline size_t
|
||||
JSObject::offsetOfInternalScopeChain()
|
||||
{
|
||||
return getFixedSlotOffset(SCOPE_CHAIN_SLOT);
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
JSObject::scopeChain() const
|
||||
{
|
||||
return isInternalScope() ? internalScopeChain() : getParent();
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
JSObject::staticBlockScopeChain() const
|
||||
{
|
||||
JS_ASSERT(isStaticBlock());
|
||||
return getFixedSlot(SCOPE_CHAIN_SLOT).toObjectOrNull();
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::setStaticBlockScopeChain(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(isStaticBlock());
|
||||
setFixedSlot(SCOPE_CHAIN_SLOT, JS::ObjectOrNullValue(obj));
|
||||
return isScope() ? &asScope().enclosingScope() : getParent();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -458,7 +412,7 @@ JSObject::getRawSlots()
|
||||
return slots;
|
||||
}
|
||||
|
||||
inline js::Value
|
||||
inline const js::Value &
|
||||
JSObject::getReservedSlot(uintN index) const
|
||||
{
|
||||
JS_ASSERT(index < JSSLOT_FREE(getClass()));
|
||||
@ -805,18 +759,6 @@ JSObject::setQNameLocalName(JSAtom *name)
|
||||
setSlot(JSSLOT_QNAME_LOCAL_NAME, name ? js::StringValue(name) : js::UndefinedValue());
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
JSObject::getWithThis() const
|
||||
{
|
||||
return &getFixedSlot(JSSLOT_WITH_THIS).toObject();
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::setWithThis(JSObject *thisp)
|
||||
{
|
||||
setFixedSlot(JSSLOT_WITH_THIS, js::ObjectValue(*thisp));
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::setSingletonType(JSContext *cx)
|
||||
{
|
||||
@ -947,31 +889,32 @@ inline bool JSObject::hasSpecialEquality() const
|
||||
|
||||
inline bool JSObject::isArguments() const { return isNormalArguments() || isStrictArguments(); }
|
||||
inline bool JSObject::isArrayBuffer() const { return hasClass(&js::ArrayBufferClass); }
|
||||
inline bool JSObject::isNormalArguments() const { return hasClass(&js::NormalArgumentsObjectClass); }
|
||||
inline bool JSObject::isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); }
|
||||
inline bool JSObject::isNumber() const { return hasClass(&js::NumberClass); }
|
||||
inline bool JSObject::isBoolean() const { return hasClass(&js::BooleanClass); }
|
||||
inline bool JSObject::isString() const { return hasClass(&js::StringClass); }
|
||||
inline bool JSObject::isPrimitive() const { return isNumber() || isString() || isBoolean(); }
|
||||
inline bool JSObject::isDate() const { return hasClass(&js::DateClass); }
|
||||
inline bool JSObject::isFunction() const { return hasClass(&js::FunctionClass); }
|
||||
inline bool JSObject::isObject() const { return hasClass(&js::ObjectClass); }
|
||||
inline bool JSObject::isWith() const { return hasClass(&js::WithClass); }
|
||||
inline bool JSObject::isBlock() const { return hasClass(&js::BlockClass); }
|
||||
inline bool JSObject::isStaticBlock() const { return isBlock() && !getProto(); }
|
||||
inline bool JSObject::isClonedBlock() const { return isBlock() && !!getProto(); }
|
||||
inline bool JSObject::isBoolean() const { return hasClass(&js::BooleanClass); }
|
||||
inline bool JSObject::isCall() const { return hasClass(&js::CallClass); }
|
||||
inline bool JSObject::isClonedBlock() const { return isBlock() && !!getProto(); }
|
||||
inline bool JSObject::isDate() const { return hasClass(&js::DateClass); }
|
||||
inline bool JSObject::isDeclEnv() const { return hasClass(&js::DeclEnvClass); }
|
||||
inline bool JSObject::isRegExp() const { return hasClass(&js::RegExpClass); }
|
||||
inline bool JSObject::isScript() const { return hasClass(&js::ScriptClass); }
|
||||
inline bool JSObject::isError() const { return hasClass(&js::ErrorClass); }
|
||||
inline bool JSObject::isFunction() const { return hasClass(&js::FunctionClass); }
|
||||
inline bool JSObject::isFunctionProxy() const { return hasClass(&js::FunctionProxyClass); }
|
||||
inline bool JSObject::isGenerator() const { return hasClass(&js::GeneratorClass); }
|
||||
inline bool JSObject::isIterator() const { return hasClass(&js::IteratorClass); }
|
||||
inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); }
|
||||
inline bool JSObject::isError() const { return hasClass(&js::ErrorClass); }
|
||||
inline bool JSObject::isXML() const { return hasClass(&js::XMLClass); }
|
||||
inline bool JSObject::isNamespace() const { return hasClass(&js::NamespaceClass); }
|
||||
inline bool JSObject::isNestedScope() const { return isBlock() || isWith(); }
|
||||
inline bool JSObject::isNormalArguments() const { return hasClass(&js::NormalArgumentsObjectClass); }
|
||||
inline bool JSObject::isNumber() const { return hasClass(&js::NumberClass); }
|
||||
inline bool JSObject::isObject() const { return hasClass(&js::ObjectClass); }
|
||||
inline bool JSObject::isPrimitive() const { return isNumber() || isString() || isBoolean(); }
|
||||
inline bool JSObject::isRegExp() const { return hasClass(&js::RegExpClass); }
|
||||
inline bool JSObject::isScope() const { return isCall() || isDeclEnv() || isNestedScope(); }
|
||||
inline bool JSObject::isStaticBlock() const { return isBlock() && !getProto(); }
|
||||
inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); }
|
||||
inline bool JSObject::isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); }
|
||||
inline bool JSObject::isString() const { return hasClass(&js::StringClass); }
|
||||
inline bool JSObject::isWeakMap() const { return hasClass(&js::WeakMapClass); }
|
||||
inline bool JSObject::isFunctionProxy() const { return hasClass(&js::FunctionProxyClass); }
|
||||
inline bool JSObject::isWith() const { return hasClass(&js::WithClass); }
|
||||
inline bool JSObject::isXML() const { return hasClass(&js::XMLClass); }
|
||||
|
||||
inline bool JSObject::isArray() const
|
||||
{
|
||||
@ -1432,8 +1375,8 @@ JSObject::isWrapper() const
|
||||
return js::IsWrapper(this);
|
||||
}
|
||||
|
||||
inline js::GlobalObject *
|
||||
JSObject::getGlobal() const
|
||||
inline js::GlobalObject &
|
||||
JSObject::global() const
|
||||
{
|
||||
JSObject *obj = const_cast<JSObject *>(this);
|
||||
while (JSObject *parent = obj->getParent())
|
||||
@ -1447,13 +1390,6 @@ js_IsCallable(const js::Value &v)
|
||||
return v.isObject() && v.toObject().isCallable();
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
js_UnwrapWithObject(JSContext *cx, JSObject *withobj)
|
||||
{
|
||||
JS_ASSERT(withobj->isWith());
|
||||
return withobj->getProto();
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
inline void
|
||||
@ -1773,7 +1709,7 @@ inline GlobalObject *
|
||||
GetCurrentGlobal(JSContext *cx)
|
||||
{
|
||||
JSObject *scopeChain = (cx->hasfp()) ? &cx->fp()->scopeChain() : cx->globalObject;
|
||||
return scopeChain ? scopeChain->getGlobal() : NULL;
|
||||
return scopeChain ? &scopeChain->global() : NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -228,7 +228,7 @@ NumBlockSlots(JSScript *script, jsbytecode *pc)
|
||||
|
||||
JSObject *obj = NULL;
|
||||
GET_OBJECT_FROM_BYTECODE(script, pc, 0, obj);
|
||||
return OBJ_BLOCK_COUNT(NULL, obj);
|
||||
return obj->asStaticBlock().slotCount();
|
||||
}
|
||||
|
||||
uintN
|
||||
@ -494,10 +494,8 @@ ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes)
|
||||
|
||||
if (!JSVAL_IS_PRIMITIVE(v)) {
|
||||
JSObject *obj = JSVAL_TO_OBJECT(v);
|
||||
Class *clasp = obj->getClass();
|
||||
|
||||
if (clasp == &BlockClass) {
|
||||
char *source = JS_sprintf_append(NULL, "depth %d {", OBJ_BLOCK_DEPTH(cx, obj));
|
||||
if (obj->isBlock()) {
|
||||
char *source = JS_sprintf_append(NULL, "depth %d {", obj->asBlock().stackDepth());
|
||||
if (!source)
|
||||
return false;
|
||||
|
||||
@ -527,15 +525,15 @@ ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (clasp == &FunctionClass) {
|
||||
if (obj->isFunction()) {
|
||||
JSString *str = JS_DecompileFunction(cx, obj->toFunction(), JS_DONT_PRETTY_PRINT);
|
||||
if (!str)
|
||||
return false;
|
||||
return bytes->encode(cx, str);
|
||||
}
|
||||
|
||||
if (clasp == &RegExpClass) {
|
||||
JSString *source = obj->asRegExp()->toString(cx);
|
||||
if (obj->isRegExp()) {
|
||||
JSString *source = obj->asRegExp().toString(cx);
|
||||
if (!source)
|
||||
return false;
|
||||
JS::Anchor<JSString *> anchor(source);
|
||||
@ -1758,9 +1756,8 @@ GetLocal(SprintStack *ss, jsint i)
|
||||
JSObject *obj = script->getObject(j);
|
||||
|
||||
if (obj->isBlock()) {
|
||||
jsint depth = OBJ_BLOCK_DEPTH(cx, obj);
|
||||
jsint count = OBJ_BLOCK_COUNT(cx, obj);
|
||||
|
||||
uint32_t depth = obj->asBlock().stackDepth();
|
||||
uint32_t count = obj->asBlock().slotCount();
|
||||
if (jsuint(i - depth) < jsuint(count))
|
||||
return GetLocalInSlot(ss, i, jsint(i - depth), obj);
|
||||
}
|
||||
@ -1772,9 +1769,8 @@ GetLocal(SprintStack *ss, jsint i)
|
||||
JSObject *obj = script->getObject(j);
|
||||
|
||||
if (obj->isBlock()) {
|
||||
jsint depth = OBJ_BLOCK_DEPTH(cx, obj);
|
||||
jsint count = OBJ_BLOCK_COUNT(cx, obj);
|
||||
|
||||
uint32_t depth = obj->asBlock().stackDepth();
|
||||
uint32_t count = obj->asBlock().slotCount();
|
||||
if (jsuint(i - depth) < jsuint(count))
|
||||
return GetLocalInSlot(ss, i, jsint(i - depth), obj);
|
||||
}
|
||||
@ -2252,15 +2248,15 @@ DecompileGroupAssignment(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
|
||||
* back in declaration order.
|
||||
*/
|
||||
static bool
|
||||
GetBlockNames(JSContext *cx, JSObject *blockObj, AtomVector *atoms)
|
||||
GetBlockNames(JSContext *cx, StaticBlockObject &blockObj, AtomVector *atoms)
|
||||
{
|
||||
size_t numAtoms = OBJ_BLOCK_COUNT(cx, blockObj);
|
||||
size_t numAtoms = blockObj.slotCount();
|
||||
LOCAL_ASSERT(numAtoms > 0);
|
||||
if (!atoms->resize(numAtoms))
|
||||
return false;
|
||||
|
||||
uintN i = numAtoms;
|
||||
for (Shape::Range r = blockObj->lastProperty()->all(); !r.empty(); r.popFront()) {
|
||||
for (Shape::Range r = blockObj.lastProperty()->all(); !r.empty(); r.popFront()) {
|
||||
const Shape &shape = r.front();
|
||||
LOCAL_ASSERT(shape.hasShortID());
|
||||
--i;
|
||||
@ -3188,7 +3184,9 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
{
|
||||
LOAD_OBJECT(0);
|
||||
AtomVector atoms(cx);
|
||||
if (!GetBlockNames(cx, obj, &atoms) || !PushBlockNames(cx, ss, atoms))
|
||||
StaticBlockObject &blockObj = obj->asStaticBlock();
|
||||
|
||||
if (!GetBlockNames(cx, blockObj, &atoms) || !PushBlockNames(cx, ss, atoms))
|
||||
return NULL;
|
||||
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
@ -3246,7 +3244,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
#endif
|
||||
LOCAL_ASSERT(*pc == JSOP_SETLOCALPOP);
|
||||
pc += JSOP_SETLOCALPOP_LENGTH;
|
||||
LOCAL_ASSERT(OBJ_BLOCK_COUNT(cx, obj) >= 1);
|
||||
LOCAL_ASSERT(blockObj.slotCount() >= 1);
|
||||
if (!QuoteString(&jp->sprinter, atoms[0], 0))
|
||||
return NULL;
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
@ -3328,18 +3326,19 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
case JSOP_ENTERLET0:
|
||||
{
|
||||
LOAD_OBJECT(0);
|
||||
StaticBlockObject &blockObj = obj->asStaticBlock();
|
||||
|
||||
AtomVector atoms(cx);
|
||||
if (!GetBlockNames(cx, obj, &atoms))
|
||||
if (!GetBlockNames(cx, blockObj, &atoms))
|
||||
return NULL;
|
||||
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
LOCAL_ASSERT(SN_TYPE(sn) == SRC_DECL);
|
||||
ptrdiff_t letData = js_GetSrcNoteOffset(sn, 0);
|
||||
bool groupAssign = LetDataToGroupAssign(letData);
|
||||
uintN letDepth = OBJ_BLOCK_DEPTH(cx, obj);
|
||||
LOCAL_ASSERT(letDepth == (uintN)ss->top - OBJ_BLOCK_COUNT(cx, obj));
|
||||
LOCAL_ASSERT(atoms.length() == OBJ_BLOCK_COUNT(cx, obj));
|
||||
uintN letDepth = blockObj.stackDepth();
|
||||
LOCAL_ASSERT(letDepth == (uintN)ss->top - blockObj.slotCount());
|
||||
LOCAL_ASSERT(atoms.length() == blockObj.slotCount());
|
||||
|
||||
/*
|
||||
* Build the list of decompiled rhs expressions. Do this before
|
||||
@ -3449,13 +3448,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
case JSOP_ENTERLET1:
|
||||
{
|
||||
LOAD_OBJECT(0);
|
||||
StaticBlockObject &blockObj = obj->asStaticBlock();
|
||||
|
||||
AtomVector atoms(cx);
|
||||
if (!GetBlockNames(cx, obj, &atoms))
|
||||
if (!GetBlockNames(cx, blockObj, &atoms))
|
||||
return NULL;
|
||||
|
||||
LOCAL_ASSERT(js_GetSrcNote(jp->script, pc) == NULL);
|
||||
LOCAL_ASSERT(ss->top - 1 == OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj));
|
||||
LOCAL_ASSERT(ss->top - 1 == blockObj.stackDepth() + blockObj.slotCount());
|
||||
jsbytecode *nextpc = pc + JSOP_ENTERLET1_LENGTH;
|
||||
if (*nextpc == JSOP_GOTO || *nextpc == JSOP_GOTOX) {
|
||||
LOCAL_ASSERT(SN_TYPE(js_GetSrcNote(jp->script, nextpc)) == SRC_FOR_IN);
|
||||
@ -4126,13 +4126,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
LOCAL_ASSERT(*(pc + offsetToLet) == JSOP_ENTERLET0);
|
||||
|
||||
GET_OBJECT_FROM_BYTECODE(jp->script, pc + offsetToLet, 0, obj);
|
||||
StaticBlockObject &blockObj = obj->asStaticBlock();
|
||||
|
||||
uint32_t blockDepth = OBJ_BLOCK_DEPTH(cx, obj);
|
||||
uint32_t blockDepth = blockObj.stackDepth();
|
||||
LOCAL_ASSERT(blockDepth < ss->top);
|
||||
LOCAL_ASSERT(ss->top <= blockDepth + OBJ_BLOCK_COUNT(cx, obj));
|
||||
LOCAL_ASSERT(ss->top <= blockDepth + blockObj.slotCount());
|
||||
|
||||
AtomVector atoms(cx);
|
||||
if (!GetBlockNames(cx, obj, &atoms))
|
||||
if (!GetBlockNames(cx, blockObj, &atoms))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
@ -4823,7 +4824,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
||||
|
||||
case JSOP_REGEXP:
|
||||
GET_REGEXP_FROM_BYTECODE(jp->script, pc, 0, obj);
|
||||
str = obj->asRegExp()->toString(cx);
|
||||
str = obj->asRegExp().toString(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
goto sprint_string;
|
||||
|
@ -77,7 +77,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, JSObject *po
|
||||
|
||||
JSObject *tmp = obj;
|
||||
for (uintN i = 0; i < scopeIndex; i++)
|
||||
tmp = tmp->internalScopeChain();
|
||||
tmp = &tmp->asScope().enclosingScope();
|
||||
|
||||
uintN protoIndex = 0;
|
||||
while (tmp != pobj) {
|
||||
@ -231,7 +231,7 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
|
||||
if (JOF_MODE(cs.format) == JOF_NAME) {
|
||||
uint8_t scopeIndex = entry->scopeIndex;
|
||||
while (scopeIndex > 0) {
|
||||
tmp = pobj->scopeChain();
|
||||
tmp = pobj->enclosingScope();
|
||||
if (!tmp || !tmp->isNative())
|
||||
break;
|
||||
pobj = tmp;
|
||||
|
@ -1539,7 +1539,7 @@ proxy_createFunction(JSContext *cx, uintN argc, Value *vp)
|
||||
return false;
|
||||
JSObject *proto, *parent;
|
||||
parent = vp[0].toObject().getParent();
|
||||
proto = parent->getGlobal()->getOrCreateFunctionPrototype(cx);
|
||||
proto = parent->global().getOrCreateFunctionPrototype(cx);
|
||||
if (!proto)
|
||||
return false;
|
||||
parent = proto->getParent();
|
||||
@ -1653,7 +1653,7 @@ callable_Construct(JSContext *cx, uintN argc, Value *vp)
|
||||
if (protov.isObject()) {
|
||||
proto = &protov.toObject();
|
||||
} else {
|
||||
proto = callable->getGlobal()->getOrCreateObjectPrototype(cx);
|
||||
proto = callable->global().getOrCreateObjectPrototype(cx);
|
||||
if (!proto)
|
||||
return false;
|
||||
}
|
||||
|
@ -316,6 +316,7 @@ class Handle
|
||||
T a = RootMethods<T>::initial();
|
||||
S b = RootMethods<S>::initial();
|
||||
a = b;
|
||||
(void)a;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
@ -1460,7 +1460,7 @@ NewObjectCache::invalidateEntriesForShape(JSContext *cx, Shape *shape, JSObject
|
||||
if (CanBeFinalizedInBackground(kind, clasp))
|
||||
kind = GetBackgroundAllocKind(kind);
|
||||
|
||||
GlobalObject *global = shape->getObjectParent()->getGlobal();
|
||||
GlobalObject *global = &shape->getObjectParent()->global();
|
||||
types::TypeObject *type = proto->getNewType(cx);
|
||||
|
||||
EntryIndex entry;
|
||||
|
@ -535,6 +535,7 @@ struct Shape : public js::gc::Cell
|
||||
{
|
||||
friend struct ::JSObject;
|
||||
friend struct ::JSFunction;
|
||||
friend class js::StaticBlockObject;
|
||||
friend class js::PropertyTree;
|
||||
friend class js::Bindings;
|
||||
friend struct js::StackShape;
|
||||
|
@ -41,6 +41,7 @@
|
||||
#define jsscopeinlines_h___
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "jsarray.h"
|
||||
#include "jsbool.h"
|
||||
#include "jscntxt.h"
|
||||
@ -52,12 +53,15 @@
|
||||
#include "jsgcmark.h"
|
||||
|
||||
#include "vm/ArgumentsObject.h"
|
||||
#include "vm/ScopeObject.h"
|
||||
#include "vm/StringObject.h"
|
||||
|
||||
#include "jscntxtinlines.h"
|
||||
#include "jsgcinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "vm/ScopeObject-inl.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
inline
|
||||
@ -265,7 +269,7 @@ Shape::get(JSContext* cx, JSObject *receiver, JSObject* obj, JSObject *pobj, js:
|
||||
* Avoid exposing the With object to native getters.
|
||||
*/
|
||||
if (obj->isWith())
|
||||
obj = js_UnwrapWithObject(cx, obj);
|
||||
obj = &obj->asWith().object();
|
||||
return js::CallJSPropertyOp(cx, getterOp(), receiver, getUserId(), vp);
|
||||
}
|
||||
|
||||
@ -284,7 +288,7 @@ Shape::set(JSContext* cx, JSObject* obj, bool strict, js::Value* vp) const
|
||||
|
||||
/* See the comment in js::Shape::get as to why we check for With. */
|
||||
if (obj->isWith())
|
||||
obj = js_UnwrapWithObject(cx, obj);
|
||||
obj = &obj->asWith().object();
|
||||
return js::CallJSPropertyOpSetter(cx, setterOp(), obj, getUserId(), strict, vp);
|
||||
}
|
||||
|
||||
|
@ -653,23 +653,24 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
||||
HeapPtr<JSObject> *objp = &script->objects()->vector[i];
|
||||
uint32_t isBlock;
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
Class *clasp = (*objp)->getClass();
|
||||
JS_ASSERT(clasp == &FunctionClass ||
|
||||
clasp == &BlockClass);
|
||||
isBlock = (clasp == &BlockClass) ? 1 : 0;
|
||||
JSObject *obj = *objp;
|
||||
JS_ASSERT(obj->isFunction() || obj->isStaticBlock());
|
||||
isBlock = obj->isBlock() ? 1 : 0;
|
||||
}
|
||||
if (!JS_XDRUint32(xdr, &isBlock))
|
||||
goto error;
|
||||
JSObject *tmp = *objp;
|
||||
if (isBlock == 0) {
|
||||
JSObject *tmp = *objp;
|
||||
if (!js_XDRFunctionObject(xdr, &tmp))
|
||||
goto error;
|
||||
*objp = tmp;
|
||||
} else {
|
||||
JS_ASSERT(isBlock == 1);
|
||||
if (!js_XDRBlockObject(xdr, &tmp))
|
||||
StaticBlockObject *tmp = static_cast<StaticBlockObject *>(objp->get());
|
||||
if (!js_XDRStaticBlockObject(xdr, &tmp))
|
||||
goto error;
|
||||
*objp = tmp;
|
||||
}
|
||||
*objp = tmp;
|
||||
}
|
||||
for (i = 0; i != nupvars; ++i) {
|
||||
if (!JS_XDRUint32(xdr, reinterpret_cast<uint32_t *>(&script->upvars()->vector[i])))
|
||||
@ -1261,7 +1262,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
|
||||
return NULL;
|
||||
|
||||
fun->setScript(script);
|
||||
script->globalObject = fun->getParent() ? fun->getParent()->getGlobal() : NULL;
|
||||
script->globalObject = fun->getParent() ? &fun->getParent()->global() : NULL;
|
||||
} else {
|
||||
/*
|
||||
* Initialize script->object, if necessary, so that the debugger has a
|
||||
@ -1278,7 +1279,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
|
||||
if (script->compileAndGo) {
|
||||
compileAndGoGlobal = script->globalObject;
|
||||
if (!compileAndGoGlobal)
|
||||
compileAndGoGlobal = bce->scopeChain()->getGlobal();
|
||||
compileAndGoGlobal = &bce->scopeChain()->global();
|
||||
}
|
||||
Debugger::onNewScript(cx, script, compileAndGoGlobal);
|
||||
}
|
||||
|
@ -48,7 +48,7 @@
|
||||
#include "jsscript.h"
|
||||
#include "jsscope.h"
|
||||
|
||||
#include "vm/CallObject.h"
|
||||
#include "vm/ScopeObject.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
|
||||
|
@ -1403,7 +1403,7 @@ class RegExpGuard
|
||||
init(uintN argc, Value *vp, bool convertVoid = false)
|
||||
{
|
||||
if (argc != 0 && ValueIsRegExp(vp[2])) {
|
||||
if (!rep.reset(vp[2].toObject().asRegExp()))
|
||||
if (!rep.reset(&vp[2].toObject().asRegExp()))
|
||||
return false;
|
||||
} else {
|
||||
if (convertVoid && (argc == 0 || vp[2].isUndefined())) {
|
||||
@ -2538,8 +2538,7 @@ js::str_split(JSContext *cx, uintN argc, Value *vp)
|
||||
bool sepUndefined = (argc == 0 || vp[2].isUndefined());
|
||||
if (!sepUndefined) {
|
||||
if (ValueIsRegExp(vp[2])) {
|
||||
RegExpObject *reobj = vp[2].toObject().asRegExp();
|
||||
if (!matcher.reset(reobj))
|
||||
if (!matcher.reset(&vp[2].toObject().asRegExp()))
|
||||
return false;
|
||||
} else {
|
||||
JSString *sep = ToString(cx, vp[2]);
|
||||
@ -3033,10 +3032,10 @@ js_InitStringClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
GlobalObject *global = &obj->asGlobal();
|
||||
|
||||
JSObject *proto = global->createBlankPrototype(cx, &StringClass);
|
||||
if (!proto || !proto->asString()->init(cx, cx->runtime->emptyString))
|
||||
if (!proto || !proto->asString().init(cx, cx->runtime->emptyString))
|
||||
return NULL;
|
||||
|
||||
/* Now create the String function. */
|
||||
|
@ -2374,7 +2374,7 @@ js_InitTypedArrayClasses(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
GlobalObject *global = &obj->asGlobal();
|
||||
|
||||
/* Idempotency required: we initialize several things, possibly lazily. */
|
||||
JSObject *stop;
|
||||
|
@ -330,7 +330,7 @@ js_InitWeakMapClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
GlobalObject *global = &obj->asGlobal();
|
||||
|
||||
JSObject *weakMapProto = global->createBlankPrototype(cx, &WeakMapClass);
|
||||
if (!weakMapProto)
|
||||
|
@ -424,10 +424,10 @@ ForceFrame::enter()
|
||||
JS_ASSERT(context->compartment == target->compartment());
|
||||
JSCompartment *destination = context->compartment;
|
||||
|
||||
JSObject *scopeChain = target->getGlobal();
|
||||
JS_ASSERT(scopeChain->isNative());
|
||||
JSObject &scopeChain = target->global();
|
||||
JS_ASSERT(scopeChain.isNative());
|
||||
|
||||
return context->stack.pushDummyFrame(context, destination, *scopeChain, frame);
|
||||
return context->stack.pushDummyFrame(context, destination, scopeChain, frame);
|
||||
}
|
||||
|
||||
AutoCompartment::AutoCompartment(JSContext *cx, JSObject *target)
|
||||
@ -450,11 +450,11 @@ AutoCompartment::enter()
|
||||
{
|
||||
JS_ASSERT(!entered);
|
||||
if (origin != destination) {
|
||||
JSObject *scopeChain = target->getGlobal();
|
||||
JS_ASSERT(scopeChain->isNative());
|
||||
JSObject &scopeChain = target->global();
|
||||
JS_ASSERT(scopeChain.isNative());
|
||||
|
||||
frame.construct();
|
||||
if (!context->stack.pushDummyFrame(context, destination, *scopeChain, &frame.ref()))
|
||||
if (!context->stack.pushDummyFrame(context, destination, scopeChain, &frame.ref()))
|
||||
return false;
|
||||
|
||||
if (context->isExceptionPending())
|
||||
|
@ -4656,7 +4656,7 @@ HasFunctionProperty(JSContext *cx, JSObject *obj, jsid funid, JSBool *found)
|
||||
* Search in String.prototype to set found whenever
|
||||
* GetXMLFunction returns existing function.
|
||||
*/
|
||||
JSObject *proto = obj->getGlobal()->getOrCreateStringPrototype(cx);
|
||||
JSObject *proto = obj->global().getOrCreateStringPrototype(cx);
|
||||
if (!proto)
|
||||
return false;
|
||||
|
||||
@ -7404,7 +7404,7 @@ js_InitNamespaceClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
GlobalObject *global = &obj->asGlobal();
|
||||
|
||||
JSObject *namespaceProto = global->createBlankPrototype(cx, &NamespaceClass);
|
||||
if (!namespaceProto)
|
||||
@ -7437,7 +7437,7 @@ js_InitQNameClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
GlobalObject *global = &obj->asGlobal();
|
||||
|
||||
JSObject *qnameProto = global->createBlankPrototype(cx, &QNameClass);
|
||||
if (!qnameProto)
|
||||
@ -7469,7 +7469,7 @@ js_InitXMLClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
GlobalObject *global = &obj->asGlobal();
|
||||
|
||||
JSObject *xmlProto = global->createBlankPrototype(cx, &XMLClass);
|
||||
if (!xmlProto)
|
||||
@ -7595,9 +7595,8 @@ js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp)
|
||||
return false;
|
||||
|
||||
obj = NULL;
|
||||
for (tmp = scopeChain; tmp; tmp = tmp->scopeChain()) {
|
||||
Class *clasp = tmp->getClass();
|
||||
if (clasp == &BlockClass || clasp == &WithClass)
|
||||
for (tmp = scopeChain; tmp; tmp = tmp->enclosingScope()) {
|
||||
if (tmp->isBlock() || tmp->isWith())
|
||||
continue;
|
||||
if (!tmp->getSpecial(cx, SpecialId::defaultXMLNamespace(), &v))
|
||||
return JS_FALSE;
|
||||
@ -7708,7 +7707,7 @@ js_ValueToXMLString(JSContext *cx, const Value &v)
|
||||
JSBool
|
||||
js_GetAnyName(JSContext *cx, jsid *idp)
|
||||
{
|
||||
JSObject *global = cx->hasfp() ? cx->fp()->scopeChain().getGlobal() : cx->globalObject;
|
||||
JSObject *global = cx->hasfp() ? &cx->fp()->scopeChain().global() : cx->globalObject;
|
||||
Value v = global->getReservedSlot(JSProto_AnyName);
|
||||
if (v.isUndefined()) {
|
||||
JSObject *obj = NewObjectWithGivenProto(cx, &AnyNameClass, NULL, global);
|
||||
@ -7793,7 +7792,7 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, JSObject **objp, jsid *i
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
} while ((obj = obj->scopeChain()) != NULL);
|
||||
} while ((obj = obj->enclosingScope()) != NULL);
|
||||
|
||||
JSAutoByteString printable;
|
||||
JSString *str = ConvertQNameToString(cx, nameobj);
|
||||
@ -7829,7 +7828,7 @@ GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
return true;
|
||||
|
||||
/* Search in String.prototype to implement 11.2.2.1 Step 3(f). */
|
||||
JSObject *proto = obj->getGlobal()->getOrCreateStringPrototype(cx);
|
||||
JSObject *proto = obj->global().getOrCreateStringPrototype(cx);
|
||||
if (!proto)
|
||||
return false;
|
||||
|
||||
|
@ -6377,7 +6377,7 @@ mjit::Compiler::jsop_callgname_epilogue()
|
||||
/* Paths for known object callee. */
|
||||
if (fval->isConstant()) {
|
||||
JSObject *obj = &fval->getValue().toObject();
|
||||
if (obj->getGlobal() == globalObj) {
|
||||
if (&obj->global() == globalObj) {
|
||||
frame.push(UndefinedValue());
|
||||
} else {
|
||||
prepareStubCall(Uses(1));
|
||||
@ -6834,7 +6834,7 @@ mjit::Compiler::jsop_regexp()
|
||||
RegExpStatics *res = globalObj ? globalObj->getRegExpStatics() : NULL;
|
||||
|
||||
if (!globalObj ||
|
||||
obj->getGlobal() != globalObj ||
|
||||
&obj->global() != globalObj ||
|
||||
!cx->typeInferenceEnabled() ||
|
||||
analysis->localsAliasStack() ||
|
||||
types::TypeSet::HasObjectFlags(cx, globalObj->getType(cx),
|
||||
@ -6846,7 +6846,7 @@ mjit::Compiler::jsop_regexp()
|
||||
return true;
|
||||
}
|
||||
|
||||
RegExpObject *reobj = obj->asRegExp();
|
||||
RegExpObject *reobj = &obj->asRegExp();
|
||||
|
||||
DebugOnly<uint32_t> origFlags = reobj->getFlags();
|
||||
DebugOnly<uint32_t> staticsFlags = res->getFlags();
|
||||
|
@ -639,7 +639,7 @@ mjit::Compiler::compileArrayConcat(types::TypeSet *thisTypes, types::TypeSet *ar
|
||||
if (thisTypes->getObjectCount() != 1)
|
||||
return Compile_InlineAbort;
|
||||
types::TypeObject *thisType = thisTypes->getTypeObject(0);
|
||||
if (!thisType || thisType->proto->getGlobal() != globalObj)
|
||||
if (!thisType || &thisType->proto->global() != globalObj)
|
||||
return Compile_InlineAbort;
|
||||
|
||||
/*
|
||||
@ -839,7 +839,7 @@ mjit::Compiler::inlineNativeFunction(uint32_t argc, bool callingNew)
|
||||
* The callee must have the same parent as the script's global, otherwise
|
||||
* inference may not have accounted for any side effects correctly.
|
||||
*/
|
||||
if (!globalObj || globalObj != callee->getGlobal())
|
||||
if (!globalObj || globalObj != &callee->global())
|
||||
return Compile_InlineAbort;
|
||||
|
||||
Native native = callee->toFunction()->maybeNative();
|
||||
|
@ -630,8 +630,8 @@ js_InternalThrow(VMFrame &f)
|
||||
*/
|
||||
if (cx->isExceptionPending()) {
|
||||
JS_ASSERT(JSOp(*pc) == JSOP_ENTERBLOCK);
|
||||
JSObject *obj = script->getObject(GET_SLOTNO(pc));
|
||||
Value *vp = cx->regs().sp + OBJ_BLOCK_COUNT(cx, obj);
|
||||
StaticBlockObject &blockObj = script->getObject(GET_SLOTNO(pc))->asStaticBlock();
|
||||
Value *vp = cx->regs().sp + blockObj.slotCount();
|
||||
SetValueRangeToUndefined(cx->regs().sp, vp);
|
||||
cx->regs().sp = vp;
|
||||
JS_ASSERT(JSOp(pc[JSOP_ENTERBLOCK_LENGTH]) == JSOP_EXCEPTION);
|
||||
@ -639,7 +639,7 @@ js_InternalThrow(VMFrame &f)
|
||||
cx->clearPendingException();
|
||||
cx->regs().sp++;
|
||||
cx->regs().pc = pc + JSOP_ENTERBLOCK_LENGTH + JSOP_EXCEPTION_LENGTH;
|
||||
cx->regs().fp()->setBlockChain(obj);
|
||||
cx->regs().fp()->setBlockChain(&blockObj);
|
||||
}
|
||||
|
||||
*f.oldregs = f.regs;
|
||||
|
@ -86,13 +86,13 @@ PatchGetFallback(VMFrame &f, ic::GetGlobalNameIC *ic)
|
||||
void JS_FASTCALL
|
||||
ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic)
|
||||
{
|
||||
JSObject *obj = f.fp()->scopeChain().getGlobal();
|
||||
JSObject &obj = f.fp()->scopeChain().global();
|
||||
JSAtom *atom = f.script()->getAtom(GET_INDEX(f.pc()));
|
||||
jsid id = ATOM_TO_JSID(atom);
|
||||
|
||||
RecompilationMonitor monitor(f.cx);
|
||||
|
||||
const Shape *shape = obj->nativeLookup(f.cx, id);
|
||||
const Shape *shape = obj.nativeLookup(f.cx, id);
|
||||
|
||||
if (monitor.recompiled()) {
|
||||
stubs::GetGlobalName(f);
|
||||
@ -112,10 +112,10 @@ ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic)
|
||||
|
||||
/* Patch shape guard. */
|
||||
Repatcher repatcher(f.jit());
|
||||
repatcher.repatch(ic->fastPathStart.dataLabelPtrAtOffset(ic->shapeOffset), obj->lastProperty());
|
||||
repatcher.repatch(ic->fastPathStart.dataLabelPtrAtOffset(ic->shapeOffset), obj.lastProperty());
|
||||
|
||||
/* Patch loads. */
|
||||
uint32_t index = obj->dynamicSlotIndex(slot);
|
||||
uint32_t index = obj.dynamicSlotIndex(slot);
|
||||
JSC::CodeLocationLabel label = ic->fastPathStart.labelAtOffset(ic->loadStoreOffset);
|
||||
repatcher.patchAddressOffsetForValueLoad(label, index * sizeof(Value));
|
||||
|
||||
@ -208,16 +208,16 @@ UpdateSetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic, JSObject *obj, const Sh
|
||||
void JS_FASTCALL
|
||||
ic::SetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic)
|
||||
{
|
||||
JSObject *obj = f.fp()->scopeChain().getGlobal();
|
||||
JSObject &obj = f.fp()->scopeChain().global();
|
||||
JSScript *script = f.script();
|
||||
JSAtom *atom = script->getAtom(GET_INDEX(f.pc()));
|
||||
|
||||
RecompilationMonitor monitor(f.cx);
|
||||
|
||||
const Shape *shape = obj->nativeLookup(f.cx, ATOM_TO_JSID(atom));
|
||||
const Shape *shape = obj.nativeLookup(f.cx, ATOM_TO_JSID(atom));
|
||||
|
||||
if (!monitor.recompiled()) {
|
||||
LookupStatus status = UpdateSetGlobalName(f, ic, obj, shape);
|
||||
LookupStatus status = UpdateSetGlobalName(f, ic, &obj, shape);
|
||||
if (status == Lookup_Error)
|
||||
THROW();
|
||||
}
|
||||
|
@ -54,7 +54,7 @@
|
||||
#include "jsinterpinlines.h"
|
||||
#include "jsautooplen.h"
|
||||
|
||||
#include "vm/CallObject-inl.h"
|
||||
#include "vm/ScopeObject-inl.h"
|
||||
|
||||
#if defined JS_POLYIC
|
||||
|
||||
@ -1443,10 +1443,10 @@ class ScopeNameCompiler : public PICStubCompiler
|
||||
return error();
|
||||
|
||||
/* Load the next link in the scope chain. */
|
||||
Address parent(pic.objReg, JSObject::offsetOfInternalScopeChain());
|
||||
Address parent(pic.objReg, ScopeObject::offsetOfEnclosingScope());
|
||||
masm.loadPayload(parent, pic.objReg);
|
||||
|
||||
tobj = tobj->internalScopeChain();
|
||||
tobj = &tobj->asScope().enclosingScope();
|
||||
}
|
||||
|
||||
if (tobj != getprop.holder)
|
||||
@ -1501,7 +1501,7 @@ class ScopeNameCompiler : public PICStubCompiler
|
||||
masm.loadPtr(Address(JSFrameReg, StackFrame::offsetOfScopeChain()), pic.objReg);
|
||||
|
||||
JS_ASSERT(obj == getprop.holder);
|
||||
JS_ASSERT(getprop.holder == scopeChain->getGlobal());
|
||||
JS_ASSERT(getprop.holder == &scopeChain->global());
|
||||
|
||||
LookupStatus status = walkScopeChain(masm, fails);
|
||||
if (status != Lookup_Cacheable)
|
||||
@ -1585,7 +1585,7 @@ class ScopeNameCompiler : public PICStubCompiler
|
||||
masm.loadPtr(Address(JSFrameReg, StackFrame::offsetOfScopeChain()), pic.objReg);
|
||||
|
||||
JS_ASSERT(obj == getprop.holder);
|
||||
JS_ASSERT(getprop.holder != scopeChain->getGlobal());
|
||||
JS_ASSERT(getprop.holder != &scopeChain->global());
|
||||
|
||||
CallObjPropKind kind;
|
||||
const Shape *shape = getprop.shape;
|
||||
@ -1763,7 +1763,7 @@ class ScopeNameCompiler : public PICStubCompiler
|
||||
const Shape *shape = getprop.shape;
|
||||
JSObject *normalized = obj;
|
||||
if (obj->isWith() && !shape->hasDefaultGetter())
|
||||
normalized = js_UnwrapWithObject(cx, obj);
|
||||
normalized = &obj->asWith().object();
|
||||
NATIVE_GET(cx, normalized, holder, shape, JSGET_METHOD_BARRIER, vp, return false);
|
||||
if (thisvp)
|
||||
return ComputeImplicitThis(cx, normalized, *vp, thisvp);
|
||||
@ -1825,7 +1825,7 @@ class BindNameCompiler : public PICStubCompiler
|
||||
|
||||
/* Walk up the scope chain. */
|
||||
JSObject *tobj = scopeChain;
|
||||
Address parent(pic.objReg, JSObject::offsetOfInternalScopeChain());
|
||||
Address parent(pic.objReg, ScopeObject::offsetOfEnclosingScope());
|
||||
while (tobj && tobj != obj) {
|
||||
if (!IsCacheableNonGlobalScope(tobj))
|
||||
return disable("non-cacheable obj in scope chain");
|
||||
@ -1835,7 +1835,7 @@ class BindNameCompiler : public PICStubCompiler
|
||||
ImmPtr(tobj->lastProperty()));
|
||||
if (!fails.append(shapeTest))
|
||||
return error();
|
||||
tobj = tobj->internalScopeChain();
|
||||
tobj = &tobj->asScope().enclosingScope();
|
||||
}
|
||||
if (tobj != obj)
|
||||
return disable("indirect hit");
|
||||
@ -1932,7 +1932,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic)
|
||||
} else if (!f.regs.sp[-1].isPrimitive()) {
|
||||
JSObject *obj = &f.regs.sp[-1].toObject();
|
||||
if (obj->isArray() ||
|
||||
(obj->isArguments() && !obj->asArguments()->hasOverriddenLength()) ||
|
||||
(obj->isArguments() && !obj->asArguments().hasOverriddenLength()) ||
|
||||
obj->isString()) {
|
||||
GetPropCompiler cc(f, script, obj, *pic, NULL, DisabledGetPropIC);
|
||||
if (obj->isArray()) {
|
||||
@ -1944,7 +1944,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic)
|
||||
LookupStatus status = cc.generateArgsLengthStub();
|
||||
if (status == Lookup_Error)
|
||||
THROW();
|
||||
f.regs.sp[-1].setInt32(int32_t(obj->asArguments()->initialLength()));
|
||||
f.regs.sp[-1].setInt32(int32_t(obj->asArguments().initialLength()));
|
||||
} else if (obj->isString()) {
|
||||
LookupStatus status = cc.generateStringObjLengthStub();
|
||||
if (status == Lookup_Error)
|
||||
@ -2069,14 +2069,14 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic)
|
||||
if (lval.isObject()) {
|
||||
objv = lval;
|
||||
} else {
|
||||
GlobalObject *global = f.fp()->scopeChain().getGlobal();
|
||||
GlobalObject &global = f.fp()->scopeChain().global();
|
||||
JSObject *pobj;
|
||||
if (lval.isString()) {
|
||||
pobj = global->getOrCreateStringPrototype(cx);
|
||||
pobj = global.getOrCreateStringPrototype(cx);
|
||||
} else if (lval.isNumber()) {
|
||||
pobj = global->getOrCreateNumberPrototype(cx);
|
||||
pobj = global.getOrCreateNumberPrototype(cx);
|
||||
} else if (lval.isBoolean()) {
|
||||
pobj = global->getOrCreateBooleanPrototype(cx);
|
||||
pobj = global.getOrCreateBooleanPrototype(cx);
|
||||
} else {
|
||||
JS_ASSERT(lval.isNull() || lval.isUndefined());
|
||||
js_ReportIsNullOrUndefined(cx, -1, lval, NULL);
|
||||
|
@ -118,7 +118,7 @@ stubs::BindNameNoCache(VMFrame &f, JSAtom *atom)
|
||||
JSObject * JS_FASTCALL
|
||||
stubs::BindGlobalName(VMFrame &f)
|
||||
{
|
||||
return f.fp()->scopeChain().getGlobal();
|
||||
return &f.fp()->scopeChain().global();
|
||||
}
|
||||
|
||||
template<JSBool strict>
|
||||
@ -317,7 +317,7 @@ NameOp(VMFrame &f, JSObject *obj, bool callname)
|
||||
Shape *shape = (Shape *)prop;
|
||||
JSObject *normalized = obj;
|
||||
if (normalized->isWith() && !shape->hasDefaultGetter())
|
||||
normalized = js_UnwrapWithObject(cx, normalized);
|
||||
normalized = &normalized->asWith().object();
|
||||
NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval, return NULL);
|
||||
}
|
||||
|
||||
@ -347,7 +347,7 @@ stubs::Name(VMFrame &f)
|
||||
void JS_FASTCALL
|
||||
stubs::GetGlobalName(VMFrame &f)
|
||||
{
|
||||
JSObject *globalObj = f.fp()->scopeChain().getGlobal();
|
||||
JSObject *globalObj = &f.fp()->scopeChain().global();
|
||||
if (!NameOp(f, globalObj, false))
|
||||
THROW();
|
||||
}
|
||||
@ -395,7 +395,7 @@ stubs::GetElem(VMFrame &f)
|
||||
return;
|
||||
}
|
||||
} else if (obj->isArguments()) {
|
||||
if (obj->asArguments()->getElement(index, &rval))
|
||||
if (obj->asArguments().getElement(index, &rval))
|
||||
return;
|
||||
}
|
||||
|
||||
@ -556,7 +556,7 @@ stubs::CallName(VMFrame &f)
|
||||
void JS_FASTCALL
|
||||
stubs::PushImplicitThisForGlobal(VMFrame &f)
|
||||
{
|
||||
return PushImplicitThis(f, f.fp()->scopeChain().getGlobal(), f.regs.sp[-1]);
|
||||
return PushImplicitThis(f, &f.fp()->scopeChain().global(), f.regs.sp[-1]);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
@ -691,7 +691,7 @@ stubs::DefFun(VMFrame &f, JSFunction *fun)
|
||||
obj = CloneFunctionObjectIfNotSingleton(cx, fun, obj2);
|
||||
if (!obj)
|
||||
THROW();
|
||||
JS_ASSERT_IF(f.script()->compileAndGo, obj->getGlobal() == fun->getGlobal());
|
||||
JS_ASSERT_IF(f.script()->compileAndGo, obj->global() == fun->global());
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1341,7 +1341,7 @@ stubs::DefLocalFun(VMFrame &f, JSFunction *fun)
|
||||
if (!obj)
|
||||
THROWV(NULL);
|
||||
|
||||
JS_ASSERT_IF(f.script()->compileAndGo, obj->getGlobal() == fun->getGlobal());
|
||||
JS_ASSERT_IF(f.script()->compileAndGo, obj->global() == fun->global());
|
||||
|
||||
return obj;
|
||||
}
|
||||
@ -1362,7 +1362,7 @@ stubs::RegExp(VMFrame &f, JSObject *regex)
|
||||
* Push a regexp object cloned from the regexp literal object mapped by the
|
||||
* bytecode at pc.
|
||||
*/
|
||||
JSObject *proto = f.fp()->scopeChain().getGlobal()->getOrCreateRegExpPrototype(f.cx);
|
||||
JSObject *proto = f.fp()->scopeChain().global().getOrCreateRegExpPrototype(f.cx);
|
||||
if (!proto)
|
||||
THROW();
|
||||
JS_ASSERT(proto);
|
||||
@ -1451,7 +1451,7 @@ stubs::Lambda(VMFrame &f, JSFunction *fun)
|
||||
if (!obj)
|
||||
THROWV(NULL);
|
||||
|
||||
JS_ASSERT_IF(f.script()->compileAndGo, obj->getGlobal() == fun->getGlobal());
|
||||
JS_ASSERT_IF(f.script()->compileAndGo, obj->global() == fun->global());
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -1536,14 +1536,14 @@ stubs::CallProp(VMFrame &f, JSAtom *origAtom)
|
||||
if (lval.isObject()) {
|
||||
objv = lval;
|
||||
} else {
|
||||
GlobalObject *global = f.fp()->scopeChain().getGlobal();
|
||||
GlobalObject &global = f.fp()->scopeChain().global();
|
||||
JSObject *pobj;
|
||||
if (lval.isString()) {
|
||||
pobj = global->getOrCreateStringPrototype(cx);
|
||||
pobj = global.getOrCreateStringPrototype(cx);
|
||||
} else if (lval.isNumber()) {
|
||||
pobj = global->getOrCreateNumberPrototype(cx);
|
||||
pobj = global.getOrCreateNumberPrototype(cx);
|
||||
} else if (lval.isBoolean()) {
|
||||
pobj = global->getOrCreateBooleanPrototype(cx);
|
||||
pobj = global.getOrCreateBooleanPrototype(cx);
|
||||
} else {
|
||||
JS_ASSERT(lval.isNull() || lval.isUndefined());
|
||||
js_ReportIsNullOrUndefined(cx, -1, lval, NULL);
|
||||
@ -1819,13 +1819,13 @@ stubs::EnterBlock(VMFrame &f, JSObject *obj)
|
||||
{
|
||||
FrameRegs ®s = f.regs;
|
||||
StackFrame *fp = f.fp();
|
||||
StaticBlockObject &blockObj = obj->asStaticBlock();
|
||||
|
||||
JS_ASSERT(!f.regs.inlined());
|
||||
JS_ASSERT(obj->isStaticBlock());
|
||||
|
||||
if (*regs.pc == JSOP_ENTERBLOCK) {
|
||||
JS_ASSERT(fp->base() + OBJ_BLOCK_DEPTH(cx, obj) == regs.sp);
|
||||
Value *vp = regs.sp + OBJ_BLOCK_COUNT(cx, obj);
|
||||
JS_ASSERT(fp->base() + blockObj.stackDepth() == regs.sp);
|
||||
Value *vp = regs.sp + blockObj.slotCount();
|
||||
JS_ASSERT(regs.sp < vp);
|
||||
JS_ASSERT(vp <= fp->slots() + fp->script()->nslots);
|
||||
SetValueRangeToUndefined(regs.sp, vp);
|
||||
@ -1834,7 +1834,7 @@ stubs::EnterBlock(VMFrame &f, JSObject *obj)
|
||||
|
||||
#ifdef DEBUG
|
||||
JSContext *cx = f.cx;
|
||||
JS_ASSERT(fp->maybeBlockChain() == obj->staticBlockScopeChain());
|
||||
JS_ASSERT(fp->maybeBlockChain() == blockObj.enclosingBlock());
|
||||
|
||||
/*
|
||||
* The young end of fp->scopeChain() may omit blocks if we haven't closed
|
||||
@ -1845,18 +1845,17 @@ stubs::EnterBlock(VMFrame &f, JSObject *obj)
|
||||
*/
|
||||
JSObject *obj2 = &fp->scopeChain();
|
||||
while (obj2->isWith())
|
||||
obj2 = obj2->internalScopeChain();
|
||||
obj2 = &obj2->asWith().enclosingScope();
|
||||
if (obj2->isBlock() &&
|
||||
obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, fp)) {
|
||||
JSObject *youngestProto = obj2->getProto();
|
||||
JS_ASSERT(youngestProto->isStaticBlock());
|
||||
JSObject *parent = obj;
|
||||
while ((parent = parent->scopeChain()) != youngestProto)
|
||||
JSObject &youngestProto = obj2->asClonedBlock().staticBlock();
|
||||
StaticBlockObject *parent = &blockObj;
|
||||
while ((parent = parent->enclosingBlock()) != &youngestProto)
|
||||
JS_ASSERT(parent);
|
||||
}
|
||||
#endif
|
||||
|
||||
fp->setBlockChain(obj);
|
||||
fp->setBlockChain(&blockObj);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
@ -1865,26 +1864,19 @@ stubs::LeaveBlock(VMFrame &f)
|
||||
JSContext *cx = f.cx;
|
||||
StackFrame *fp = f.fp();
|
||||
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(fp->blockChain().isBlock());
|
||||
uintN blockDepth = OBJ_BLOCK_DEPTH(cx, &fp->blockChain());
|
||||
StaticBlockObject &blockObj = fp->blockChain();
|
||||
JS_ASSERT(blockObj.stackDepth() <= StackDepth(fp->script()));
|
||||
|
||||
JS_ASSERT(blockDepth <= StackDepth(fp->script()));
|
||||
#endif
|
||||
/*
|
||||
* If we're about to leave the dynamic scope of a block that has been
|
||||
* cloned onto fp->scopeChain(), clear its private data, move its locals from
|
||||
* the stack into the clone, and pop it off the chain.
|
||||
*/
|
||||
JSObject &obj = fp->scopeChain();
|
||||
JSObject &blockChain = fp->blockChain();
|
||||
if (obj.getProto() == &blockChain) {
|
||||
JS_ASSERT(obj.isBlock());
|
||||
if (!js_PutBlockObject(cx, JS_TRUE))
|
||||
THROW();
|
||||
}
|
||||
if (obj.getProto() == &blockObj && !obj.asClonedBlock().put(cx, JS_TRUE))
|
||||
THROW();
|
||||
|
||||
fp->setBlockChain(blockChain.staticBlockScopeChain());
|
||||
fp->setBlockChain(blockObj.enclosingBlock());
|
||||
}
|
||||
|
||||
void * JS_FASTCALL
|
||||
|
@ -3740,7 +3740,7 @@ Wrap(JSContext *cx, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
JSObject *obj = JSVAL_TO_OBJECT(v);
|
||||
JSObject *wrapped = Wrapper::New(cx, obj, obj->getProto(), obj->getGlobal(),
|
||||
JSObject *wrapped = Wrapper::New(cx, obj, obj->getProto(), &obj->global(),
|
||||
&Wrapper::singleton);
|
||||
if (!wrapped)
|
||||
return false;
|
||||
|
@ -141,7 +141,7 @@ struct ArgumentsData
|
||||
* remove this oddity, but preserving it allows us to work with arguments
|
||||
* objects of either kind more abstractly, so we keep it for now.
|
||||
*/
|
||||
class ArgumentsObject : public ::JSObject
|
||||
class ArgumentsObject : public JSObject
|
||||
{
|
||||
static const uint32_t INITIAL_LENGTH_SLOT = 0;
|
||||
static const uint32_t DATA_SLOT = 1;
|
||||
@ -243,25 +243,25 @@ class StrictArgumentsObject : public ArgumentsObject
|
||||
|
||||
} // namespace js
|
||||
|
||||
js::NormalArgumentsObject *
|
||||
js::NormalArgumentsObject &
|
||||
JSObject::asNormalArguments()
|
||||
{
|
||||
JS_ASSERT(isNormalArguments());
|
||||
return reinterpret_cast<js::NormalArgumentsObject *>(this);
|
||||
return *reinterpret_cast<js::NormalArgumentsObject *>(this);
|
||||
}
|
||||
|
||||
js::StrictArgumentsObject *
|
||||
js::StrictArgumentsObject &
|
||||
JSObject::asStrictArguments()
|
||||
{
|
||||
JS_ASSERT(isStrictArguments());
|
||||
return reinterpret_cast<js::StrictArgumentsObject *>(this);
|
||||
return *reinterpret_cast<js::StrictArgumentsObject *>(this);
|
||||
}
|
||||
|
||||
js::ArgumentsObject *
|
||||
js::ArgumentsObject &
|
||||
JSObject::asArguments()
|
||||
{
|
||||
JS_ASSERT(isArguments());
|
||||
return reinterpret_cast<js::ArgumentsObject *>(this);
|
||||
return *reinterpret_cast<js::ArgumentsObject *>(this);
|
||||
}
|
||||
|
||||
#endif /* ArgumentsObject_h___ */
|
||||
|
@ -45,11 +45,11 @@
|
||||
|
||||
#include "vm/BooleanObject.h"
|
||||
|
||||
inline js::BooleanObject *
|
||||
inline js::BooleanObject &
|
||||
JSObject::asBoolean()
|
||||
{
|
||||
JS_ASSERT(isBoolean());
|
||||
return static_cast<js::BooleanObject *>(const_cast<JSObject *>(this));
|
||||
return *static_cast<js::BooleanObject *>(this);
|
||||
}
|
||||
|
||||
namespace js {
|
||||
@ -60,9 +60,9 @@ BooleanObject::create(JSContext *cx, bool b)
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, &BooleanClass);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
BooleanObject *boolobj = obj->asBoolean();
|
||||
boolobj->setPrimitiveValue(b);
|
||||
return boolobj;
|
||||
BooleanObject &boolobj = obj->asBoolean();
|
||||
boolobj.setPrimitiveValue(b);
|
||||
return &boolobj;
|
||||
}
|
||||
|
||||
inline BooleanObject *
|
||||
@ -72,9 +72,9 @@ BooleanObject::createWithProto(JSContext *cx, bool b, JSObject &proto)
|
||||
gc::GetGCObjectKind(RESERVED_SLOTS));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
BooleanObject *boolobj = obj->asBoolean();
|
||||
boolobj->setPrimitiveValue(b);
|
||||
return boolobj;
|
||||
BooleanObject &boolobj = obj->asBoolean();
|
||||
boolobj.setPrimitiveValue(b);
|
||||
return &boolobj;
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
@ -47,7 +47,7 @@
|
||||
|
||||
namespace js {
|
||||
|
||||
class BooleanObject : public ::JSObject
|
||||
class BooleanObject : public JSObject
|
||||
{
|
||||
/* Stores this Boolean object's [[PrimitiveValue]]. */
|
||||
static const uintN PRIMITIVE_VALUE_SLOT = 0;
|
||||
|
@ -1,191 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey call object code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Paul Biggar <pbiggar@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef CallObject_inl_h___
|
||||
#define CallObject_inl_h___
|
||||
|
||||
#include "CallObject.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
inline bool
|
||||
CallObject::isForEval() const
|
||||
{
|
||||
JS_ASSERT(getFixedSlot(CALLEE_SLOT).isObjectOrNull());
|
||||
JS_ASSERT_IF(getFixedSlot(CALLEE_SLOT).isObject(),
|
||||
getFixedSlot(CALLEE_SLOT).toObject().isFunction());
|
||||
return getFixedSlot(CALLEE_SLOT).isNull();
|
||||
}
|
||||
|
||||
inline js::StackFrame *
|
||||
CallObject::maybeStackFrame() const
|
||||
{
|
||||
return reinterpret_cast<js::StackFrame *>(getPrivate());
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::setStackFrame(StackFrame *frame)
|
||||
{
|
||||
return setPrivate(frame);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::setCallee(JSObject *callee)
|
||||
{
|
||||
JS_ASSERT_IF(callee, callee->isFunction());
|
||||
setFixedSlot(CALLEE_SLOT, js::ObjectOrNullValue(callee));
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::initCallee(JSObject *callee)
|
||||
{
|
||||
JS_ASSERT_IF(callee, callee->isFunction());
|
||||
initFixedSlot(CALLEE_SLOT, js::ObjectOrNullValue(callee));
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
CallObject::getCallee() const
|
||||
{
|
||||
return getFixedSlot(CALLEE_SLOT).toObjectOrNull();
|
||||
}
|
||||
|
||||
inline JSFunction *
|
||||
CallObject::getCalleeFunction() const
|
||||
{
|
||||
return getFixedSlot(CALLEE_SLOT).toObject().toFunction();
|
||||
}
|
||||
|
||||
inline const js::Value &
|
||||
CallObject::getArguments() const
|
||||
{
|
||||
JS_ASSERT(!isForEval());
|
||||
return getFixedSlot(ARGUMENTS_SLOT);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::setArguments(const js::Value &v)
|
||||
{
|
||||
JS_ASSERT(!isForEval());
|
||||
setFixedSlot(ARGUMENTS_SLOT, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::initArguments(const js::Value &v)
|
||||
{
|
||||
JS_ASSERT(!isForEval());
|
||||
initFixedSlot(ARGUMENTS_SLOT, v);
|
||||
}
|
||||
|
||||
inline const js::Value &
|
||||
CallObject::arg(uintN i) const
|
||||
{
|
||||
JS_ASSERT(i < getCalleeFunction()->nargs);
|
||||
return getSlot(RESERVED_SLOTS + i);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::setArg(uintN i, const js::Value &v)
|
||||
{
|
||||
JS_ASSERT(i < getCalleeFunction()->nargs);
|
||||
setSlot(RESERVED_SLOTS + i, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::initArgUnchecked(uintN i, const js::Value &v)
|
||||
{
|
||||
JS_ASSERT(i < getCalleeFunction()->nargs);
|
||||
initSlotUnchecked(RESERVED_SLOTS + i, v);
|
||||
}
|
||||
|
||||
inline const js::Value &
|
||||
CallObject::var(uintN i) const
|
||||
{
|
||||
JSFunction *fun = getCalleeFunction();
|
||||
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
|
||||
JS_ASSERT(i < fun->script()->bindings.countVars());
|
||||
return getSlot(RESERVED_SLOTS + fun->nargs + i);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::setVar(uintN i, const js::Value &v)
|
||||
{
|
||||
JSFunction *fun = getCalleeFunction();
|
||||
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
|
||||
JS_ASSERT(i < fun->script()->bindings.countVars());
|
||||
setSlot(RESERVED_SLOTS + fun->nargs + i, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::initVarUnchecked(uintN i, const js::Value &v)
|
||||
{
|
||||
JSFunction *fun = getCalleeFunction();
|
||||
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
|
||||
JS_ASSERT(i < fun->script()->bindings.countVars());
|
||||
initSlotUnchecked(RESERVED_SLOTS + fun->nargs + i, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots)
|
||||
{
|
||||
JS_ASSERT(slotInRange(RESERVED_SLOTS + nargs + nvars, SENTINEL_ALLOWED));
|
||||
copySlotRange(RESERVED_SLOTS, argv, nargs);
|
||||
copySlotRange(RESERVED_SLOTS + nargs, slots, nvars);
|
||||
}
|
||||
|
||||
inline js::HeapValueArray
|
||||
CallObject::argArray()
|
||||
{
|
||||
js::DebugOnly<JSFunction*> fun = getCalleeFunction();
|
||||
JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS, fun->nargs));
|
||||
return HeapValueArray(getSlotAddress(RESERVED_SLOTS));
|
||||
}
|
||||
|
||||
inline js::HeapValueArray
|
||||
CallObject::varArray()
|
||||
{
|
||||
JSFunction *fun = getCalleeFunction();
|
||||
JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS + fun->nargs,
|
||||
fun->script()->bindings.countVars()));
|
||||
return HeapValueArray(getSlotAddress(RESERVED_SLOTS + fun->nargs));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* CallObject_inl_h___ */
|
@ -1,117 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey call object code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Paul Biggar <pbiggar@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
#include "CallObject.h"
|
||||
|
||||
#include "CallObject-inl.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* Construct a call object for the given bindings. If this is a call object
|
||||
* for a function invocation, callee should be the function being called.
|
||||
* Otherwise it must be a call object for eval of strict mode code, and callee
|
||||
* must be null.
|
||||
*/
|
||||
CallObject *
|
||||
CallObject::create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObject *callee)
|
||||
{
|
||||
Bindings &bindings = script->bindings;
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(bindings.lastShape()->numFixedSlots() + 1);
|
||||
|
||||
RootedVarTypeObject type(cx);
|
||||
|
||||
type = cx->compartment->getEmptyType(cx);
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
HeapValue *slots;
|
||||
if (!PreallocateObjectDynamicSlots(cx, bindings.lastShape(), &slots))
|
||||
return NULL;
|
||||
|
||||
RootedVarShape shape(cx);
|
||||
shape = bindings.lastShape();
|
||||
|
||||
JSObject *obj = JSObject::create(cx, kind, shape, type, slots);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Update the parent for bindings associated with non-compileAndGo scripts,
|
||||
* whose call objects do not have a consistent global variable and need
|
||||
* to be updated dynamically.
|
||||
*/
|
||||
JSObject *global = scopeChain.getGlobal();
|
||||
if (global != obj->getParent()) {
|
||||
JS_ASSERT(obj->getParent() == NULL);
|
||||
if (!obj->setParent(cx, global))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
for (Shape::Range r = obj->lastProperty(); !r.empty(); r.popFront()) {
|
||||
const Shape &s = r.front();
|
||||
if (s.hasSlot()) {
|
||||
JS_ASSERT(s.slot() + 1 == obj->slotSpan());
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
JS_ASSERT(obj->isCall());
|
||||
JS_ASSERT(!obj->inDictionaryMode());
|
||||
|
||||
if (!obj->setInternalScopeChain(cx, &scopeChain))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* If |bindings| is for a function that has extensible parents, that means
|
||||
* its Call should have its own shape; see js::BaseShape::extensibleParents.
|
||||
*/
|
||||
if (obj->lastProperty()->extensibleParents() && !obj->generateOwnShape(cx))
|
||||
return NULL;
|
||||
|
||||
CallObject &callobj = obj->asCall();
|
||||
callobj.initCallee(callee);
|
||||
return &callobj;
|
||||
}
|
||||
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey call object code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Paul Biggar <pbiggar@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef CallObject_h___
|
||||
#define CallObject_h___
|
||||
|
||||
namespace js {
|
||||
|
||||
class CallObject : public ::JSObject
|
||||
{
|
||||
/*
|
||||
* Reserved slot structure for Call objects:
|
||||
*
|
||||
* SCOPE_CHAIN_SLOT - The enclosing scope. This must come first, for
|
||||
* JSObject::scopeParent.
|
||||
* CALLEE_SLOT - Callee function for the stack frame, or null if
|
||||
* the stack frame is for strict mode eval code.
|
||||
* ARGUMENTS_SLOT - Arguments object for non-strict mode eval stack
|
||||
* frames (not valid for strict mode eval frames).
|
||||
* private - The stack frame corresponding to the Call object
|
||||
* until js_PutCallObject or its on-trace analog
|
||||
* is called, null thereafter.
|
||||
*
|
||||
* DeclEnv objects use SCOPE_CHAIN_SLOT and private in the same fashion.
|
||||
*/
|
||||
static const uint32_t CALLEE_SLOT = 1;
|
||||
static const uint32_t ARGUMENTS_SLOT = 2;
|
||||
|
||||
public:
|
||||
/* Create a CallObject for the given callee function. */
|
||||
static CallObject *
|
||||
create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObject *callee);
|
||||
|
||||
static const uint32_t RESERVED_SLOTS = 3;
|
||||
|
||||
static const uint32_t DECL_ENV_RESERVED_SLOTS = 1;
|
||||
static const gc::AllocKind DECL_ENV_FINALIZE_KIND = gc::FINALIZE_OBJECT2;
|
||||
|
||||
/* True if this is for a strict mode eval frame or for a function call. */
|
||||
inline bool isForEval() const;
|
||||
|
||||
/* The stack frame for this CallObject, if the frame is still active. */
|
||||
inline js::StackFrame *maybeStackFrame() const;
|
||||
inline void setStackFrame(js::StackFrame *frame);
|
||||
|
||||
/*
|
||||
* The callee function if this CallObject was created for a function
|
||||
* invocation, or null if it was created for a strict mode eval frame.
|
||||
*/
|
||||
inline JSObject *getCallee() const;
|
||||
inline JSFunction *getCalleeFunction() const;
|
||||
inline void setCallee(JSObject *callee);
|
||||
inline void initCallee(JSObject *callee);
|
||||
|
||||
/* Returns the callee's arguments object. */
|
||||
inline const js::Value &getArguments() const;
|
||||
inline void setArguments(const js::Value &v);
|
||||
inline void initArguments(const js::Value &v);
|
||||
|
||||
/* Returns the formal argument at the given index. */
|
||||
inline const js::Value &arg(uintN i) const;
|
||||
inline void setArg(uintN i, const js::Value &v);
|
||||
inline void initArgUnchecked(uintN i, const js::Value &v);
|
||||
|
||||
/* Returns the variable at the given index. */
|
||||
inline const js::Value &var(uintN i) const;
|
||||
inline void setVar(uintN i, const js::Value &v);
|
||||
inline void initVarUnchecked(uintN i, const js::Value &v);
|
||||
|
||||
/*
|
||||
* Get the actual arrays of arguments and variables. Only call if type
|
||||
* inference is enabled, where we ensure that call object variables are in
|
||||
* contiguous slots (see NewCallObject).
|
||||
*/
|
||||
inline js::HeapValueArray argArray();
|
||||
inline js::HeapValueArray varArray();
|
||||
|
||||
inline void copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
js::CallObject &
|
||||
JSObject::asCall()
|
||||
{
|
||||
JS_ASSERT(isCall());
|
||||
return *reinterpret_cast<js::CallObject *>(this);
|
||||
}
|
||||
|
||||
#endif /* CallObject_h___ */
|
@ -171,7 +171,7 @@ ScriptGlobal(JSContext *cx, JSScript *script, GlobalObject *scriptGlobal)
|
||||
for (AllFramesIter i(cx->stack.space()); ; ++i) {
|
||||
JS_ASSERT(!i.done());
|
||||
if (i.fp()->maybeScript() == script)
|
||||
return i.fp()->scopeChain().getGlobal();
|
||||
return &i.fp()->scopeChain().global();
|
||||
}
|
||||
JS_NOT_REACHED("ScriptGlobal: live non-held script not on stack");
|
||||
}
|
||||
@ -431,7 +431,7 @@ Debugger::slowPathOnEnterFrame(JSContext *cx, Value *vp)
|
||||
{
|
||||
/* Build the list of recipients. */
|
||||
AutoValueVector triggered(cx);
|
||||
GlobalObject *global = cx->fp()->scopeChain().getGlobal();
|
||||
GlobalObject *global = &cx->fp()->scopeChain().global();
|
||||
if (GlobalObject::DebuggerVector *debuggers = global->getDebuggers()) {
|
||||
for (Debugger **p = debuggers->begin(); p != debuggers->end(); p++) {
|
||||
Debugger *dbg = *p;
|
||||
@ -458,7 +458,7 @@ void
|
||||
Debugger::slowPathOnLeaveFrame(JSContext *cx)
|
||||
{
|
||||
StackFrame *fp = cx->fp();
|
||||
GlobalObject *global = fp->scopeChain().getGlobal();
|
||||
GlobalObject *global = &fp->scopeChain().global();
|
||||
|
||||
/*
|
||||
* FIXME This notifies only current debuggers, so it relies on a hack in
|
||||
@ -811,7 +811,7 @@ Debugger::dispatchHook(JSContext *cx, Value *vp, Hook which)
|
||||
* different compartments--every compartment *except* this one.
|
||||
*/
|
||||
AutoValueVector triggered(cx);
|
||||
GlobalObject *global = cx->fp()->scopeChain().getGlobal();
|
||||
GlobalObject *global = &cx->fp()->scopeChain().global();
|
||||
if (GlobalObject::DebuggerVector *debuggers = global->getDebuggers()) {
|
||||
for (Debugger **p = debuggers->begin(); p != debuggers->end(); p++) {
|
||||
Debugger *dbg = *p;
|
||||
@ -899,7 +899,7 @@ Debugger::onTrap(JSContext *cx, Value *vp)
|
||||
{
|
||||
StackFrame *fp = cx->fp();
|
||||
JSScript *script = fp->script();
|
||||
GlobalObject *scriptGlobal = fp->scopeChain().getGlobal();
|
||||
GlobalObject *scriptGlobal = &fp->scopeChain().global();
|
||||
jsbytecode *pc = cx->regs().pc;
|
||||
BreakpointSite *site = script->getBreakpointSite(pc);
|
||||
JSOp op = JSOp(*pc);
|
||||
@ -975,7 +975,7 @@ Debugger::onSingleStep(JSContext *cx, Value *vp)
|
||||
* onStep handlers.
|
||||
*/
|
||||
AutoObjectVector frames(cx);
|
||||
GlobalObject *global = fp->scopeChain().getGlobal();
|
||||
GlobalObject *global = &fp->scopeChain().global();
|
||||
if (GlobalObject::DebuggerVector *debuggers = global->getDebuggers()) {
|
||||
for (Debugger **d = debuggers->begin(); d != debuggers->end(); d++) {
|
||||
Debugger *dbg = *d;
|
||||
@ -1536,7 +1536,7 @@ Debugger::addDebuggee(JSContext *cx, uintN argc, Value *vp)
|
||||
JSObject *referent = dbg->unwrapDebuggeeArgument(cx, args[0]);
|
||||
if (!referent)
|
||||
return false;
|
||||
GlobalObject *global = referent->getGlobal();
|
||||
GlobalObject *global = &referent->global();
|
||||
if (!dbg->addDebuggeeGlobal(cx, global))
|
||||
return false;
|
||||
|
||||
@ -1555,7 +1555,7 @@ Debugger::removeDebuggee(JSContext *cx, uintN argc, Value *vp)
|
||||
JSObject *referent = dbg->unwrapDebuggeeArgument(cx, args[0]);
|
||||
if (!referent)
|
||||
return false;
|
||||
GlobalObject *global = referent->getGlobal();
|
||||
GlobalObject *global = &referent->global();
|
||||
if (dbg->debuggees.has(global))
|
||||
dbg->removeDebuggeeGlobal(cx, global, NULL, NULL);
|
||||
args.rval().setUndefined();
|
||||
@ -1570,7 +1570,7 @@ Debugger::hasDebuggee(JSContext *cx, uintN argc, Value *vp)
|
||||
JSObject *referent = dbg->unwrapDebuggeeArgument(cx, args[0]);
|
||||
if (!referent)
|
||||
return false;
|
||||
args.rval().setBoolean(!!dbg->debuggees.lookup(referent->getGlobal()));
|
||||
args.rval().setBoolean(!!dbg->debuggees.lookup(&referent->global()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1665,7 +1665,7 @@ Debugger::construct(JSContext *cx, uintN argc, Value *vp)
|
||||
|
||||
/* Add the initial debuggees, if any. */
|
||||
for (uintN i = 0; i < argc; i++) {
|
||||
GlobalObject *debuggee = GetProxyPrivate(&args[i].toObject()).toObject().getGlobal();
|
||||
GlobalObject *debuggee = &GetProxyPrivate(&args[i].toObject()).toObject().global();
|
||||
if (!dbg->addDebuggeeGlobal(cx, debuggee))
|
||||
return false;
|
||||
}
|
||||
@ -1773,7 +1773,7 @@ Debugger::removeDebuggeeGlobal(JSContext *cx, GlobalObject *global,
|
||||
*/
|
||||
for (FrameMap::Enum e(frames); !e.empty(); e.popFront()) {
|
||||
StackFrame *fp = e.front().key;
|
||||
if (fp->scopeChain().getGlobal() == global) {
|
||||
if (&fp->scopeChain().global() == global) {
|
||||
e.front().value->setPrivate(NULL);
|
||||
e.removeFront();
|
||||
}
|
||||
@ -2637,7 +2637,7 @@ DebuggerFrame_getArguments(JSContext *cx, uintN argc, Value *vp)
|
||||
if (fp->hasArgs()) {
|
||||
/* Create an arguments object. */
|
||||
RootedVar<GlobalObject*> global(cx);
|
||||
global = args.callee().getGlobal();
|
||||
global = &args.callee().global();
|
||||
JSObject *proto;
|
||||
if (!js_GetClassPrototype(cx, global, JSProto_Array, &proto))
|
||||
return false;
|
||||
@ -3683,7 +3683,7 @@ DebuggerEnv_getParent(JSContext *cx, uintN argc, Value *vp)
|
||||
THIS_DEBUGENV_OWNER(cx, argc, vp, "get parent", args, envobj, env, dbg);
|
||||
|
||||
/* Don't bother switching compartments just to get env's parent. */
|
||||
Env *parent = env->scopeChain();
|
||||
Env *parent = env->enclosingScope();
|
||||
return dbg->wrapEnvironment(cx, parent, &args.rval());
|
||||
}
|
||||
|
||||
@ -3760,7 +3760,7 @@ DebuggerEnv_find(JSContext *cx, uintN argc, Value *vp)
|
||||
ErrorCopier ec(ac, dbg->toJSObject());
|
||||
JSProperty *prop = NULL;
|
||||
JSObject *pobj;
|
||||
for (; env && !prop; env = env->scopeChain()) {
|
||||
for (; env && !prop; env = env->enclosingScope()) {
|
||||
if (!env->lookupGeneric(cx, id, &pobj, &prop))
|
||||
return false;
|
||||
if (prop)
|
||||
|
@ -483,7 +483,7 @@ Debugger::observesGlobal(GlobalObject *global) const
|
||||
bool
|
||||
Debugger::observesFrame(StackFrame *fp) const
|
||||
{
|
||||
return observesGlobal(fp->scopeChain().getGlobal());
|
||||
return observesGlobal(&fp->scopeChain().global());
|
||||
}
|
||||
|
||||
JSTrapStatus
|
||||
|
@ -60,7 +60,7 @@ js_InitObjectClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
return obj->asGlobal()->getOrCreateObjectPrototype(cx);
|
||||
return obj->asGlobal().getOrCreateObjectPrototype(cx);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
@ -68,7 +68,7 @@ js_InitFunctionClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
return obj->asGlobal()->getOrCreateFunctionPrototype(cx);
|
||||
return obj->asGlobal().getOrCreateFunctionPrototype(cx);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -272,7 +272,7 @@ GlobalObject::create(JSContext *cx, Class *clasp)
|
||||
JSObject *obj_ = NewObjectWithGivenProto(cx, clasp, NULL, NULL);
|
||||
if (!obj_)
|
||||
return NULL;
|
||||
obj = obj_->asGlobal();
|
||||
obj = &obj_->asGlobal();
|
||||
|
||||
if (!obj->setSingletonType(cx) || !obj->setVarObj(cx))
|
||||
return NULL;
|
||||
|
@ -91,7 +91,7 @@ class Debugger;
|
||||
* even deletable) Object, Array, &c. properties (although a slot won't be used
|
||||
* again if its property is deleted and readded).
|
||||
*/
|
||||
class GlobalObject : public ::JSObject {
|
||||
class GlobalObject : public JSObject {
|
||||
GlobalObject(const GlobalObject &other) MOZ_DELETE;
|
||||
void operator=(const GlobalObject &other) MOZ_DELETE;
|
||||
|
||||
@ -372,11 +372,11 @@ JSObject::isGlobal() const
|
||||
return !!(js::GetObjectClass(this)->flags & JSCLASS_IS_GLOBAL);
|
||||
}
|
||||
|
||||
js::GlobalObject *
|
||||
js::GlobalObject &
|
||||
JSObject::asGlobal()
|
||||
{
|
||||
JS_ASSERT(isGlobal());
|
||||
return static_cast<js::GlobalObject *>(this);
|
||||
return *static_cast<js::GlobalObject *>(this);
|
||||
}
|
||||
|
||||
#endif /* GlobalObject_h___ */
|
||||
|
@ -43,11 +43,11 @@
|
||||
|
||||
#include "NumberObject.h"
|
||||
|
||||
inline js::NumberObject *
|
||||
inline js::NumberObject &
|
||||
JSObject::asNumber()
|
||||
{
|
||||
JS_ASSERT(isNumber());
|
||||
return static_cast<js::NumberObject *>(const_cast<JSObject *>(this));
|
||||
return *static_cast<js::NumberObject *>(this);
|
||||
}
|
||||
|
||||
namespace js {
|
||||
@ -58,9 +58,9 @@ NumberObject::create(JSContext *cx, jsdouble d)
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, &NumberClass);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
NumberObject *numobj = obj->asNumber();
|
||||
numobj->setPrimitiveValue(d);
|
||||
return numobj;
|
||||
NumberObject &numobj = obj->asNumber();
|
||||
numobj.setPrimitiveValue(d);
|
||||
return &numobj;
|
||||
}
|
||||
|
||||
inline NumberObject *
|
||||
@ -70,9 +70,9 @@ NumberObject::createWithProto(JSContext *cx, jsdouble d, JSObject &proto)
|
||||
gc::GetGCObjectKind(RESERVED_SLOTS));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
NumberObject *numobj = obj->asNumber();
|
||||
numobj->setPrimitiveValue(d);
|
||||
return numobj;
|
||||
NumberObject &numobj = obj->asNumber();
|
||||
numobj.setPrimitiveValue(d);
|
||||
return &numobj;
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
@ -47,7 +47,7 @@
|
||||
|
||||
namespace js {
|
||||
|
||||
class NumberObject : public ::JSObject
|
||||
class NumberObject : public JSObject
|
||||
{
|
||||
/* Stores this Number object's [[PrimitiveValue]]. */
|
||||
static const uintN PRIMITIVE_VALUE_SLOT = 0;
|
||||
|
@ -50,11 +50,11 @@
|
||||
#include "jsstrinlines.h"
|
||||
#include "RegExpStatics-inl.h"
|
||||
|
||||
inline js::RegExpObject *
|
||||
inline js::RegExpObject &
|
||||
JSObject::asRegExp()
|
||||
{
|
||||
JS_ASSERT(isRegExp());
|
||||
return static_cast<js::RegExpObject *>(this);
|
||||
return *static_cast<js::RegExpObject *>(this);
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
@ -98,7 +98,7 @@ RegExpObjectBuilder::getOrCreate()
|
||||
return false;
|
||||
obj->setPrivate(NULL);
|
||||
|
||||
reobj_ = obj->asRegExp();
|
||||
reobj_ = &obj->asRegExp();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -112,7 +112,7 @@ RegExpObjectBuilder::getOrCreateClone(RegExpObject *proto)
|
||||
return false;
|
||||
clone->setPrivate(NULL);
|
||||
|
||||
reobj_ = clone->asRegExp();
|
||||
reobj_ = &clone->asRegExp();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -327,9 +327,9 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
|
||||
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
JS_ASSERT(objp);
|
||||
RegExpObject *reobj = (*objp)->asRegExp();
|
||||
source = reobj->getSource();
|
||||
flagsword = reobj->getFlags();
|
||||
RegExpObject &reobj = (*objp)->asRegExp();
|
||||
source = reobj.getSource();
|
||||
flagsword = reobj.getFlags();
|
||||
}
|
||||
if (!JS_XDRString(xdr, &source) || !JS_XDRUint32(xdr, &flagsword))
|
||||
return false;
|
||||
@ -360,14 +360,14 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
|
||||
static void
|
||||
regexp_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
obj->asRegExp()->finalize(cx);
|
||||
obj->asRegExp().finalize(cx);
|
||||
}
|
||||
|
||||
static void
|
||||
regexp_trace(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
if (trc->runtime->gcRunning)
|
||||
obj->asRegExp()->purge(trc->context);
|
||||
obj->asRegExp().purge(trc->context);
|
||||
}
|
||||
|
||||
Class js::RegExpClass = {
|
||||
@ -565,7 +565,7 @@ js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *proto)
|
||||
JS_ASSERT(proto->isRegExp());
|
||||
|
||||
RegExpObjectBuilder builder(cx);
|
||||
return builder.clone(obj->asRegExp(), proto->asRegExp());
|
||||
return builder.clone(&obj->asRegExp(), &proto->asRegExp());
|
||||
}
|
||||
|
||||
JSFlatString *
|
||||
|
@ -65,7 +65,7 @@ enum RegExpRunStatus
|
||||
RegExpRunStatus_Success_NotFound
|
||||
};
|
||||
|
||||
class RegExpObject : public ::JSObject
|
||||
class RegExpObject : public JSObject
|
||||
{
|
||||
typedef detail::RegExpPrivate RegExpPrivate;
|
||||
typedef detail::RegExpPrivateCode RegExpPrivateCode;
|
||||
|
345
js/src/vm/ScopeObject-inl.h
Normal file
345
js/src/vm/ScopeObject-inl.h
Normal file
@ -0,0 +1,345 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey call object code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Paul Biggar <pbiggar@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef ScopeObject_inl_h___
|
||||
#define ScopeObject_inl_h___
|
||||
|
||||
#include "ScopeObject.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
inline JSObject &
|
||||
ScopeObject::enclosingScope() const
|
||||
{
|
||||
return getReservedSlot(SCOPE_CHAIN_SLOT).toObject();
|
||||
}
|
||||
|
||||
inline bool
|
||||
ScopeObject::setEnclosingScope(JSContext *cx, JSObject &obj)
|
||||
{
|
||||
if (!obj.setDelegate(cx))
|
||||
return false;
|
||||
setFixedSlot(SCOPE_CHAIN_SLOT, ObjectValue(obj));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline StackFrame *
|
||||
ScopeObject::maybeStackFrame() const
|
||||
{
|
||||
JS_ASSERT(!isStaticBlock());
|
||||
return reinterpret_cast<StackFrame *>(JSObject::getPrivate());
|
||||
}
|
||||
|
||||
inline void
|
||||
ScopeObject::setStackFrame(StackFrame *frame)
|
||||
{
|
||||
return setPrivate(frame);
|
||||
}
|
||||
|
||||
/*static*/ inline size_t
|
||||
ScopeObject::offsetOfEnclosingScope()
|
||||
{
|
||||
return getFixedSlotOffset(SCOPE_CHAIN_SLOT);
|
||||
}
|
||||
|
||||
inline bool
|
||||
CallObject::isForEval() const
|
||||
{
|
||||
JS_ASSERT(getReservedSlot(CALLEE_SLOT).isObjectOrNull());
|
||||
JS_ASSERT_IF(getReservedSlot(CALLEE_SLOT).isObject(),
|
||||
getReservedSlot(CALLEE_SLOT).toObject().isFunction());
|
||||
return getReservedSlot(CALLEE_SLOT).isNull();
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::setCallee(JSObject *callee)
|
||||
{
|
||||
JS_ASSERT_IF(callee, callee->isFunction());
|
||||
setFixedSlot(CALLEE_SLOT, ObjectOrNullValue(callee));
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
CallObject::getCallee() const
|
||||
{
|
||||
return getReservedSlot(CALLEE_SLOT).toObjectOrNull();
|
||||
}
|
||||
|
||||
inline JSFunction *
|
||||
CallObject::getCalleeFunction() const
|
||||
{
|
||||
return getReservedSlot(CALLEE_SLOT).toObject().toFunction();
|
||||
}
|
||||
|
||||
inline const Value &
|
||||
CallObject::getArguments() const
|
||||
{
|
||||
JS_ASSERT(!isForEval());
|
||||
return getReservedSlot(ARGUMENTS_SLOT);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::setArguments(const Value &v)
|
||||
{
|
||||
JS_ASSERT(!isForEval());
|
||||
setFixedSlot(ARGUMENTS_SLOT, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::initArguments(const Value &v)
|
||||
{
|
||||
JS_ASSERT(!isForEval());
|
||||
initFixedSlot(ARGUMENTS_SLOT, v);
|
||||
}
|
||||
|
||||
inline const Value &
|
||||
CallObject::arg(uintN i) const
|
||||
{
|
||||
JS_ASSERT(i < getCalleeFunction()->nargs);
|
||||
return getSlot(RESERVED_SLOTS + i);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::setArg(uintN i, const Value &v)
|
||||
{
|
||||
JS_ASSERT(i < getCalleeFunction()->nargs);
|
||||
setSlot(RESERVED_SLOTS + i, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::initArgUnchecked(uintN i, const Value &v)
|
||||
{
|
||||
JS_ASSERT(i < getCalleeFunction()->nargs);
|
||||
initSlotUnchecked(RESERVED_SLOTS + i, v);
|
||||
}
|
||||
|
||||
inline const Value &
|
||||
CallObject::var(uintN i) const
|
||||
{
|
||||
JSFunction *fun = getCalleeFunction();
|
||||
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
|
||||
JS_ASSERT(i < fun->script()->bindings.countVars());
|
||||
return getSlot(RESERVED_SLOTS + fun->nargs + i);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::setVar(uintN i, const Value &v)
|
||||
{
|
||||
JSFunction *fun = getCalleeFunction();
|
||||
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
|
||||
JS_ASSERT(i < fun->script()->bindings.countVars());
|
||||
setSlot(RESERVED_SLOTS + fun->nargs + i, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::initVarUnchecked(uintN i, const Value &v)
|
||||
{
|
||||
JSFunction *fun = getCalleeFunction();
|
||||
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
|
||||
JS_ASSERT(i < fun->script()->bindings.countVars());
|
||||
initSlotUnchecked(RESERVED_SLOTS + fun->nargs + i, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
CallObject::copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots)
|
||||
{
|
||||
JS_ASSERT(slotInRange(RESERVED_SLOTS + nargs + nvars, SENTINEL_ALLOWED));
|
||||
copySlotRange(RESERVED_SLOTS, argv, nargs);
|
||||
copySlotRange(RESERVED_SLOTS + nargs, slots, nvars);
|
||||
}
|
||||
|
||||
inline HeapValueArray
|
||||
CallObject::argArray()
|
||||
{
|
||||
DebugOnly<JSFunction*> fun = getCalleeFunction();
|
||||
JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS, fun->nargs));
|
||||
return HeapValueArray(getSlotAddress(RESERVED_SLOTS));
|
||||
}
|
||||
|
||||
inline HeapValueArray
|
||||
CallObject::varArray()
|
||||
{
|
||||
JSFunction *fun = getCalleeFunction();
|
||||
JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS + fun->nargs,
|
||||
fun->script()->bindings.countVars()));
|
||||
return HeapValueArray(getSlotAddress(RESERVED_SLOTS + fun->nargs));
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
NestedScopeObject::stackDepth() const
|
||||
{
|
||||
return getReservedSlot(DEPTH_SLOT).toPrivateUint32();
|
||||
}
|
||||
|
||||
inline JSObject &
|
||||
WithObject::withThis() const
|
||||
{
|
||||
return getReservedSlot(THIS_SLOT).toObject();
|
||||
}
|
||||
|
||||
inline JSObject &
|
||||
WithObject::object() const
|
||||
{
|
||||
return *JSObject::getProto();
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
BlockObject::slotCount() const
|
||||
{
|
||||
return propertyCount();
|
||||
}
|
||||
|
||||
inline HeapValue &
|
||||
BlockObject::slotValue(unsigned i)
|
||||
{
|
||||
return getSlotRef(RESERVED_SLOTS + i);
|
||||
}
|
||||
|
||||
inline StaticBlockObject *
|
||||
StaticBlockObject::enclosingBlock() const
|
||||
{
|
||||
JSObject *obj = getReservedSlot(SCOPE_CHAIN_SLOT).toObjectOrNull();
|
||||
return obj ? &obj->asStaticBlock() : NULL;
|
||||
}
|
||||
|
||||
inline void
|
||||
StaticBlockObject::setEnclosingBlock(StaticBlockObject *blockObj)
|
||||
{
|
||||
setFixedSlot(SCOPE_CHAIN_SLOT, ObjectOrNullValue(blockObj));
|
||||
}
|
||||
|
||||
inline void
|
||||
StaticBlockObject::setStackDepth(uint32_t depth)
|
||||
{
|
||||
JS_ASSERT(getReservedSlot(DEPTH_SLOT).isUndefined());
|
||||
getReservedSlotRef(DEPTH_SLOT).init(PrivateUint32Value(depth));
|
||||
}
|
||||
|
||||
inline void
|
||||
StaticBlockObject::setDefinitionParseNode(unsigned i, Definition *def)
|
||||
{
|
||||
JS_ASSERT(slotValue(i).isUndefined());
|
||||
slotValue(i).init(PrivateValue(def));
|
||||
}
|
||||
|
||||
inline Definition *
|
||||
StaticBlockObject::maybeDefinitionParseNode(unsigned i)
|
||||
{
|
||||
Value v = slotValue(i);
|
||||
return v.isUndefined() ? NULL : reinterpret_cast<Definition *>(v.toPrivate());
|
||||
}
|
||||
|
||||
inline void
|
||||
StaticBlockObject::poisonDefinitionParseNode(unsigned i)
|
||||
{
|
||||
slotValue(i).init(PrivateValue(NULL));
|
||||
}
|
||||
|
||||
inline StaticBlockObject &
|
||||
ClonedBlockObject::staticBlock() const
|
||||
{
|
||||
return getProto()->asStaticBlock();
|
||||
}
|
||||
|
||||
inline const Value &
|
||||
ClonedBlockObject::closedSlot(unsigned i)
|
||||
{
|
||||
JS_ASSERT(!maybeStackFrame());
|
||||
return slotValue(i);
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
inline js::ScopeObject &
|
||||
JSObject::asScope()
|
||||
{
|
||||
JS_ASSERT(isScope());
|
||||
return *static_cast<js::ScopeObject *>(this);
|
||||
}
|
||||
|
||||
inline js::CallObject &
|
||||
JSObject::asCall()
|
||||
{
|
||||
JS_ASSERT(isCall());
|
||||
return *static_cast<js::CallObject *>(this);
|
||||
}
|
||||
|
||||
inline js::DeclEnvObject &
|
||||
JSObject::asDeclEnv()
|
||||
{
|
||||
JS_ASSERT(isDeclEnv());
|
||||
return *static_cast<js::DeclEnvObject *>(this);
|
||||
}
|
||||
|
||||
inline js::NestedScopeObject &
|
||||
JSObject::asNestedScope()
|
||||
{
|
||||
JS_ASSERT(isWith() || isBlock());
|
||||
return *static_cast<js::NestedScopeObject *>(this);
|
||||
}
|
||||
|
||||
inline js::WithObject &
|
||||
JSObject::asWith()
|
||||
{
|
||||
JS_ASSERT(isWith());
|
||||
return *static_cast<js::WithObject *>(this);
|
||||
}
|
||||
|
||||
inline js::BlockObject &
|
||||
JSObject::asBlock()
|
||||
{
|
||||
JS_ASSERT(isBlock());
|
||||
return *static_cast<js::BlockObject *>(this);
|
||||
}
|
||||
|
||||
inline js::StaticBlockObject &
|
||||
JSObject::asStaticBlock()
|
||||
{
|
||||
JS_ASSERT(isStaticBlock());
|
||||
return *static_cast<js::StaticBlockObject *>(this);
|
||||
}
|
||||
|
||||
inline js::ClonedBlockObject &
|
||||
JSObject::asClonedBlock()
|
||||
{
|
||||
JS_ASSERT(isClonedBlock());
|
||||
return *static_cast<js::ClonedBlockObject *>(this);
|
||||
}
|
||||
|
||||
#endif /* CallObject_inl_h___ */
|
737
js/src/vm/ScopeObject.cpp
Normal file
737
js/src/vm/ScopeObject.cpp
Normal file
@ -0,0 +1,737 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey call object code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Paul Biggar <pbiggar@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "jscompartment.h"
|
||||
#include "jsiter.h"
|
||||
#include "jsscope.h"
|
||||
#if JS_HAS_XDR
|
||||
#include "jsxdrapi.h"
|
||||
#endif
|
||||
|
||||
#include "GlobalObject.h"
|
||||
#include "ScopeObject.h"
|
||||
|
||||
#include "jsatominlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "ScopeObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
/*
|
||||
* Construct a call object for the given bindings. If this is a call object
|
||||
* for a function invocation, callee should be the function being called.
|
||||
* Otherwise it must be a call object for eval of strict mode code, and callee
|
||||
* must be null.
|
||||
*/
|
||||
CallObject *
|
||||
CallObject::create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObject *callee)
|
||||
{
|
||||
Bindings &bindings = script->bindings;
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(bindings.lastShape()->numFixedSlots() + 1);
|
||||
|
||||
RootedVarTypeObject type(cx);
|
||||
|
||||
type = cx->compartment->getEmptyType(cx);
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
HeapValue *slots;
|
||||
if (!PreallocateObjectDynamicSlots(cx, bindings.lastShape(), &slots))
|
||||
return NULL;
|
||||
|
||||
RootedVarShape shape(cx);
|
||||
shape = bindings.lastShape();
|
||||
|
||||
JSObject *obj = JSObject::create(cx, kind, shape, type, slots);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Update the parent for bindings associated with non-compileAndGo scripts,
|
||||
* whose call objects do not have a consistent global variable and need
|
||||
* to be updated dynamically.
|
||||
*/
|
||||
JSObject &global = enclosing.global();
|
||||
if (&global != obj->getParent()) {
|
||||
JS_ASSERT(obj->getParent() == NULL);
|
||||
if (!obj->setParent(cx, &global))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(!obj->inDictionaryMode());
|
||||
for (Shape::Range r = obj->lastProperty(); !r.empty(); r.popFront()) {
|
||||
const Shape &s = r.front();
|
||||
if (s.hasSlot()) {
|
||||
JS_ASSERT(s.slot() + 1 == obj->slotSpan());
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!obj->asScope().setEnclosingScope(cx, enclosing))
|
||||
return NULL;
|
||||
|
||||
JS_ASSERT_IF(callee, callee->isFunction());
|
||||
obj->initFixedSlot(CALLEE_SLOT, ObjectOrNullValue(callee));
|
||||
|
||||
/*
|
||||
* If |bindings| is for a function that has extensible parents, that means
|
||||
* its Call should have its own shape; see BaseShape::extensibleParents.
|
||||
*/
|
||||
if (obj->lastProperty()->extensibleParents() && !obj->generateOwnShape(cx))
|
||||
return NULL;
|
||||
|
||||
return &obj->asCall();
|
||||
}
|
||||
|
||||
Class js::DeclEnvClass = {
|
||||
js_Object_str,
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(DeclEnvObject::RESERVED_SLOTS) |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub
|
||||
};
|
||||
|
||||
DeclEnvObject *
|
||||
DeclEnvObject::create(JSContext *cx, StackFrame *fp)
|
||||
{
|
||||
RootedVarTypeObject type(cx);
|
||||
type = cx->compartment->getEmptyType(cx);
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
RootedVarShape emptyDeclEnvShape(cx);
|
||||
emptyDeclEnvShape = EmptyShape::getInitialShape(cx, &DeclEnvClass, NULL,
|
||||
&fp->scopeChain().global(),
|
||||
FINALIZE_KIND);
|
||||
if (!emptyDeclEnvShape)
|
||||
return NULL;
|
||||
|
||||
JSObject *obj = JSObject::create(cx, FINALIZE_KIND, emptyDeclEnvShape, type, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
obj->setPrivate(fp);
|
||||
if (!obj->asScope().setEnclosingScope(cx, fp->scopeChain()))
|
||||
return NULL;
|
||||
|
||||
return &obj->asDeclEnv();
|
||||
}
|
||||
|
||||
WithObject *
|
||||
WithObject::create(JSContext *cx, StackFrame *fp, JSObject &proto, JSObject &enclosing,
|
||||
uint32_t depth)
|
||||
{
|
||||
RootedVarTypeObject type(cx);
|
||||
type = proto.getNewType(cx);
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
RootedVarShape emptyWithShape(cx);
|
||||
emptyWithShape = EmptyShape::getInitialShape(cx, &WithClass, &proto,
|
||||
&enclosing.global(), FINALIZE_KIND);
|
||||
if (!emptyWithShape)
|
||||
return NULL;
|
||||
|
||||
JSObject *obj = JSObject::create(cx, FINALIZE_KIND, emptyWithShape, type, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (!obj->asScope().setEnclosingScope(cx, enclosing))
|
||||
return NULL;
|
||||
|
||||
obj->setReservedSlot(DEPTH_SLOT, PrivateUint32Value(depth));
|
||||
obj->setPrivate(js_FloatingFrameIfGenerator(cx, fp));
|
||||
|
||||
JSObject *thisp = proto.thisObject(cx);
|
||||
if (!thisp)
|
||||
return NULL;
|
||||
|
||||
obj->setFixedSlot(THIS_SLOT, ObjectValue(*thisp));
|
||||
|
||||
return &obj->asWith();
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_LookupGeneric(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, JSProperty **propp)
|
||||
{
|
||||
/* Fixes bug 463997 */
|
||||
uintN flags = cx->resolveFlags;
|
||||
if (flags == RESOLVE_INFER)
|
||||
flags = js_InferFlags(cx, flags);
|
||||
flags |= JSRESOLVE_WITH;
|
||||
JSAutoResolveFlags rf(cx, flags);
|
||||
return obj->asWith().object().lookupGeneric(cx, id, objp, propp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_LookupProperty(JSContext *cx, JSObject *obj, PropertyName *name, JSObject **objp, JSProperty **propp)
|
||||
{
|
||||
return with_LookupGeneric(cx, obj, ATOM_TO_JSID(name), objp, propp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_LookupElement(JSContext *cx, JSObject *obj, uint32_t index, JSObject **objp,
|
||||
JSProperty **propp)
|
||||
{
|
||||
jsid id;
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
return with_LookupGeneric(cx, obj, id, objp, propp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_LookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp, JSProperty **propp)
|
||||
{
|
||||
return with_LookupGeneric(cx, obj, SPECIALID_TO_JSID(sid), objp, propp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
|
||||
{
|
||||
return obj->asWith().object().getGeneric(cx, id, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp)
|
||||
{
|
||||
return with_GetGeneric(cx, obj, receiver, ATOM_TO_JSID(name), vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp)
|
||||
{
|
||||
jsid id;
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
return with_GetGeneric(cx, obj, receiver, id, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
|
||||
{
|
||||
return with_GetGeneric(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
|
||||
{
|
||||
return obj->asWith().object().setGeneric(cx, id, vp, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict)
|
||||
{
|
||||
return obj->asWith().object().setProperty(cx, name, vp, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetElement(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict)
|
||||
{
|
||||
return obj->asWith().object().setElement(cx, index, vp, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
|
||||
{
|
||||
return obj->asWith().object().setSpecial(cx, sid, vp, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
|
||||
{
|
||||
return obj->asWith().object().getGenericAttributes(cx, id, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
|
||||
{
|
||||
return obj->asWith().object().getPropertyAttributes(cx, name, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, uintN *attrsp)
|
||||
{
|
||||
return obj->asWith().object().getElementAttributes(cx, index, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_GetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
|
||||
{
|
||||
return obj->asWith().object().getSpecialAttributes(cx, sid, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
|
||||
{
|
||||
return obj->asWith().object().setGenericAttributes(cx, id, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
|
||||
{
|
||||
return obj->asWith().object().setPropertyAttributes(cx, name, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, uintN *attrsp)
|
||||
{
|
||||
return obj->asWith().object().setElementAttributes(cx, index, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_SetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
|
||||
{
|
||||
return obj->asWith().object().setSpecialAttributes(cx, sid, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
|
||||
{
|
||||
return obj->asWith().object().deleteGeneric(cx, id, rval, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_DeleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
|
||||
{
|
||||
return obj->asWith().object().deleteProperty(cx, name, rval, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict)
|
||||
{
|
||||
return obj->asWith().object().deleteElement(cx, index, rval, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_DeleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
|
||||
{
|
||||
return obj->asWith().object().deleteSpecial(cx, sid, rval, strict);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
with_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
Value *statep, jsid *idp)
|
||||
{
|
||||
return obj->asWith().object().enumerate(cx, enum_op, statep, idp);
|
||||
}
|
||||
|
||||
static JSType
|
||||
with_TypeOf(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return JSTYPE_OBJECT;
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
with_ThisObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return &obj->asWith().withThis();
|
||||
}
|
||||
|
||||
Class js::WithClass = {
|
||||
"With",
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(WithObject::RESERVED_SLOTS) |
|
||||
JSCLASS_IS_ANONYMOUS,
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub,
|
||||
NULL, /* finalize */
|
||||
NULL, /* reserved */
|
||||
NULL, /* checkAccess */
|
||||
NULL, /* call */
|
||||
NULL, /* construct */
|
||||
NULL, /* xdrObject */
|
||||
NULL, /* hasInstance */
|
||||
NULL, /* trace */
|
||||
JS_NULL_CLASS_EXT,
|
||||
{
|
||||
with_LookupGeneric,
|
||||
with_LookupProperty,
|
||||
with_LookupElement,
|
||||
with_LookupSpecial,
|
||||
NULL, /* defineGeneric */
|
||||
NULL, /* defineProperty */
|
||||
NULL, /* defineElement */
|
||||
NULL, /* defineSpecial */
|
||||
with_GetGeneric,
|
||||
with_GetProperty,
|
||||
with_GetElement,
|
||||
NULL, /* getElementIfPresent */
|
||||
with_GetSpecial,
|
||||
with_SetGeneric,
|
||||
with_SetProperty,
|
||||
with_SetElement,
|
||||
with_SetSpecial,
|
||||
with_GetGenericAttributes,
|
||||
with_GetPropertyAttributes,
|
||||
with_GetElementAttributes,
|
||||
with_GetSpecialAttributes,
|
||||
with_SetGenericAttributes,
|
||||
with_SetPropertyAttributes,
|
||||
with_SetElementAttributes,
|
||||
with_SetSpecialAttributes,
|
||||
with_DeleteGeneric,
|
||||
with_DeleteProperty,
|
||||
with_DeleteElement,
|
||||
with_DeleteSpecial,
|
||||
with_Enumerate,
|
||||
with_TypeOf,
|
||||
NULL, /* fix */
|
||||
with_ThisObject,
|
||||
NULL, /* clear */
|
||||
}
|
||||
};
|
||||
|
||||
ClonedBlockObject *
|
||||
ClonedBlockObject::create(JSContext *cx, StaticBlockObject &block, StackFrame *fp)
|
||||
{
|
||||
RootedVarTypeObject type(cx);
|
||||
type = block.getNewType(cx);
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
HeapValue *slots;
|
||||
if (!PreallocateObjectDynamicSlots(cx, block.lastProperty(), &slots))
|
||||
return NULL;
|
||||
|
||||
RootedVarShape shape(cx);
|
||||
shape = block.lastProperty();
|
||||
|
||||
JSObject *obj = JSObject::create(cx, FINALIZE_KIND, shape, type, slots);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
/* Set the parent if necessary, as for call objects. */
|
||||
JSObject &global = fp->scopeChain().global();
|
||||
if (&global != obj->getParent()) {
|
||||
JS_ASSERT(obj->getParent() == NULL);
|
||||
if (!obj->setParent(cx, &global))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_ASSERT(!obj->inDictionaryMode());
|
||||
JS_ASSERT(obj->slotSpan() >= block.slotCount() + RESERVED_SLOTS);
|
||||
|
||||
obj->setReservedSlot(DEPTH_SLOT, PrivateUint32Value(block.stackDepth()));
|
||||
obj->setPrivate(js_FloatingFrameIfGenerator(cx, fp));
|
||||
|
||||
if (obj->lastProperty()->extensibleParents() && !obj->generateOwnShape(cx))
|
||||
return NULL;
|
||||
|
||||
return &obj->asClonedBlock();
|
||||
}
|
||||
|
||||
bool
|
||||
ClonedBlockObject::put(JSContext *cx, JSBool normalUnwind)
|
||||
{
|
||||
StackFrame *fp = cx->fp();
|
||||
JS_ASSERT(maybeStackFrame() == js_FloatingFrameIfGenerator(cx, fp));
|
||||
|
||||
uint32_t count = slotCount();
|
||||
uint32_t depth = stackDepth();
|
||||
|
||||
/* The block and its locals must be on the current stack for GC safety. */
|
||||
JS_ASSERT(depth <= uint32_t(cx->regs().sp - fp->base()));
|
||||
JS_ASSERT(count <= uint32_t(cx->regs().sp - fp->base() - depth));
|
||||
|
||||
/* See comments in CheckDestructuring in frontend/Parser.cpp. */
|
||||
JS_ASSERT(count >= 1);
|
||||
|
||||
if (normalUnwind)
|
||||
copySlotRange(RESERVED_SLOTS, fp->base() + depth, count);
|
||||
|
||||
/* We must clear the private slot even with errors. */
|
||||
setPrivate(NULL);
|
||||
fp->setScopeChainNoCallObj(enclosingScope());
|
||||
return normalUnwind;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
block_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
{
|
||||
/*
|
||||
* Block objects are never exposed to script, and the engine handles them
|
||||
* with care. So unlike other getters, this one can assert (rather than
|
||||
* check) certain invariants about obj.
|
||||
*/
|
||||
ClonedBlockObject &block = obj->asClonedBlock();
|
||||
uintN index = (uintN) JSID_TO_INT(id);
|
||||
JS_ASSERT(index < block.slotCount());
|
||||
|
||||
if (StackFrame *fp = block.maybeStackFrame()) {
|
||||
fp = js_LiveFrameIfGenerator(fp);
|
||||
index += fp->numFixed() + block.stackDepth();
|
||||
JS_ASSERT(index < fp->numSlots());
|
||||
*vp = fp->slots()[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Values are in slots immediately following the class-reserved ones. */
|
||||
JS_ASSERT(block.closedSlot(index) == *vp);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
block_setProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
{
|
||||
ClonedBlockObject &block = obj->asClonedBlock();
|
||||
uintN index = (uintN) JSID_TO_INT(id);
|
||||
JS_ASSERT(index < block.slotCount());
|
||||
|
||||
if (StackFrame *fp = block.maybeStackFrame()) {
|
||||
fp = js_LiveFrameIfGenerator(fp);
|
||||
index += fp->numFixed() + block.stackDepth();
|
||||
JS_ASSERT(index < fp->numSlots());
|
||||
fp->slots()[index] = *vp;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The value in *vp will be written back to the slot in obj that was
|
||||
* allocated when this let binding was defined.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
StaticBlockObject *
|
||||
StaticBlockObject::create(JSContext *cx)
|
||||
{
|
||||
RootedVarTypeObject type(cx);
|
||||
type = cx->compartment->getEmptyType(cx);
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
RootedVarShape emptyBlockShape(cx);
|
||||
emptyBlockShape = EmptyShape::getInitialShape(cx, &BlockClass, NULL, NULL, FINALIZE_KIND);
|
||||
if (!emptyBlockShape)
|
||||
return NULL;
|
||||
|
||||
JSObject *obj = JSObject::create(cx, FINALIZE_KIND, emptyBlockShape, type, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
return &obj->asStaticBlock();
|
||||
}
|
||||
|
||||
const Shape *
|
||||
StaticBlockObject::addVar(JSContext *cx, jsid id, intN index, bool *redeclared)
|
||||
{
|
||||
*redeclared = false;
|
||||
|
||||
/* Inline JSObject::addProperty in order to trap the redefinition case. */
|
||||
Shape **spp;
|
||||
if (Shape::search(cx, lastProperty(), id, &spp, true)) {
|
||||
*redeclared = true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't convert this object to dictionary mode so that we can clone the
|
||||
* block's shape later.
|
||||
*/
|
||||
uint32_t slot = JSSLOT_FREE(&BlockClass) + index;
|
||||
return addPropertyInternal(cx, id, block_getProperty, block_setProperty,
|
||||
slot, JSPROP_ENUMERATE | JSPROP_PERMANENT,
|
||||
Shape::HAS_SHORTID, index, spp,
|
||||
/* allowDictionary = */ false);
|
||||
}
|
||||
|
||||
Class js::BlockClass = {
|
||||
"Block",
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(BlockObject::RESERVED_SLOTS) |
|
||||
JSCLASS_IS_ANONYMOUS,
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub
|
||||
};
|
||||
|
||||
#if JS_HAS_XDR
|
||||
|
||||
#define NO_PARENT_INDEX UINT32_MAX
|
||||
|
||||
static uint32_t
|
||||
FindObjectIndex(JSObjectArray *array, JSObject *obj)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (array) {
|
||||
i = array->length;
|
||||
do {
|
||||
|
||||
if (array->vector[--i] == obj)
|
||||
return i;
|
||||
} while (i != 0);
|
||||
}
|
||||
|
||||
return NO_PARENT_INDEX;
|
||||
}
|
||||
|
||||
bool
|
||||
js_XDRStaticBlockObject(JSXDRState *xdr, StaticBlockObject **objp)
|
||||
{
|
||||
JSContext *cx;
|
||||
uint32_t parentId;
|
||||
StaticBlockObject *obj, *parent;
|
||||
uintN depth, count;
|
||||
uint32_t depthAndCount;
|
||||
const Shape *shape;
|
||||
|
||||
cx = xdr->cx;
|
||||
#ifdef __GNUC__
|
||||
obj = NULL; /* quell GCC overwarning */
|
||||
#endif
|
||||
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
obj = *objp;
|
||||
parent = obj->enclosingBlock();
|
||||
parentId = JSScript::isValidOffset(xdr->script->objectsOffset)
|
||||
? FindObjectIndex(xdr->script->objects(), parent)
|
||||
: NO_PARENT_INDEX;
|
||||
depth = uint16_t(obj->stackDepth());
|
||||
count = uint16_t(obj->slotCount());
|
||||
depthAndCount = uint32_t(depth << 16) | count;
|
||||
}
|
||||
#ifdef __GNUC__ /* suppress bogus gcc warnings */
|
||||
else count = 0;
|
||||
#endif
|
||||
|
||||
/* First, XDR the parent atomid. */
|
||||
if (!JS_XDRUint32(xdr, &parentId))
|
||||
return JS_FALSE;
|
||||
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
obj = StaticBlockObject::create(cx);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
*objp = obj;
|
||||
|
||||
/*
|
||||
* If there's a parent id, then get the parent out of our script's
|
||||
* object array. We know that we XDR block object in outer-to-inner
|
||||
* order, which means that getting the parent now will work.
|
||||
*/
|
||||
if (parentId == NO_PARENT_INDEX)
|
||||
parent = NULL;
|
||||
else
|
||||
parent = &xdr->script->getObject(parentId)->asStaticBlock();
|
||||
obj->setEnclosingBlock(parent);
|
||||
}
|
||||
|
||||
AutoObjectRooter tvr(cx, obj);
|
||||
|
||||
if (!JS_XDRUint32(xdr, &depthAndCount))
|
||||
return false;
|
||||
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
depth = uint16_t(depthAndCount >> 16);
|
||||
count = uint16_t(depthAndCount);
|
||||
obj->setStackDepth(depth);
|
||||
|
||||
/*
|
||||
* XDR the block object's properties. We know that there are 'count'
|
||||
* properties to XDR, stored as id/shortid pairs.
|
||||
*/
|
||||
for (uintN i = 0; i < count; i++) {
|
||||
JSAtom *atom;
|
||||
|
||||
/* XDR the real id. */
|
||||
if (!js_XDRAtom(xdr, &atom))
|
||||
return false;
|
||||
|
||||
bool redeclared;
|
||||
if (!obj->addVar(cx, ATOM_TO_JSID(atom), i, &redeclared)) {
|
||||
JS_ASSERT(!redeclared);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
AutoShapeVector shapes(cx);
|
||||
shapes.growBy(count);
|
||||
|
||||
for (Shape::Range r(obj->lastProperty()); !r.empty(); r.popFront()) {
|
||||
shape = &r.front();
|
||||
shapes[shape->shortid()] = shape;
|
||||
}
|
||||
|
||||
/*
|
||||
* XDR the block object's properties. We know that there are 'count'
|
||||
* properties to XDR, stored as id/shortid pairs.
|
||||
*/
|
||||
for (uintN i = 0; i < count; i++) {
|
||||
shape = shapes[i];
|
||||
JS_ASSERT(shape->getter() == block_getProperty);
|
||||
|
||||
jsid propid = shape->propid();
|
||||
JS_ASSERT(JSID_IS_ATOM(propid));
|
||||
JSAtom *atom = JSID_TO_ATOM(propid);
|
||||
|
||||
#ifdef DEBUG
|
||||
uint16_t shortid = uint16_t(shape->shortid());
|
||||
JS_ASSERT(shortid == i);
|
||||
#endif
|
||||
|
||||
/* XDR the real id. */
|
||||
if (!js_XDRAtom(xdr, &atom))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* JS_HAS_XDR */
|
264
js/src/vm/ScopeObject.h
Normal file
264
js/src/vm/ScopeObject.h
Normal file
@ -0,0 +1,264 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey call object code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Paul Biggar <pbiggar@mozilla.com> (original author)
|
||||
* Luke Wagner <luke@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef ScopeObject_h___
|
||||
#define ScopeObject_h___
|
||||
|
||||
#include "jsobj.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* Scope objects
|
||||
*
|
||||
* Scope objects are technically real JSObjects but only belong on the scope
|
||||
* chain (that is, fp->scopeChain() or fun->environment()). The hierarchy of
|
||||
* scope objects is:
|
||||
*
|
||||
* JSObject Generic object
|
||||
* \
|
||||
* ScopeObject Engine-internal scope
|
||||
* \ \ \
|
||||
* \ \ DeclEnvObject Holds name of recursive/heavyweight named lambda
|
||||
* \ \
|
||||
* \ CallObject Scope of entire function or strict eval
|
||||
* \
|
||||
* NestedScopeObject Scope created for a statement
|
||||
* \ \
|
||||
* \ WithObject with
|
||||
* \
|
||||
* BlockObject Shared interface of cloned/static block objects
|
||||
* \ \
|
||||
* \ ClonedBlockObject let, switch, catch, for
|
||||
* \
|
||||
* StaticBlockObject See NB
|
||||
*
|
||||
* This hierarchy represents more than just the interface hierarchy: reserved
|
||||
* slots in base classes are fixed for all derived classes. Thus, for example,
|
||||
* ScopeObject::enclosingScope() can simply access a fixed slot without further
|
||||
* dynamic type information.
|
||||
*
|
||||
* NB: Static block objects are a special case: these objects are created at
|
||||
* compile time to hold the shape/binding information from which block objects
|
||||
* are cloned at runtime. These objects should never escape into the wild and
|
||||
* support a restricted set of ScopeObject operations.
|
||||
*/
|
||||
|
||||
class ScopeObject : public JSObject
|
||||
{
|
||||
/* Use maybeStackFrame() instead. */
|
||||
void *getPrivate() const;
|
||||
|
||||
protected:
|
||||
static const uint32_t SCOPE_CHAIN_SLOT = 0;
|
||||
|
||||
public:
|
||||
/*
|
||||
* Since every scope chain terminates with a global object and GlobalObject
|
||||
* does not derive ScopeObject (it has a completely different layout), the
|
||||
* enclosing scope of a ScopeObject is necessarily non-null.
|
||||
*/
|
||||
inline JSObject &enclosingScope() const;
|
||||
inline bool setEnclosingScope(JSContext *cx, JSObject &obj);
|
||||
|
||||
/*
|
||||
* The stack frame for this scope object, if the frame is still active.
|
||||
* Note: these members may not be called for a StaticBlockObject.
|
||||
*/
|
||||
inline js::StackFrame *maybeStackFrame() const;
|
||||
inline void setStackFrame(StackFrame *frame);
|
||||
|
||||
/* For jit access. */
|
||||
static inline size_t offsetOfEnclosingScope();
|
||||
};
|
||||
|
||||
class CallObject : public ScopeObject
|
||||
{
|
||||
static const uint32_t CALLEE_SLOT = 1;
|
||||
static const uint32_t ARGUMENTS_SLOT = 2;
|
||||
|
||||
public:
|
||||
static const uint32_t RESERVED_SLOTS = 3;
|
||||
|
||||
static CallObject *
|
||||
create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObject *callee);
|
||||
|
||||
/* True if this is for a strict mode eval frame or for a function call. */
|
||||
inline bool isForEval() const;
|
||||
|
||||
/*
|
||||
* The callee function if this CallObject was created for a function
|
||||
* invocation, or null if it was created for a strict mode eval frame.
|
||||
*/
|
||||
inline JSObject *getCallee() const;
|
||||
inline JSFunction *getCalleeFunction() const;
|
||||
inline void setCallee(JSObject *callee);
|
||||
|
||||
/* Returns the callee's arguments object. */
|
||||
inline const js::Value &getArguments() const;
|
||||
inline void setArguments(const js::Value &v);
|
||||
inline void initArguments(const js::Value &v);
|
||||
|
||||
/* Returns the formal argument at the given index. */
|
||||
inline const js::Value &arg(uintN i) const;
|
||||
inline void setArg(uintN i, const js::Value &v);
|
||||
inline void initArgUnchecked(uintN i, const js::Value &v);
|
||||
|
||||
/* Returns the variable at the given index. */
|
||||
inline const js::Value &var(uintN i) const;
|
||||
inline void setVar(uintN i, const js::Value &v);
|
||||
inline void initVarUnchecked(uintN i, const js::Value &v);
|
||||
|
||||
/*
|
||||
* Get the actual arrays of arguments and variables. Only call if type
|
||||
* inference is enabled, where we ensure that call object variables are in
|
||||
* contiguous slots (see NewCallObject).
|
||||
*/
|
||||
inline js::HeapValueArray argArray();
|
||||
inline js::HeapValueArray varArray();
|
||||
|
||||
inline void copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots);
|
||||
};
|
||||
|
||||
class DeclEnvObject : public ScopeObject
|
||||
{
|
||||
public:
|
||||
static const uint32_t RESERVED_SLOTS = 1;
|
||||
static const gc::AllocKind FINALIZE_KIND = gc::FINALIZE_OBJECT2;
|
||||
|
||||
static DeclEnvObject *create(JSContext *cx, StackFrame *fp);
|
||||
|
||||
};
|
||||
|
||||
class NestedScopeObject : public ScopeObject
|
||||
{
|
||||
protected:
|
||||
static const unsigned DEPTH_SLOT = 1;
|
||||
|
||||
public:
|
||||
/* Return the abstract stack depth right before entering this nested scope. */
|
||||
uint32_t stackDepth() const;
|
||||
};
|
||||
|
||||
class WithObject : public NestedScopeObject
|
||||
{
|
||||
static const unsigned THIS_SLOT = 2;
|
||||
|
||||
/* Use WithObject::object() instead. */
|
||||
JSObject *getProto() const;
|
||||
|
||||
public:
|
||||
static const unsigned RESERVED_SLOTS = 3;
|
||||
static const gc::AllocKind FINALIZE_KIND = gc::FINALIZE_OBJECT4;
|
||||
|
||||
static WithObject *
|
||||
create(JSContext *cx, StackFrame *fp, JSObject &proto, JSObject &enclosing, uint32_t depth);
|
||||
|
||||
/* Return object for the 'this' class hook. */
|
||||
JSObject &withThis() const;
|
||||
|
||||
/* Return the 'o' in 'with (o)'. */
|
||||
JSObject &object() const;
|
||||
};
|
||||
|
||||
class BlockObject : public NestedScopeObject
|
||||
{
|
||||
public:
|
||||
static const unsigned RESERVED_SLOTS = 2;
|
||||
static const gc::AllocKind FINALIZE_KIND = gc::FINALIZE_OBJECT4;
|
||||
|
||||
/* Return the number of variables associated with this block. */
|
||||
inline uint32_t slotCount() const;
|
||||
|
||||
protected:
|
||||
/* Blocks contain an object slot for each slot i: 0 <= i < slotCount. */
|
||||
inline HeapValue &slotValue(unsigned i);
|
||||
};
|
||||
|
||||
class StaticBlockObject : public BlockObject
|
||||
{
|
||||
/* These ScopeObject operations are not valid on a static block object. */
|
||||
js::StackFrame *maybeStackFrame() const;
|
||||
void setStackFrame(StackFrame *frame);
|
||||
|
||||
public:
|
||||
static StaticBlockObject *create(JSContext *cx);
|
||||
|
||||
inline StaticBlockObject *enclosingBlock() const;
|
||||
inline void setEnclosingBlock(StaticBlockObject *blockObj);
|
||||
|
||||
void setStackDepth(uint32_t depth);
|
||||
|
||||
/*
|
||||
* Frontend compilation temporarily uses the object's slots to link
|
||||
* a let var to its associated Definition parse node.
|
||||
*/
|
||||
void setDefinitionParseNode(unsigned i, Definition *def);
|
||||
Definition *maybeDefinitionParseNode(unsigned i);
|
||||
void poisonDefinitionParseNode(unsigned i);
|
||||
|
||||
const js::Shape *addVar(JSContext *cx, jsid id, intN index, bool *redeclared);
|
||||
};
|
||||
|
||||
class ClonedBlockObject : public BlockObject
|
||||
{
|
||||
public:
|
||||
static ClonedBlockObject *create(JSContext *cx, StaticBlockObject &block, StackFrame *fp);
|
||||
|
||||
/* The static block from which this block was cloned. */
|
||||
StaticBlockObject &staticBlock() const;
|
||||
|
||||
/*
|
||||
* When this block's stack slots are about to be popped, 'put' must be
|
||||
* called to copy the slot values into this block's object slots.
|
||||
*/
|
||||
bool put(JSContext *cx, JSBool normalUnwind);
|
||||
|
||||
/* Assuming 'put' has been called, return the value of the ith let var. */
|
||||
const Value &closedSlot(unsigned i);
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
extern bool
|
||||
js_XDRStaticBlockObject(JSXDRState *xdr, js::StaticBlockObject **objp);
|
||||
|
||||
#endif /* ScopeObject_h___ */
|
@ -44,13 +44,14 @@
|
||||
#include "jscntxt.h"
|
||||
#include "jscompartment.h"
|
||||
|
||||
#include "Stack.h"
|
||||
#include "methodjit/MethodJIT.h"
|
||||
#include "vm/Stack.h"
|
||||
|
||||
#include "jsscriptinlines.h"
|
||||
#include "ArgumentsObject-inl.h"
|
||||
#include "CallObject-inl.h"
|
||||
|
||||
#include "methodjit/MethodJIT.h"
|
||||
#include "ArgumentsObject-inl.h"
|
||||
#include "ScopeObject-inl.h"
|
||||
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -84,7 +85,7 @@ StackFrame::varObj()
|
||||
{
|
||||
JSObject *obj = &scopeChain();
|
||||
while (!obj->isVarObj())
|
||||
obj = obj->scopeChain();
|
||||
obj = obj->enclosingScope();
|
||||
return *obj;
|
||||
}
|
||||
|
||||
@ -377,10 +378,10 @@ StackFrame::setScopeChainNoCallObj(JSObject &obj)
|
||||
if (hasCallObj()) {
|
||||
JSObject *pobj = &obj;
|
||||
while (pobj && pobj->getPrivate() != this)
|
||||
pobj = pobj->scopeChain();
|
||||
pobj = pobj->enclosingScope();
|
||||
JS_ASSERT(pobj);
|
||||
} else {
|
||||
for (JSObject *pobj = &obj; pobj->isInternalScope(); pobj = pobj->scopeChain())
|
||||
for (JSObject *pobj = &obj; pobj->isScope(); pobj = pobj->enclosingScope())
|
||||
JS_ASSERT_IF(pobj->isCall(), pobj->getPrivate() != this);
|
||||
}
|
||||
}
|
||||
@ -405,7 +406,7 @@ StackFrame::callObj() const
|
||||
|
||||
JSObject *pobj = &scopeChain();
|
||||
while (JS_UNLIKELY(!pobj->isCall()))
|
||||
pobj = pobj->scopeChain();
|
||||
pobj = pobj->enclosingScope();
|
||||
return pobj->asCall();
|
||||
}
|
||||
|
||||
@ -477,7 +478,7 @@ StackFrame::markFunctionEpilogueDone()
|
||||
*/
|
||||
scopeChain_ = isFunctionFrame()
|
||||
? callee().toFunction()->environment()
|
||||
: scopeChain_->internalScopeChain();
|
||||
: &scopeChain_->asScope().enclosingScope();
|
||||
flags_ &= ~HAS_CALL_OBJ;
|
||||
}
|
||||
}
|
||||
|
@ -148,13 +148,12 @@ StackFrame::stealFrameAndSlots(Value *vp, StackFrame *otherfp,
|
||||
* js_LiveFrameToFloating comment in jsiter.h.
|
||||
*/
|
||||
if (hasCallObj()) {
|
||||
JSObject &obj = callObj();
|
||||
obj.setPrivate(this);
|
||||
CallObject &obj = callObj();
|
||||
obj.setStackFrame(this);
|
||||
otherfp->flags_ &= ~HAS_CALL_OBJ;
|
||||
if (js_IsNamedLambda(fun())) {
|
||||
JSObject *env = obj.internalScopeChain();
|
||||
JS_ASSERT(env->isDeclEnv());
|
||||
env->setPrivate(this);
|
||||
DeclEnvObject &env = obj.enclosingScope().asDeclEnv();
|
||||
env.setStackFrame(this);
|
||||
}
|
||||
}
|
||||
if (hasArgsObj()) {
|
||||
|
@ -73,6 +73,7 @@ class FrameRegsIter;
|
||||
class AllFramesIter;
|
||||
|
||||
class ArgumentsObject;
|
||||
class StaticBlockObject;
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
typedef js::mjit::CallSite JSInlinedSite;
|
||||
@ -369,7 +370,7 @@ class StackFrame
|
||||
|
||||
/* Lazily initialized */
|
||||
Value rval_; /* return value of the frame */
|
||||
JSObject *blockChain_; /* innermost let block */
|
||||
StaticBlockObject *blockChain_; /* innermost let block */
|
||||
jsbytecode *prevpc_; /* pc of previous frame*/
|
||||
JSInlinedSite *prevInline_; /* inlined site in previous frame */
|
||||
void *hookData_; /* closure returned by call hook */
|
||||
@ -848,16 +849,16 @@ class StackFrame
|
||||
return (flags_ & HAS_BLOCKCHAIN) && blockChain_;
|
||||
}
|
||||
|
||||
JSObject *maybeBlockChain() {
|
||||
StaticBlockObject *maybeBlockChain() {
|
||||
return (flags_ & HAS_BLOCKCHAIN) ? blockChain_ : NULL;
|
||||
}
|
||||
|
||||
JSObject &blockChain() const {
|
||||
StaticBlockObject &blockChain() const {
|
||||
JS_ASSERT(hasBlockChain());
|
||||
return *blockChain_;
|
||||
}
|
||||
|
||||
void setBlockChain(JSObject *obj) {
|
||||
void setBlockChain(StaticBlockObject *obj) {
|
||||
flags_ |= HAS_BLOCKCHAIN;
|
||||
blockChain_ = obj;
|
||||
}
|
||||
|
@ -43,11 +43,11 @@
|
||||
|
||||
#include "StringObject.h"
|
||||
|
||||
inline js::StringObject *
|
||||
inline js::StringObject &
|
||||
JSObject::asString()
|
||||
{
|
||||
JS_ASSERT(isString());
|
||||
return static_cast<js::StringObject *>(const_cast<JSObject *>(this));
|
||||
return *static_cast<js::StringObject *>(this);
|
||||
}
|
||||
|
||||
namespace js {
|
||||
@ -82,10 +82,10 @@ StringObject::create(JSContext *cx, JSString *str)
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, &StringClass);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
StringObject *strobj = obj->asString();
|
||||
if (!strobj->init(cx, str))
|
||||
StringObject &strobj = obj->asString();
|
||||
if (!strobj.init(cx, str))
|
||||
return NULL;
|
||||
return strobj;
|
||||
return &strobj;
|
||||
}
|
||||
|
||||
inline StringObject *
|
||||
@ -94,10 +94,10 @@ StringObject::createWithProto(JSContext *cx, JSString *str, JSObject &proto)
|
||||
JSObject *obj = NewObjectWithClassProto(cx, &StringClass, &proto, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
StringObject *strobj = obj->asString();
|
||||
if (!strobj->init(cx, str))
|
||||
StringObject &strobj = obj->asString();
|
||||
if (!strobj.init(cx, str))
|
||||
return NULL;
|
||||
return strobj;
|
||||
return &strobj;
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
@ -48,7 +48,7 @@
|
||||
|
||||
namespace js {
|
||||
|
||||
class StringObject : public ::JSObject
|
||||
class StringObject : public JSObject
|
||||
{
|
||||
static const uintN PRIMITIVE_THIS_SLOT = 0;
|
||||
static const uintN LENGTH_SLOT = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user