mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 462300 - Add support for self-hosting syntax and operations (r=luke)
--HG-- extra : rebase_source : 82852ba6bf800e4d87f64b178a963e71323af391
This commit is contained in:
parent
1c3aa14b84
commit
dec43a91e0
@ -1209,7 +1209,7 @@ TryConvertToGname(BytecodeEmitter *bce, ParseNode *pn, JSOp *op)
|
||||
static bool
|
||||
BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
{
|
||||
JS_ASSERT(pn->isKind(PNK_NAME));
|
||||
JS_ASSERT(pn->isKind(PNK_NAME) || pn->isKind(PNK_INTRINSICNAME));
|
||||
|
||||
/* Don't attempt if 'pn' is already bound or deoptimized or a nop. */
|
||||
JSOp op = pn->getOp();
|
||||
@ -1746,6 +1746,9 @@ EmitNameOp(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool callContext)
|
||||
case JSOP_NAME:
|
||||
op = JSOP_CALLNAME;
|
||||
break;
|
||||
case JSOP_INTRINSICNAME:
|
||||
op = JSOP_CALLINTRINSIC;
|
||||
break;
|
||||
case JSOP_GETGNAME:
|
||||
op = JSOP_CALLGNAME;
|
||||
break;
|
||||
@ -5332,12 +5335,54 @@ EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
||||
* value required for calls (which non-strict mode functions
|
||||
* will box into the global object).
|
||||
*/
|
||||
uint32_t argc = pn->pn_count - 1;
|
||||
bool emitArgs = true;
|
||||
ParseNode *pn2 = pn->pn_head;
|
||||
switch (pn2->getKind()) {
|
||||
case PNK_NAME:
|
||||
if (!EmitNameOp(cx, bce, pn2, callop))
|
||||
return false;
|
||||
break;
|
||||
case PNK_INTRINSICNAME:
|
||||
if (pn2->atom() == cx->runtime->atomState._CallFunctionAtom)
|
||||
{
|
||||
/*
|
||||
* Special-casing of %_CallFunction to emit bytecode that directly
|
||||
* invokes the callee with the correct |this| object and arguments.
|
||||
* The call %_CallFunction(receiver, ...args, fun) thus becomes:
|
||||
* - emit lookup for fun
|
||||
* - emit lookup for receiver
|
||||
* - emit lookups for ...args
|
||||
*
|
||||
* argc is set to the amount of actually emitted args and the
|
||||
* emitting of args below is disabled by setting emitArgs to false.
|
||||
*/
|
||||
if (pn->pn_count < 3) {
|
||||
bce->reportError(pn, JSMSG_MORE_ARGS_NEEDED, "%_CallFunction", "1", "s");
|
||||
return false;
|
||||
}
|
||||
ParseNode *funNode = pn2->pn_next;
|
||||
while (funNode->pn_next)
|
||||
funNode = funNode->pn_next;
|
||||
if (!EmitTree(cx, bce, funNode))
|
||||
return false;
|
||||
ParseNode *receiver = pn2->pn_next;
|
||||
if (!EmitTree(cx, bce, receiver))
|
||||
return false;
|
||||
bool oldInForInit = bce->inForInit;
|
||||
bce->inForInit = false;
|
||||
for (ParseNode *argpn = receiver->pn_next; argpn != funNode; argpn = argpn->pn_next) {
|
||||
if (!EmitTree(cx, bce, argpn))
|
||||
return false;
|
||||
}
|
||||
bce->inForInit = oldInForInit;
|
||||
argc -= 2;
|
||||
emitArgs = false;
|
||||
break;
|
||||
}
|
||||
if (!EmitNameOp(cx, bce, pn2, callop))
|
||||
return false;
|
||||
break;
|
||||
case PNK_DOT:
|
||||
if (!EmitPropOp(cx, pn2, pn2->getOp(), bce, callop))
|
||||
return false;
|
||||
@ -5364,25 +5409,23 @@ EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
||||
if (!callop && Emit1(cx, bce, JSOP_UNDEFINED) < 0)
|
||||
return false;
|
||||
|
||||
/* Remember start of callable-object bytecode for decompilation hint. */
|
||||
ptrdiff_t off = top;
|
||||
|
||||
/*
|
||||
* Emit code for each argument in order, then emit the JSOP_*CALL or
|
||||
* JSOP_NEW bytecode with a two-byte immediate telling how many args
|
||||
* were pushed on the operand stack.
|
||||
*/
|
||||
bool oldInForInit = bce->inForInit;
|
||||
bce->inForInit = false;
|
||||
for (ParseNode *pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
|
||||
if (!EmitTree(cx, bce, pn3))
|
||||
return false;
|
||||
if (emitArgs) {
|
||||
/*
|
||||
* Emit code for each argument in order, then emit the JSOP_*CALL or
|
||||
* JSOP_NEW bytecode with a two-byte immediate telling how many args
|
||||
* were pushed on the operand stack.
|
||||
*/
|
||||
bool oldInForInit = bce->inForInit;
|
||||
bce->inForInit = false;
|
||||
for (ParseNode *pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
|
||||
if (!EmitTree(cx, bce, pn3))
|
||||
return false;
|
||||
}
|
||||
bce->inForInit = oldInForInit;
|
||||
}
|
||||
bce->inForInit = oldInForInit;
|
||||
if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - off) < 0)
|
||||
if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - top) < 0)
|
||||
return false;
|
||||
|
||||
uint32_t argc = pn->pn_count - 1;
|
||||
if (Emit3(cx, bce, pn->getOp(), ARGC_HI(argc), ARGC_LO(argc)) < 0)
|
||||
return false;
|
||||
CheckTypeSet(cx, bce, pn->getOp());
|
||||
|
@ -35,7 +35,7 @@ UpvarCookie::set(JSContext *cx, unsigned newLevel, uint16_t newSlot)
|
||||
inline PropertyName *
|
||||
ParseNode::atom() const
|
||||
{
|
||||
JS_ASSERT(isKind(PNK_FUNCTION) || isKind(PNK_NAME));
|
||||
JS_ASSERT(isKind(PNK_FUNCTION) || isKind(PNK_NAME) || isKind(PNK_INTRINSICNAME));
|
||||
JSAtom *atom = isKind(PNK_FUNCTION) ? pn_funbox->function()->atom : pn_atom;
|
||||
return atom->asPropertyName();
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ enum ParseNodeKind {
|
||||
PNK_LP,
|
||||
PNK_RP,
|
||||
PNK_NAME,
|
||||
PNK_INTRINSICNAME,
|
||||
PNK_NUMBER,
|
||||
PNK_STRING,
|
||||
PNK_REGEXP,
|
||||
|
@ -117,7 +117,8 @@ Parser::Parser(JSContext *cx, const CompileOptions &options,
|
||||
sct(NULL),
|
||||
keepAtoms(cx->runtime),
|
||||
foldConstants(foldConstants),
|
||||
compileAndGo(options.compileAndGo)
|
||||
compileAndGo(options.compileAndGo),
|
||||
allowIntrinsicsCalls(options.allowIntrinsicsCalls)
|
||||
{
|
||||
cx->activeCompilations++;
|
||||
}
|
||||
@ -6497,6 +6498,30 @@ Parser::identifierName(bool afterDoubleDot)
|
||||
return node;
|
||||
}
|
||||
|
||||
ParseNode *
|
||||
Parser::intrinsicName()
|
||||
{
|
||||
JS_ASSERT(tokenStream.isCurrentTokenType(TOK_MOD));
|
||||
if (tokenStream.getToken() != TOK_NAME) {
|
||||
reportError(NULL, JSMSG_SYNTAX_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PropertyName *name = tokenStream.currentToken().name();
|
||||
if (!(name == context->runtime->atomState._CallFunctionAtom ||
|
||||
context->global()->hasIntrinsicFunction(context, name)))
|
||||
{
|
||||
reportError(NULL, JSMSG_INTRINSIC_NOT_DEFINED, JS_EncodeString(context, name));
|
||||
return NULL;
|
||||
}
|
||||
ParseNode *node = NameNode::create(PNK_INTRINSICNAME, name, this, this->tc);
|
||||
if (!node)
|
||||
return NULL;
|
||||
JS_ASSERT(tokenStream.currentToken().t_op == JSOP_NAME);
|
||||
node->setOp(JSOP_INTRINSICNAME);
|
||||
return node;
|
||||
}
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
ParseNode *
|
||||
Parser::starOrAtPropertyIdentifier(TokenKind tt)
|
||||
@ -7054,6 +7079,12 @@ Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
|
||||
case TOK_NULL:
|
||||
return new_<NullLiteral>(tokenStream.currentToken().pos);
|
||||
|
||||
case TOK_MOD:
|
||||
if (allowIntrinsicsCalls)
|
||||
return intrinsicName();
|
||||
else
|
||||
goto syntaxerror;
|
||||
|
||||
case TOK_ERROR:
|
||||
/* The scanner or one of its subroutines reported the error. */
|
||||
return NULL;
|
||||
|
@ -54,6 +54,12 @@ struct Parser : private AutoGCRooter
|
||||
/* Script can optimize name references based on scope chain. */
|
||||
const bool compileAndGo:1;
|
||||
|
||||
/*
|
||||
* Self-hosted scripts can use the special syntax %funName(..args) to call
|
||||
* internal functions.
|
||||
*/
|
||||
const bool allowIntrinsicsCalls:1;
|
||||
|
||||
public:
|
||||
Parser(JSContext *cx, const CompileOptions &options,
|
||||
const jschar *chars, size_t length, bool foldConstants);
|
||||
@ -230,6 +236,7 @@ struct Parser : private AutoGCRooter
|
||||
bool checkForFunctionNode(PropertyName *name, ParseNode *node);
|
||||
|
||||
ParseNode *identifierName(bool afterDoubleDot);
|
||||
ParseNode *intrinsicName();
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
// True if E4X syntax is allowed in the current syntactic context. Note this
|
||||
|
@ -352,3 +352,4 @@ MSG_DEF(JSMSG_FUNCTION_ARGUMENTS_AND_REST, 298, 0, JSEXN_ERR, "the 'arguments' p
|
||||
MSG_DEF(JSMSG_REST_WITH_DEFAULT, 299, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default")
|
||||
MSG_DEF(JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT, 300, 0, JSEXN_SYNTAXERR, "parameter(s) with default followed by parameter without default")
|
||||
MSG_DEF(JSMSG_YIELD_IN_DEFAULT, 301, 0, JSEXN_SYNTAXERR, "yield in default expression")
|
||||
MSG_DEF(JSMSG_INTRINSIC_NOT_DEFINED, 302, 1, JSEXN_REFERENCEERR, "no intrinsic function {0}")
|
||||
|
@ -570,6 +570,8 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
case JSOP_RETRVAL:
|
||||
case JSOP_GETGNAME:
|
||||
case JSOP_CALLGNAME:
|
||||
case JSOP_INTRINSICNAME:
|
||||
case JSOP_CALLINTRINSIC:
|
||||
case JSOP_SETGNAME:
|
||||
case JSOP_REGEXP:
|
||||
case JSOP_OBJECT:
|
||||
|
@ -5067,7 +5067,8 @@ JS::CompileOptions::CompileOptions(JSContext *cx)
|
||||
filename(NULL),
|
||||
lineno(1),
|
||||
compileAndGo(cx->hasRunOption(JSOPTION_COMPILE_N_GO)),
|
||||
noScriptRval(cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL))
|
||||
noScriptRval(cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL)),
|
||||
allowIntrinsicsCalls(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -4090,7 +4090,7 @@ struct JSClass {
|
||||
* with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
|
||||
* prevously allowed, but is now an ES5 violation and thus unsupported.
|
||||
*/
|
||||
#define JSCLASS_GLOBAL_SLOT_COUNT (JSProto_LIMIT * 3 + 23)
|
||||
#define JSCLASS_GLOBAL_SLOT_COUNT (JSProto_LIMIT * 3 + 24)
|
||||
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
|
||||
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
|
||||
#define JSCLASS_GLOBAL_FLAGS \
|
||||
@ -4962,6 +4962,7 @@ struct CompileOptions {
|
||||
unsigned lineno;
|
||||
bool compileAndGo;
|
||||
bool noScriptRval;
|
||||
bool allowIntrinsicsCalls;
|
||||
|
||||
CompileOptions(JSContext *cx);
|
||||
CompileOptions &setPrincipals(JSPrincipals *p) { principals = p; return *this; }
|
||||
@ -4973,6 +4974,7 @@ struct CompileOptions {
|
||||
}
|
||||
CompileOptions &setCompileAndGo(bool cng) { compileAndGo = cng; return *this; }
|
||||
CompileOptions &setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
|
||||
CompileOptions &setAllowIntrinsicsCalls(bool aic) { allowIntrinsicsCalls = aic; return *this; }
|
||||
};
|
||||
|
||||
extern JS_PUBLIC_API(JSScript *)
|
||||
|
@ -149,3 +149,4 @@ DEFINE_ATOM(unescape, "unescape")
|
||||
DEFINE_ATOM(uneval, "uneval")
|
||||
DEFINE_ATOM(unwatch, "unwatch")
|
||||
DEFINE_ATOM(watch, "watch")
|
||||
DEFINE_ATOM(_CallFunction, "_CallFunction")
|
||||
|
@ -3394,11 +3394,13 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
}
|
||||
|
||||
case JSOP_NAME:
|
||||
case JSOP_CALLNAME: {
|
||||
case JSOP_INTRINSICNAME:
|
||||
case JSOP_CALLNAME:
|
||||
case JSOP_CALLINTRINSIC: {
|
||||
TypeSet *seen = bytecodeTypes(pc);
|
||||
addTypeBarrier(cx, pc, seen, Type::UnknownType());
|
||||
seen->addSubset(cx, &pushed[0]);
|
||||
if (op == JSOP_CALLNAME)
|
||||
if (op == JSOP_CALLNAME || op == JSOP_CALLINTRINSIC)
|
||||
pushed[0].addPropagateThis(cx, script, pc, Type::UnknownType());
|
||||
break;
|
||||
}
|
||||
|
@ -1418,8 +1418,6 @@ ADD_EMPTY_CASE(JSOP_NOP)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED1)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED2)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED3)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED8)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED9)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED10)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED11)
|
||||
ADD_EMPTY_CASE(JSOP_UNUSED12)
|
||||
@ -2524,6 +2522,19 @@ BEGIN_CASE(JSOP_CALLNAME)
|
||||
}
|
||||
END_CASE(JSOP_NAME)
|
||||
|
||||
BEGIN_CASE(JSOP_INTRINSICNAME)
|
||||
BEGIN_CASE(JSOP_CALLINTRINSIC)
|
||||
{
|
||||
RootedValue &rval = rootValue0;
|
||||
|
||||
if (!IntrinsicNameOperation(cx, script, regs.pc, rval.address()))
|
||||
goto error;
|
||||
|
||||
PUSH_COPY(rval);
|
||||
TypeScript::Monitor(cx, script, regs.pc, rval);
|
||||
}
|
||||
END_CASE(JSOP_INTRINSICNAME)
|
||||
|
||||
BEGIN_CASE(JSOP_UINT16)
|
||||
PUSH_INT32((int32_t) GET_UINT16(regs.pc));
|
||||
END_CASE(JSOP_UINT16)
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "jsfuninlines.h"
|
||||
#include "jsinferinlines.h"
|
||||
#include "jsopcodeinlines.h"
|
||||
#include "jspropertycacheinlines.h"
|
||||
#include "jstypedarrayinlines.h"
|
||||
|
||||
@ -359,6 +360,17 @@ SetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, const Val
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IntrinsicNameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, Value *vp)
|
||||
{
|
||||
JSOp op = JSOp(*pc);
|
||||
RootedPropertyName name(cx);
|
||||
name = GetNameFromBytecode(cx, script, pc, op);
|
||||
JSFunction *fun = cx->global()->getIntrinsicFunction(cx, name);
|
||||
vp->setObject(*fun);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
NameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, Value *vp)
|
||||
{
|
||||
|
@ -350,9 +350,17 @@ OPDEF(JSOP_DECALIASEDVAR, 140,"decaliasedvar",NULL, 10, 0, 1, 15, JOF_SCOPEC
|
||||
OPDEF(JSOP_ALIASEDVARINC, 141,"aliasedvarinc",NULL, 10, 0, 1, 15, JOF_SCOPECOORD|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_ALIASEDVARDEC, 142,"aliasedvardec",NULL, 10, 0, 1, 15, JOF_SCOPECOORD|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
|
||||
|
||||
/*
|
||||
* Intrinsic names have the syntax %name and can only be used when the
|
||||
* CompileOptions flag "allowIntrinsicsCalls" is set.
|
||||
*
|
||||
* They are used to access intrinsic functions the runtime doesn't give
|
||||
* client JS code access to from self-hosted code.
|
||||
*/
|
||||
OPDEF(JSOP_INTRINSICNAME, 143, "intrinsicname", NULL, 5, 0, 1, 19, JOF_ATOM|JOF_NAME|JOF_TYPESET)
|
||||
OPDEF(JSOP_CALLINTRINSIC, 144, "callintrinsic", NULL, 5, 0, 1, 19, JOF_ATOM|JOF_NAME|JOF_TYPESET)
|
||||
|
||||
/* Unused. */
|
||||
OPDEF(JSOP_UNUSED8, 143,"unused8", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED9, 144,"unused9", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED10, 145,"unused10", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED11, 146,"unused11", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED12, 147,"unused12", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
@ -4,6 +4,9 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef jsopcodeinlines_h__
|
||||
#define jsopcodeinlines_h__
|
||||
|
||||
#include "jsautooplen.h"
|
||||
|
||||
#include "frontend/BytecodeEmitter.h"
|
||||
@ -118,3 +121,5 @@ public:
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* jsopcodeinlines_h__ */
|
||||
|
@ -2645,6 +2645,15 @@ mjit::Compiler::generateMethod()
|
||||
}
|
||||
END_CASE(JSOP_NAME)
|
||||
|
||||
BEGIN_CASE(JSOP_INTRINSICNAME)
|
||||
BEGIN_CASE(JSOP_CALLINTRINSIC)
|
||||
{
|
||||
PropertyName *name = script->getName(GET_UINT32_INDEX(PC));
|
||||
jsop_intrinsicname(name, knownPushedType(0));
|
||||
frame.extra(frame.peek(-1)).name = name;
|
||||
}
|
||||
END_CASE(JSOP_INTRINSICNAME)
|
||||
|
||||
BEGIN_CASE(JSOP_IMPLICITTHIS)
|
||||
{
|
||||
prepareStubCall(Uses(0));
|
||||
@ -5552,6 +5561,13 @@ mjit::Compiler::jsop_setprop(PropertyName *name, bool popGuaranteed)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
mjit::Compiler::jsop_intrinsicname(PropertyName *name, JSValueType type)
|
||||
{
|
||||
JSFunction *fun = cx->global().get()->getIntrinsicFunction(cx, name);
|
||||
frame.push(ObjectValue(*fun));
|
||||
}
|
||||
|
||||
void
|
||||
mjit::Compiler::jsop_name(PropertyName *name, JSValueType type)
|
||||
{
|
||||
|
@ -653,6 +653,7 @@ private:
|
||||
bool jsop_setprop(PropertyName *name, bool popGuaranteed);
|
||||
void jsop_setprop_slow(PropertyName *name);
|
||||
bool jsop_instanceof();
|
||||
void jsop_intrinsicname(PropertyName *name, JSValueType type);
|
||||
void jsop_name(PropertyName *name, JSValueType type);
|
||||
bool jsop_xname(PropertyName *name);
|
||||
void enterBlock(StaticBlockObject *block);
|
||||
|
@ -213,6 +213,13 @@ GlobalObject::setProtoGetter(JSFunction *protoGetter)
|
||||
setSlot(PROTO_GETTER, ObjectValue(*protoGetter));
|
||||
}
|
||||
|
||||
void
|
||||
GlobalObject::setIntrinsicsHolder(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(getSlotRef(INTRINSICS).isUndefined());
|
||||
setSlot(INTRINSICS, ObjectValue(*obj));
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif
|
||||
|
@ -173,6 +173,10 @@ ProtoSetter(JSContext *cx, unsigned argc, Value *vp)
|
||||
return CallNonGenericMethod(cx, TestProtoSetterThis, ProtoSetterImpl, args);
|
||||
}
|
||||
|
||||
JSFunctionSpec intrinsic_functions[] = {
|
||||
JS_FN("ThrowTypeError", ThrowTypeError, 0,0),
|
||||
JS_FS_END
|
||||
};
|
||||
JSObject *
|
||||
GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
|
||||
{
|
||||
@ -369,14 +373,20 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
|
||||
self->setOriginalEval(evalobj);
|
||||
|
||||
/* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
|
||||
RootedFunction throwTypeError(cx);
|
||||
throwTypeError = js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, self, NULL);
|
||||
RootedFunction throwTypeError(cx, js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, self, NULL));
|
||||
if (!throwTypeError)
|
||||
return NULL;
|
||||
if (!throwTypeError->preventExtensions(cx))
|
||||
return NULL;
|
||||
self->setThrowTypeError(throwTypeError);
|
||||
|
||||
RootedObject intrinsicsHolder(cx, JS_NewObject(cx, NULL, NULL, self));
|
||||
if (!intrinsicsHolder)
|
||||
return NULL;
|
||||
self->setIntrinsicsHolder(intrinsicsHolder);
|
||||
if (!JS_DefineFunctions(cx, intrinsicsHolder, intrinsic_functions))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* The global object should have |Object.prototype| as its [[Prototype]].
|
||||
* Eventually we'd like to have standard classes be there from the start,
|
||||
@ -482,6 +492,7 @@ GlobalObject::clear(JSContext *cx)
|
||||
setSlot(EVAL, UndefinedValue());
|
||||
setSlot(CREATE_DATAVIEW_FOR_THIS, UndefinedValue());
|
||||
setSlot(THROWTYPEERROR, UndefinedValue());
|
||||
setSlot(INTRINSICS, UndefinedValue());
|
||||
setSlot(PROTO_GETTER, UndefinedValue());
|
||||
|
||||
/*
|
||||
|
@ -100,9 +100,10 @@ class GlobalObject : public JSObject
|
||||
static const unsigned RUNTIME_CODEGEN_ENABLED = FUNCTION_NS + 1;
|
||||
static const unsigned FLAGS = RUNTIME_CODEGEN_ENABLED + 1;
|
||||
static const unsigned DEBUGGERS = FLAGS + 1;
|
||||
static const unsigned INTRINSICS = DEBUGGERS + 1;
|
||||
|
||||
/* Total reserved-slot count for global objects. */
|
||||
static const unsigned RESERVED_SLOTS = DEBUGGERS + 1;
|
||||
static const unsigned RESERVED_SLOTS = INTRINSICS + 1;
|
||||
|
||||
void staticAsserts() {
|
||||
/*
|
||||
@ -135,6 +136,8 @@ class GlobalObject : public JSObject
|
||||
inline void setOriginalEval(JSObject *evalobj);
|
||||
inline void setProtoGetter(JSFunction *protoGetter);
|
||||
|
||||
inline void setIntrinsicsHolder(JSObject *obj);
|
||||
|
||||
Value getConstructor(JSProtoKey key) const {
|
||||
JS_ASSERT(key <= JSProto_LIMIT);
|
||||
return getSlot(key);
|
||||
@ -360,6 +363,20 @@ class GlobalObject : public JSObject
|
||||
return &self->getPrototype(JSProto_DataView).toObject();
|
||||
}
|
||||
|
||||
bool hasIntrinsicFunction(JSContext *cx, PropertyName *name) {
|
||||
RootedObject holder(cx, &getSlotRef(INTRINSICS).toObject());
|
||||
Value fun = NullValue();
|
||||
return HasDataProperty(cx, holder, NameToId(name), &fun);
|
||||
}
|
||||
|
||||
JSFunction *getIntrinsicFunction(JSContext *cx, PropertyName *name) {
|
||||
RootedObject holder(cx, &getSlotRef(INTRINSICS).toObject());
|
||||
Value fun = NullValue();
|
||||
DebugOnly<bool> ok = HasDataProperty(cx, holder, NameToId(name), &fun);
|
||||
JS_ASSERT(ok);
|
||||
return fun.toObject().toFunction();
|
||||
}
|
||||
|
||||
inline RegExpStatics *getRegExpStatics() const;
|
||||
|
||||
JSObject *getThrowTypeError() const {
|
||||
|
@ -25,7 +25,7 @@ namespace js {
|
||||
* and saved versions. If deserialization fails, the data should be
|
||||
* invalidated if possible.
|
||||
*/
|
||||
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 124);
|
||||
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 125);
|
||||
|
||||
class XDRBuffer {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user