зеркало из https://github.com/mozilla/gecko-dev.git
Incrementals
This commit is contained in:
Родитель
427dffcdd5
Коммит
c5247a541f
|
@ -97,8 +97,6 @@ const bool showTokens = false;
|
|||
#define INTERPRET_INPUT 1
|
||||
//#define SHOW_ICODE 1
|
||||
|
||||
MetaData::GlobalObject glob(world);
|
||||
MetaData::Environment env(new MetaData::SystemFrame(), &glob);
|
||||
MetaData::JS2Metadata *metadata;
|
||||
|
||||
|
||||
|
@ -140,10 +138,9 @@ static int readEvalPrint(FILE *in)
|
|||
}
|
||||
|
||||
metadata->setCurrentParser(&p); // for error reporting
|
||||
MetaData::Context cxt;
|
||||
|
||||
metadata->ValidateStmtList(&cxt, &env, parsedStatements);
|
||||
metadata->EvalStmtList(&env, MetaData::RunPhase, parsedStatements);
|
||||
metadata->ValidateStmtList(parsedStatements);
|
||||
metadata->EvalStmtList(MetaData::RunPhase, parsedStatements);
|
||||
|
||||
}
|
||||
clear(buffer);
|
||||
|
|
|
@ -59,7 +59,8 @@ namespace JavaScript
|
|||
userException,
|
||||
definitionError,
|
||||
badValueError,
|
||||
compileExpressionError
|
||||
compileExpressionError,
|
||||
propertyAccessError
|
||||
};
|
||||
|
||||
Kind kind; // The exception's kind
|
||||
|
|
|
@ -69,20 +69,21 @@ namespace JavaScript {
|
|||
namespace MetaData {
|
||||
|
||||
|
||||
JSRuntime *gMonkeyRuntime;
|
||||
JSContext *gMonkeyContext;
|
||||
JSObject *gMonkeyGlobalObject;
|
||||
JSClass gMonkeyGlobalClass = { "MyClass", 0, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
|
||||
JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub };
|
||||
|
||||
JSClass gMonkeyMultinameClass =
|
||||
{ "Multiname", 0, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
|
||||
JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub };
|
||||
|
||||
// forward ref.
|
||||
// forward refs.
|
||||
static void Multiname_finalize(JSContext *cx, JSObject *obj);
|
||||
static void LexicalReference_finalize(JSContext *cx, JSObject *obj);
|
||||
static void Namespace_finalize(JSContext *cx, JSObject *obj);
|
||||
|
||||
JSClass gMonkeyMultinameClass =
|
||||
{ "Multiname", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
|
||||
JS_ResolveStub, JS_ConvertStub, Multiname_finalize };
|
||||
|
||||
|
||||
JSClass gMonkeyLexicalReferenceClass =
|
||||
{ "LexicalReference", JSCLASS_HAS_PRIVATE,
|
||||
|
@ -90,6 +91,12 @@ namespace MetaData {
|
|||
JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
|
||||
JS_ResolveStub, JS_ConvertStub, LexicalReference_finalize };
|
||||
|
||||
JSClass gMonkeyNamespaceClass =
|
||||
{ "Namespace", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
|
||||
JS_ResolveStub, JS_ConvertStub, Namespace_finalize };
|
||||
|
||||
// member functions at global scope
|
||||
JSFunctionSpec jsfGlobal [] =
|
||||
{
|
||||
|
@ -112,7 +119,7 @@ namespace MetaData {
|
|||
static JSBool
|
||||
LexicalReference_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
ExecutionState *eState = static_cast<ExecutionState *>(JS_GetContextPrivate(cx));
|
||||
JS2Metadata *meta = static_cast<JS2Metadata *>(JS_GetContextPrivate(cx));
|
||||
|
||||
ASSERT(argc == 2);
|
||||
ASSERT(JSVAL_IS_BOOLEAN(argv[0])); // the 'strict' flag (XXX what's that for?)
|
||||
|
@ -122,7 +129,7 @@ namespace MetaData {
|
|||
ASSERT(OBJ_GET_CLASS(cx, multiNameObj) == &gMonkeyMultinameClass);
|
||||
Multiname *mName = static_cast<Multiname *>(JS_GetPrivate(cx, multiNameObj));
|
||||
|
||||
if (!JS_SetPrivate(cx, obj, new LexicalReference(mName, eState->env, (JSVAL_TO_BOOLEAN(argv[0])) == JS_TRUE) ))
|
||||
if (!JS_SetPrivate(cx, obj, new LexicalReference(mName, &meta->env, (JSVAL_TO_BOOLEAN(argv[0])) == JS_TRUE) ))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_TRUE;
|
||||
|
@ -142,10 +149,10 @@ namespace MetaData {
|
|||
readLexicalReference(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyLexicalReferenceClass);
|
||||
ExecutionState *eState = static_cast<ExecutionState *>(JS_GetContextPrivate(cx));
|
||||
JS2Metadata *meta = static_cast<JS2Metadata *>(JS_GetContextPrivate(cx));
|
||||
LexicalReference *lRef = static_cast<LexicalReference *>(JS_GetPrivate(cx, obj));
|
||||
|
||||
eState->env->lexicalRead(eState, lRef->variableMultiname, RunPhase);
|
||||
meta->env.lexicalRead(meta, lRef->variableMultiname, RunPhase);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -154,7 +161,7 @@ namespace MetaData {
|
|||
writeLexicalReference(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyLexicalReferenceClass);
|
||||
ExecutionState *eState = static_cast<ExecutionState *>(JS_GetContextPrivate(cx));
|
||||
JS2Metadata *meta = static_cast<JS2Metadata *>(JS_GetContextPrivate(cx));
|
||||
LexicalReference *lRef = static_cast<LexicalReference *>(JS_GetPrivate(cx, obj));
|
||||
|
||||
|
||||
|
@ -179,35 +186,67 @@ namespace MetaData {
|
|||
static JSBool
|
||||
Multiname_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JS2Metadata *meta = static_cast<JS2Metadata *>(JS_GetContextPrivate(cx));
|
||||
|
||||
ASSERT(argc >= 1); // could be just the base name
|
||||
ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyMultinameClass);
|
||||
|
||||
ASSERT(JSVAL_IS_STRING(argv[0]));
|
||||
JSString *str = JSVAL_TO_STRING(argv[0]);
|
||||
|
||||
// XXX use reserved slots instead
|
||||
if (!JS_SetProperty(cx, obj, "name", &argv[0]))
|
||||
Multiname *mName = new Multiname(meta->world.identifiers[String(JS_GetStringChars(str), JS_GetStringLength(str))]);
|
||||
if (!JS_SetPrivate(cx, obj, mName))
|
||||
return JS_FALSE;
|
||||
|
||||
jsval qualifierVal = JSVAL_NULL;
|
||||
if (argc > 1) {
|
||||
JSObject *qualArray = JS_NewArrayObject(cx, argc - 1, &argv[1]);
|
||||
if (!qualArray)
|
||||
return JS_FALSE;
|
||||
qualifierVal = OBJECT_TO_JSVAL(qualArray);
|
||||
for (uintN i = 1; i < argc; i++) {
|
||||
ASSERT(JSVAL_IS_OBJECT(argv[i]));
|
||||
JSObject *obj = JSVAL_TO_OBJECT(argv[i]);
|
||||
ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyNamespaceClass);
|
||||
Namespace *ns = static_cast<Namespace *>(JS_GetPrivate(cx, obj));
|
||||
mName->addNamespace(ns);
|
||||
}
|
||||
if (!JS_SetProperty(cx, obj, "qualifiers", &qualifierVal))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// member functions in a Multiname
|
||||
JSFunctionSpec jsfMultiname [] =
|
||||
// finalize a Multiname - called by Monkey gc
|
||||
static void
|
||||
Multiname_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
{ 0 }
|
||||
};
|
||||
ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyMultinameClass);
|
||||
Multiname *mName = static_cast<Multiname *>(JS_GetPrivate(cx, obj));
|
||||
if (mName) delete mName;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Namespace
|
||||
******************************************************************************/
|
||||
|
||||
// finish constructing a Namespace
|
||||
static JSBool
|
||||
Namespace_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JS2Metadata *meta = static_cast<JS2Metadata *>(JS_GetContextPrivate(cx));
|
||||
ASSERT(argc == 1);
|
||||
ASSERT(JSVAL_IS_STRING(argv[0]));
|
||||
JSString *str = JSVAL_TO_STRING(argv[0]);
|
||||
|
||||
Namespace *ns = new Namespace(meta->world.identifiers[String(JS_GetStringChars(str), JS_GetStringLength(str))]);
|
||||
if (!JS_SetPrivate(cx, obj, ns))
|
||||
return JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// finalize a Namespace - called by Monkey gc
|
||||
static void
|
||||
Namespace_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyNamespaceClass);
|
||||
Namespace *ns = static_cast<Namespace *>(JS_GetPrivate(cx, obj));
|
||||
if (ns) delete ns;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -216,45 +255,50 @@ namespace MetaData {
|
|||
// Initialize the SpiderMonkey engine
|
||||
void JS2Metadata::initializeMonkey()
|
||||
{
|
||||
gMonkeyRuntime = JS_NewRuntime( 1000000L );
|
||||
if (!gMonkeyRuntime)
|
||||
monkeyRuntime = JS_NewRuntime(1000000L);
|
||||
if (!monkeyRuntime)
|
||||
throw "Monkey start failure";
|
||||
|
||||
gMonkeyContext = JS_NewContext( gMonkeyRuntime, 8192 );
|
||||
if (!gMonkeyContext)
|
||||
monkeyContext = JS_NewContext(monkeyRuntime, 8192);
|
||||
if (!monkeyContext)
|
||||
throw "Monkey start failure";
|
||||
|
||||
|
||||
gMonkeyGlobalObject = JS_NewObject(gMonkeyContext, &gMonkeyGlobalClass, NULL, NULL);
|
||||
if (!gMonkeyGlobalObject)
|
||||
monkeyGlobalObject = JS_NewObject(monkeyContext, &gMonkeyGlobalClass, NULL, NULL);
|
||||
if (!monkeyGlobalObject)
|
||||
throw "Monkey start failure";
|
||||
|
||||
JS_SetErrorReporter(gMonkeyContext, MonkeyError);
|
||||
JS_SetErrorReporter(monkeyContext, MonkeyError);
|
||||
|
||||
JS_InitStandardClasses(gMonkeyContext, gMonkeyGlobalObject);
|
||||
if (!JS_InitStandardClasses(monkeyContext, monkeyGlobalObject))
|
||||
throw "Monkey start failure";
|
||||
|
||||
JS_InitClass(gMonkeyContext, gMonkeyGlobalObject, NULL,
|
||||
JS_InitClass(monkeyContext, monkeyGlobalObject, NULL,
|
||||
&gMonkeyLexicalReferenceClass, LexicalReference_constructor, 0,
|
||||
NULL, jsfLexicalReference, NULL, NULL);
|
||||
|
||||
JS_InitClass(gMonkeyContext, gMonkeyGlobalObject, NULL,
|
||||
JS_InitClass(monkeyContext, monkeyGlobalObject, NULL,
|
||||
&gMonkeyMultinameClass, Multiname_constructor, 0,
|
||||
NULL, jsfMultiname, NULL, NULL);
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
JS_DefineFunctions(gMonkeyContext, gMonkeyGlobalObject, jsfGlobal);
|
||||
JS_InitClass(monkeyContext, monkeyGlobalObject, NULL,
|
||||
&gMonkeyNamespaceClass, Namespace_constructor, 0,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
if (!JS_DefineFunctions(monkeyContext, monkeyGlobalObject, jsfGlobal))
|
||||
throw "Monkey start failure";
|
||||
}
|
||||
|
||||
// Execute a JS string against the given environment
|
||||
// Errors are thrown back to C++ by the error handler
|
||||
jsval JS2Metadata::execute(String *str, Environment *env, JS2Metadata *meta, size_t pos)
|
||||
jsval JS2Metadata::execute(String *str, size_t pos)
|
||||
{
|
||||
jsval retval;
|
||||
|
||||
ExecutionState eState(gMonkeyContext, env, meta, pos);
|
||||
JS_SetContextPrivate(gMonkeyContext, &eState);
|
||||
errorPos = pos;
|
||||
JS_SetContextPrivate(monkeyContext, this);
|
||||
|
||||
JS_EvaluateUCScript(gMonkeyContext, gMonkeyGlobalObject, str->c_str(), str->length(), "file", 1, &retval);
|
||||
JS_EvaluateUCScript(monkeyContext, monkeyGlobalObject, str->c_str(), str->length(), "file", 1, &retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -61,6 +61,15 @@ namespace MetaData {
|
|||
/*
|
||||
* Validate the linked list of statement nodes beginning at 'p'
|
||||
*/
|
||||
void JS2Metadata::ValidateStmtList(StmtNode *p) {
|
||||
cxt.openNamespaces.clear();
|
||||
cxt.openNamespaces.push_back(publicNamespace);
|
||||
while (p) {
|
||||
ValidateStmt(&cxt, &env, p);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
void JS2Metadata::ValidateStmtList(Context *cxt, Environment *env, StmtNode *p) {
|
||||
while (p) {
|
||||
ValidateStmt(cxt, env, p);
|
||||
|
@ -92,10 +101,10 @@ namespace MetaData {
|
|||
Attribute *attr = NULL;
|
||||
VariableStmtNode *vs = checked_cast<VariableStmtNode *>(p);
|
||||
|
||||
ValidateAttributeExpression(cxt, env, vs->attributes);
|
||||
if (vs->attributes)
|
||||
if (vs->attributes) {
|
||||
ValidateAttributeExpression(cxt, env, vs->attributes);
|
||||
attr = EvalAttributeExpression(env, CompilePhase, vs->attributes);
|
||||
|
||||
}
|
||||
|
||||
VariableBinding *v = vs->bindings;
|
||||
Frame *regionalFrame = env->getRegionalFrame();
|
||||
|
@ -130,10 +139,10 @@ namespace MetaData {
|
|||
/*
|
||||
* Evaluate the linked list of statement nodes beginning at 'p'
|
||||
*/
|
||||
jsval JS2Metadata::EvalStmtList(Environment *env, Phase phase, StmtNode *p) {
|
||||
jsval JS2Metadata::EvalStmtList(Phase phase, StmtNode *p) {
|
||||
jsval retval = JSVAL_VOID;
|
||||
while (p) {
|
||||
retval = EvalStmt(env, phase, p);
|
||||
retval = EvalStmt(&env, phase, p);
|
||||
p = p->next;
|
||||
}
|
||||
return retval;
|
||||
|
@ -150,7 +159,7 @@ namespace MetaData {
|
|||
case StmtNode::group:
|
||||
{
|
||||
BlockStmtNode *b = checked_cast<BlockStmtNode *>(p);
|
||||
retval = EvalStmtList(env, phase, b->statements);
|
||||
retval = EvalStmtList(phase, b->statements);
|
||||
}
|
||||
break;
|
||||
case StmtNode::label:
|
||||
|
@ -438,9 +447,10 @@ namespace MetaData {
|
|||
jsval JS2Metadata::EvalExpression(Environment *env, Phase phase, ExprNode *p)
|
||||
{
|
||||
String s;
|
||||
EvalExprNode(env, phase, p, s);
|
||||
if (EvalExprNode(env, phase, p, s))
|
||||
s += ".readReference()";
|
||||
try {
|
||||
return execute(&s, env, this, p->pos);
|
||||
return execute(&s, p->pos);
|
||||
}
|
||||
catch (const char *err) {
|
||||
reportError(Exception::internalError, err, p->pos);
|
||||
|
@ -495,10 +505,10 @@ namespace MetaData {
|
|||
{
|
||||
if (phase == CompilePhase) reportError(Exception::compileExpressionError, "Inappropriate compile time expression", p->pos);
|
||||
UnaryExprNode *u = checked_cast<UnaryExprNode *>(p);
|
||||
// rather than inserting "(r = , a = readRef(), r.writeRef(a + 1), a)" with
|
||||
// all the attendant performance overhead and temp. handling issues.
|
||||
if (!EvalExprNode(env, phase, u->op, s))
|
||||
ASSERT(false); // not an lvalue
|
||||
// rather than inserting "(r = , a = readRef(), r.writeRef(a + 1), a)" with
|
||||
// all the attendant performance overhead and temp. handling issues.
|
||||
s += ".postIncrement()";
|
||||
returningRef = true;
|
||||
}
|
||||
|
@ -512,11 +522,14 @@ namespace MetaData {
|
|||
case ExprNode::identifier:
|
||||
{
|
||||
IdentifierExprNode *i = checked_cast<IdentifierExprNode *>(p);
|
||||
s += "new LexicalReference(" + (i->cxt->strict) ? "true, " : "false, ";
|
||||
s += "new LexicalReference(";
|
||||
s += (i->cxt->strict) ? "true, " : "false, ";
|
||||
s += "new Multiname(\"" + i->name + "\"";
|
||||
for (NamespaceListIterator nli = i->cxt->openNamespaces.begin(), end = i->cxt->openNamespaces.end();
|
||||
(nli != end); nli++) {
|
||||
s += ", " + (*nli)->name;
|
||||
s += ", new Namespace(\""
|
||||
s += (*nli)->name;
|
||||
s += "\")";
|
||||
}
|
||||
s += "))";
|
||||
returningRef = true;
|
||||
|
@ -584,32 +597,27 @@ namespace MetaData {
|
|||
return JSVAL_VOID;
|
||||
}
|
||||
|
||||
// Slightly varies from spec. - the multiname is actually the list of
|
||||
// qualifiers to apply to the name
|
||||
jsval Environment::lexicalRead(ExecutionState *eState, Multiname *multiname, Phase phase)
|
||||
// Read the value of a lexical reference - it's an error if that reference
|
||||
// doesn't have a binding somewhere
|
||||
jsval Environment::lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase)
|
||||
{
|
||||
LookupKind lookup(true, findThis(false));
|
||||
Frame *pf = firstFrame;
|
||||
while (pf) {
|
||||
jsval rval;
|
||||
if (readProperty(eState, pf, multiname, &lookup, phase, &rval))
|
||||
// have to wrap the frame in a Monkey object in order
|
||||
// to have readProperty handle it...
|
||||
if (meta->readProperty(pf, multiname, &lookup, phase, &rval))
|
||||
return rval;
|
||||
|
||||
pf = pf->nextFrame;
|
||||
}
|
||||
eState->meta->reportError(Exception::referenceError, "{0} is undefined", eState->pos, multiname->name);
|
||||
meta->reportError(Exception::referenceError, "{0} is undefined", meta->errorPos, multiname->name);
|
||||
return JSVAL_VOID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Environment::readProperty(ExecutionState *eState, jsval container, Multiname *multinameVal, LookupKind *lookupKind, Phase phase, jsval *rval)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
*
|
||||
* Context
|
||||
|
@ -620,6 +628,21 @@ namespace MetaData {
|
|||
{
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
*
|
||||
* Multiname
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
// return true if the given namespace is on the namespace list
|
||||
bool Multiname::onList(Namespace *nameSpace)
|
||||
{
|
||||
for (NamespaceListIterator n = nsList.begin(), end = nsList.end(); (n != end); n++) {
|
||||
if (*n == nameSpace)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
*
|
||||
|
@ -679,7 +702,10 @@ namespace MetaData {
|
|||
}
|
||||
|
||||
JS2Metadata::JS2Metadata(World &world) :
|
||||
publicNamespace(new Namespace(world.identifiers["public"]))
|
||||
world(world),
|
||||
publicNamespace(new Namespace(world.identifiers["public"])),
|
||||
glob(world),
|
||||
env(new MetaData::SystemFrame(), &glob)
|
||||
{
|
||||
initializeMonkey();
|
||||
}
|
||||
|
@ -701,6 +727,8 @@ namespace MetaData {
|
|||
else
|
||||
return stringClass;
|
||||
}
|
||||
ASSERT(JSVAL_IS_OBJECT(obj));
|
||||
return NULL;
|
||||
/*
|
||||
NAMESPACE do return namespaceClass;
|
||||
COMPOUNDATTRIBUTE do return attributeClass;
|
||||
|
@ -712,6 +740,68 @@ namespace MetaData {
|
|||
*/
|
||||
}
|
||||
|
||||
bool JS2Metadata::readDynamicProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JS2Metadata::readStaticMember(StaticMember *m, Phase phase)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read the value of a property in the container. Return true/false if that container has
|
||||
// the property or not. If it does, return it's value
|
||||
bool JS2Metadata::readProperty(jsval container, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read the value of a property in the frame. Return true/false if that frame has
|
||||
// the property or not. If it does, return it's value
|
||||
bool JS2Metadata::readProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval)
|
||||
{
|
||||
StaticMember *m = findFlatMember(container, multiname, ReadAccess, phase);
|
||||
if (!m && (container->kind == Frame::GlobalObject))
|
||||
return readDynamicProperty(container, multiname, lookupKind, phase);
|
||||
else
|
||||
return readStaticMember(m, phase);
|
||||
}
|
||||
|
||||
// Find a binding in the frame that matches the multiname and access
|
||||
// It's an error if more than one such binding exists.
|
||||
StaticMember *JS2Metadata::findFlatMember(Frame *container, Multiname *multiname, Access access, Phase phase)
|
||||
{
|
||||
StaticMember *found = NULL;
|
||||
StaticBindingIterator b, end;
|
||||
if ((access == ReadAccess) || (access == ReadWriteAccess)) {
|
||||
b = container->staticReadBindings.lower_bound(multiname->name);
|
||||
end = container->staticReadBindings.upper_bound(multiname->name);
|
||||
}
|
||||
else {
|
||||
b = container->staticWriteBindings.lower_bound(multiname->name);
|
||||
end = container->staticWriteBindings.upper_bound(multiname->name);
|
||||
}
|
||||
while (true) {
|
||||
if (b == end) {
|
||||
if (access == ReadWriteAccess) {
|
||||
access = WriteAccess;
|
||||
b = container->staticWriteBindings.lower_bound(multiname->name);
|
||||
end = container->staticWriteBindings.upper_bound(multiname->name);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (multiname->matches(b->second->qname)) {
|
||||
if (found)
|
||||
reportError(Exception::propertyAccessError, "Ambiguous reference to {0}", errorPos, multiname->name);
|
||||
else
|
||||
found = b->second->content;
|
||||
}
|
||||
b++;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
* Throw an exception of the specified kind, indicating the position 'pos' and
|
||||
|
|
|
@ -46,7 +46,6 @@ namespace MetaData {
|
|||
|
||||
|
||||
// forward definitions:
|
||||
class ExecutionState;
|
||||
class JS2Metadata;
|
||||
class JS2Class;
|
||||
class StaticBinding;
|
||||
|
@ -59,7 +58,8 @@ typedef Invokable Callor;
|
|||
typedef Invokable Constructor;
|
||||
|
||||
|
||||
enum Phase { CompilePhase, RunPhase };
|
||||
enum Phase { CompilePhase, RunPhase };
|
||||
enum Access { ReadAccess, WriteAccess, ReadWriteAccess };
|
||||
|
||||
class JS2Object {
|
||||
// Every object is either undefined, null, a Boolean,
|
||||
|
@ -105,11 +105,19 @@ public:
|
|||
};
|
||||
|
||||
// MULTINAME is the semantic domain of sets of qualified names. Multinames are used internally in property lookup.
|
||||
typedef std::vector<QualifiedName *> QualifierList;
|
||||
typedef QualifierList::iterator QualifierListIterator;
|
||||
// We keep Multinames as a basename and a list of namespace qualifiers
|
||||
typedef std::vector<Namespace *> NamespaceList;
|
||||
typedef NamespaceList::iterator NamespaceListIterator;
|
||||
class Multiname {
|
||||
public:
|
||||
QualifierList qList;
|
||||
|
||||
Multiname(StringAtom &name) : name(name) { }
|
||||
void addNamespace(Namespace *ns) { nsList.push_back(ns); }
|
||||
|
||||
bool matches(QualifiedName &q) { return (name == q.id) && onList(q.nameSpace); }
|
||||
bool onList(Namespace *nameSpace);
|
||||
|
||||
NamespaceList nsList;
|
||||
StringAtom &name;
|
||||
};
|
||||
|
||||
|
@ -237,7 +245,9 @@ public:
|
|||
class Frame {
|
||||
public:
|
||||
enum Plurality { Singular, Plural };
|
||||
enum FrameKind { GlobalObject, Package, Function, Class, Block };
|
||||
enum FrameKind { System, GlobalObject, Package, Function, Class, Block };
|
||||
|
||||
Frame(FrameKind kind) : kind(kind), nextFrame(NULL) { }
|
||||
|
||||
StaticBindingMap staticReadBindings; // Map of qualified names to readable static members defined in this frame
|
||||
StaticBindingMap staticWriteBindings; // Map of qualified names to writable static members defined in this frame
|
||||
|
@ -252,6 +262,7 @@ public:
|
|||
|
||||
class JS2Class : public Frame {
|
||||
public:
|
||||
JS2Class() : Frame(Class) { }
|
||||
|
||||
InstanceBindingMap instanceReadBindings; // Map of qualified names to readable instance members defined in this class
|
||||
InstanceBindingMap instanceWriteBindings; // Map of qualified names to writable instance members defined in this class
|
||||
|
@ -276,7 +287,7 @@ public:
|
|||
|
||||
class GlobalObject : public Frame {
|
||||
public:
|
||||
GlobalObject(World &world) : internalNamespace(new Namespace(world.identifiers["internal"])) { }
|
||||
GlobalObject(World &world) : Frame(Frame::GlobalObject), internalNamespace(new Namespace(world.identifiers["internal"])) { }
|
||||
|
||||
Namespace *internalNamespace; // This global object's internal namespace
|
||||
DynamicPropertyMap dynamicProperties; // A set of this global object's dynamic properties
|
||||
|
@ -369,11 +380,14 @@ public:
|
|||
// The top-level frame containing predefined constants, functions, and classes.
|
||||
class SystemFrame : public Frame {
|
||||
public:
|
||||
SystemFrame() : Frame(System) { }
|
||||
};
|
||||
|
||||
// Frames holding bindings for invoked functions
|
||||
class FunctionFrame : public Frame {
|
||||
public:
|
||||
FunctionFrame() : Frame(Function) { }
|
||||
|
||||
Plurality plurality;
|
||||
jsval thisObject; // The value of this; none if this function doesn't define this;
|
||||
// inaccessible if this function defines this but the value is not
|
||||
|
@ -386,6 +400,8 @@ public:
|
|||
|
||||
class BlockFrame : public Frame {
|
||||
public:
|
||||
BlockFrame() : Frame(Block) { }
|
||||
|
||||
Plurality plurality;
|
||||
};
|
||||
|
||||
|
@ -410,9 +426,7 @@ public:
|
|||
Frame *getTopFrame() { return firstFrame; }
|
||||
|
||||
jsval findThis(bool allowPrototypeThis);
|
||||
jsval lexicalRead(ExecutionState *eState, Multiname *multiname, Phase phase);
|
||||
|
||||
bool readProperty(ExecutionState *eState, jsval container, Multiname *multinameVal, LookupKind *lookupKind, Phase phase, jsval *rval);
|
||||
jsval lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase);
|
||||
|
||||
|
||||
private:
|
||||
|
@ -468,32 +482,47 @@ public:
|
|||
|
||||
void setCurrentParser(Parser *parser) { mParser = parser; }
|
||||
|
||||
void ValidateTypeExpression(ExprNode *e);
|
||||
void ValidateStmtList(StmtNode *p);
|
||||
jsval EvalStmtList(Phase phase, StmtNode *p);
|
||||
|
||||
|
||||
void ValidateStmtList(Context *cxt, Environment *env, StmtNode *p);
|
||||
void ValidateTypeExpression(ExprNode *e);
|
||||
void ValidateStmt(Context *cxt, Environment *env, StmtNode *p);
|
||||
void defineHoistedVar(Environment *env, const StringAtom &id, StmtNode *p);
|
||||
void ValidateExpression(Context *cxt, Environment *env, ExprNode *p);
|
||||
void ValidateAttributeExpression(Context *cxt, Environment *env, ExprNode *p);
|
||||
|
||||
jsval EvalStmtList(Environment *env, Phase phase, StmtNode *p);
|
||||
jsval EvalExpression(Environment *env, Phase phase, ExprNode *p);
|
||||
bool EvalExprNode(Environment *env, Phase phase, ExprNode *p, String &s);
|
||||
Attribute *EvalAttributeExpression(Environment *env, Phase phase, ExprNode *p);
|
||||
jsval EvalStmtList(Environment *env, Phase phase, StmtNode *p);
|
||||
jsval EvalStmt(Environment *env, Phase phase, StmtNode *p);
|
||||
|
||||
|
||||
JS2Class *objectType(jsval obj);
|
||||
|
||||
bool readProperty(jsval container, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval);
|
||||
bool readProperty(Frame *pf, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval);
|
||||
StaticMember *findFlatMember(Frame *container, Multiname *multiname, Access access, Phase phase);
|
||||
|
||||
bool readDynamicProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase);
|
||||
bool readStaticMember(StaticMember *m, Phase phase);
|
||||
|
||||
|
||||
|
||||
void reportError(Exception::Kind kind, const char *message, size_t pos, const char *arg = NULL);
|
||||
void reportError(Exception::Kind kind, const char *message, size_t pos, const String& name);
|
||||
|
||||
|
||||
void initializeMonkey();
|
||||
jsval execute(String *str, Environment *env, JS2Metadata *meta, size_t pos);
|
||||
jsval execute(String *str, size_t pos);
|
||||
|
||||
// Used for interning strings
|
||||
World &world;
|
||||
|
||||
// The one and only 'public' namespace
|
||||
Namespace *publicNamespace; // XXX is this the right place for this ???
|
||||
Namespace *publicNamespace;
|
||||
|
||||
// The base classes:
|
||||
JS2Class *undefinedClass;
|
||||
|
@ -505,21 +534,18 @@ public:
|
|||
|
||||
|
||||
Parser *mParser; // used for error reporting
|
||||
size_t errorPos;
|
||||
|
||||
};
|
||||
|
||||
// Captures some metadata-related info. that gets passed back into
|
||||
// js2metadata routines from executing JS code
|
||||
// - it's hidden in the Monkey context private
|
||||
class ExecutionState {
|
||||
public:
|
||||
ExecutionState(JSContext *cx, Environment *env, JS2Metadata *meta, size_t pos) : cx(cx), env(env), meta(meta), pos(pos) { }
|
||||
virtual ~ExecutionState() { }
|
||||
GlobalObject glob;
|
||||
Environment env;
|
||||
Context cxt;
|
||||
|
||||
// SpiderMonkey execution data:
|
||||
JSRuntime *monkeyRuntime;
|
||||
JSContext *monkeyContext;
|
||||
JSObject *monkeyGlobalObject;
|
||||
|
||||
JSContext *cx; // the SpiderMonkey context
|
||||
Environment *env; // the frame array, used for lookups
|
||||
JS2Metadata *meta; // base class for error reporting
|
||||
size_t pos; // position from node being executed (vaguely)
|
||||
};
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче