зеркало из https://github.com/mozilla/pjs.git
Changes to arguments instance & class
This commit is contained in:
Родитель
f1e70c6436
Коммит
d3d055b2bf
|
@ -853,6 +853,48 @@ namespace MetaData {
|
|||
return Delete(meta, base, mn, NULL, result);
|
||||
}
|
||||
|
||||
bool JS2ArgumentsClass::Read(JS2Metadata *meta, js2val *base, Multiname *multiname, Environment *env, Phase phase, js2val *rval)
|
||||
{
|
||||
ASSERT(JS2VAL_IS_OBJECT(*base));
|
||||
JS2Object *obj = JS2VAL_TO_OBJECT(*base);
|
||||
ArgumentsInstance *args = checked_cast<ArgumentsInstance *>(obj);
|
||||
|
||||
uint32 index;
|
||||
if ((multiname->nsList->size() == 1)
|
||||
&& (multiname->nsList->back() == meta->publicNamespace)
|
||||
&& isValidIndex(multiname->name, index)
|
||||
&& (index < args->mSlots->size())) {
|
||||
*rval = (*args->mSlots)[index];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return JS2Class::Read(meta, base, multiname, env, phase, rval);
|
||||
}
|
||||
|
||||
bool JS2ArgumentsClass::Write(JS2Metadata *meta, js2val base, Multiname *multiname, Environment *env, bool createIfMissing, js2val newValue, bool initFlag)
|
||||
{
|
||||
ASSERT(JS2VAL_IS_OBJECT(base));
|
||||
JS2Object *obj = JS2VAL_TO_OBJECT(base);
|
||||
ArgumentsInstance *args = checked_cast<ArgumentsInstance *>(obj);
|
||||
|
||||
uint32 index;
|
||||
if ((multiname->nsList->size() == 1)
|
||||
&& (multiname->nsList->back() == meta->publicNamespace)
|
||||
&& isValidIndex(multiname->name, index)
|
||||
&& (index < args->mSlots->size())) {
|
||||
(*args->mSlots)[index] = newValue;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return JS2Class::Write(meta, base, multiname, env, createIfMissing, newValue, false);
|
||||
}
|
||||
|
||||
bool JS2ArgumentsClass::Delete(JS2Metadata *meta, js2val base, Multiname *multiname, Environment *env, bool *result)
|
||||
{
|
||||
return JS2Class::Delete(meta, base, multiname, env, result);
|
||||
}
|
||||
|
||||
|
||||
bool JS2Class::Write(JS2Metadata *meta, js2val base, Multiname *multiname, Environment *env, bool createIfMissing, js2val newValue, bool initFlag)
|
||||
{
|
||||
InstanceMember *mBase = meta->findBaseInstanceMember(this, multiname, WriteAccess);
|
||||
|
@ -883,7 +925,7 @@ namespace MetaData {
|
|||
DEFINE_ROOTKEEPER(rk, mn);
|
||||
if ( (meta->findBaseInstanceMember(this, mn, ReadAccess) == NULL)
|
||||
&& (meta->findCommonMember(&base, mn, ReadAccess, true) == NULL) ) {
|
||||
meta->createDynamicProperty(baseObj, &qName, newValue, ReadWriteAccess, false, true);
|
||||
meta->createDynamicProperty(baseObj, mn->name, newValue, ReadWriteAccess, false, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3106,7 +3106,7 @@ doUnary:
|
|||
}
|
||||
|
||||
// Clone the pluralFrame bindings into the singularFrame, instantiating new members for each binding
|
||||
void Environment::instantiateFrame(NonWithFrame *pluralFrame, NonWithFrame *singularFrame)
|
||||
void Environment::instantiateFrame(NonWithFrame *pluralFrame, NonWithFrame *singularFrame, bool buildSlots)
|
||||
{
|
||||
singularFrame->localBindings.clear();
|
||||
|
||||
|
@ -3118,7 +3118,7 @@ doUnary:
|
|||
LocalBindingEntry *lbe = *bi2;
|
||||
singularFrame->localBindings.insert(lbe->name, lbe->clone());
|
||||
}
|
||||
if (pluralFrame->slots) {
|
||||
if (buildSlots && pluralFrame->slots) {
|
||||
size_t count = pluralFrame->slots->size();
|
||||
singularFrame->slots = new std::vector<js2val>(count);
|
||||
for (size_t i = 0; i < count; i++)
|
||||
|
@ -4008,6 +4008,7 @@ static const uint8 urlCharType[256] =
|
|||
MAKEBUILTINCLASS(classClass, objectClass, false, true, engine->allocStringPtr(&world.identifiers["Class"]), JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(functionClass, objectClass, true, true, engine->Function_StringAtom, JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(packageClass, objectClass, true, true, engine->allocStringPtr(&world.identifiers["Package"]), JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(argumentsClass, objectClass, true, true, engine->allocStringPtr(&world.identifiers["Arguments"]), JS2VAL_NULL);
|
||||
|
||||
|
||||
|
||||
|
@ -4581,22 +4582,34 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
|
||||
DynamicVariable *JS2Metadata::createDynamicProperty(JS2Object *obj, const char *name, js2val initVal, Access access, bool sealed, bool enumerable)
|
||||
{
|
||||
QualifiedName qName(publicNamespace, &world.identifiers[widenCString(name)]);
|
||||
return createDynamicProperty(obj, &qName, initVal, access, sealed, enumerable);
|
||||
return createDynamicProperty(obj, &world.identifiers[widenCString(name)], initVal, access, sealed, enumerable);
|
||||
}
|
||||
|
||||
/*
|
||||
DynamicVariable *JS2Metadata::createDynamicProperty(JS2Object *obj, const String *name, js2val initVal, Access access, bool sealed, bool enumerable)
|
||||
{
|
||||
DEFINE_ROOTKEEPER(rk, name);
|
||||
QualifiedName qName(publicNamespace, name);
|
||||
return createDynamicProperty(obj, &qName, initVal, access, sealed, enumerable);
|
||||
}
|
||||
*/
|
||||
void JS2Metadata::addPublicVariableToLocalMap(LocalBindingMap *lMap, const String *name, LocalMember *v, Access access, bool enumerable)
|
||||
{
|
||||
LocalBinding *new_b = new LocalBinding(access, v, enumerable);
|
||||
LocalBindingEntry **lbeP = (*lMap)[*name];
|
||||
LocalBindingEntry *lbe;
|
||||
if (lbeP == NULL) {
|
||||
lbe = new LocalBindingEntry(*name);
|
||||
lMap->insert(*name, lbe);
|
||||
}
|
||||
else
|
||||
lbe = *lbeP;
|
||||
lbe->bindingList.push_back(LocalBindingEntry::NamespaceBinding(publicNamespace, new_b));
|
||||
}
|
||||
|
||||
// The caller must make sure that the created property does not already exist and does not conflict with any other property.
|
||||
DynamicVariable *JS2Metadata::createDynamicProperty(JS2Object *obj, QualifiedName *qName, js2val initVal, Access access, bool sealed, bool enumerable)
|
||||
DynamicVariable *JS2Metadata::createDynamicProperty(JS2Object *obj, const String *name, js2val initVal, Access access, bool sealed, bool enumerable)
|
||||
{
|
||||
DynamicVariable *dv = new DynamicVariable(initVal, sealed);
|
||||
LocalBinding *new_b = new LocalBinding(access, dv, enumerable);
|
||||
LocalBindingMap *lMap;
|
||||
if (obj->kind == SimpleInstanceKind)
|
||||
lMap = &checked_cast<SimpleInstance *>(obj)->localBindings;
|
||||
|
@ -4605,7 +4618,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
lMap = &checked_cast<Package *>(obj)->localBindings;
|
||||
else
|
||||
ASSERT(false);
|
||||
|
||||
addPublicVariableToLocalMap(lMap, name, dv, access, enumerable);
|
||||
/*
|
||||
LocalBindingEntry **lbeP = (*lMap)[*qName->name];
|
||||
LocalBindingEntry *lbe;
|
||||
if (lbeP == NULL) {
|
||||
|
@ -4615,6 +4629,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
else
|
||||
lbe = *lbeP;
|
||||
lbe->bindingList.push_back(LocalBindingEntry::NamespaceBinding(qName->nameSpace, new_b));
|
||||
*/
|
||||
return dv;
|
||||
}
|
||||
|
||||
|
@ -4662,6 +4677,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
GCMARKOBJECT(syntaxErrorClass);
|
||||
GCMARKOBJECT(typeErrorClass);
|
||||
GCMARKOBJECT(uriErrorClass);
|
||||
GCMARKOBJECT(argumentsClass);
|
||||
|
||||
for (BConListIterator i = bConList.begin(), end = bConList.end(); (i != end); i++)
|
||||
(*i)->mark();
|
||||
|
@ -5039,6 +5055,28 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
delete fWrap;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
*
|
||||
* ArgumentsInstance
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
// gc-mark all contained JS2Objects and visit contained structures to do likewise
|
||||
void ArgumentsInstance::markChildren()
|
||||
{
|
||||
SimpleInstance::markChildren();
|
||||
if (mSlots) {
|
||||
for (uint32 i = 0; i < mSlots->size(); i++)
|
||||
GCMARKVALUE((*mSlots)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ArgumentsInstance::~ArgumentsInstance()
|
||||
{
|
||||
if (mSlots)
|
||||
delete mSlots;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
*
|
||||
* InstanceMethod
|
||||
|
@ -5129,7 +5167,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
|
||||
void ParameterFrame::instantiate(Environment *env)
|
||||
{
|
||||
env->instantiateFrame(pluralFrame, this);
|
||||
env->instantiateFrame(pluralFrame, this, !buildArguments);
|
||||
}
|
||||
|
||||
// Assume that instantiate has been called, the plural frame will contain
|
||||
|
@ -5141,11 +5179,18 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
ASSERT(pluralFrame->kind == ParameterFrameKind);
|
||||
ParameterFrame *plural = checked_cast<ParameterFrame *>(pluralFrame);
|
||||
|
||||
SimpleInstance *argsObj = NULL;
|
||||
ArgumentsInstance *argsObj = NULL;
|
||||
DEFINE_ROOTKEEPER(rk2, argsObj);
|
||||
|
||||
uint32 slotCount = (plural->slots) ? plural->slots->size() : 0;
|
||||
|
||||
if (plural->buildArguments) {
|
||||
argsObj = new SimpleInstance(meta, meta->objectClass->prototype, meta->objectClass);
|
||||
// If we're building an arguments object, the slots for the parameter frame are located
|
||||
// there so that the arguments object itself can survive beyond the life of the function.
|
||||
argsObj = new ArgumentsInstance(meta, meta->objectClass->prototype, meta->argumentsClass);
|
||||
if (slotCount)
|
||||
argsObj->mSlots = new std::vector<js2val>(slotCount);
|
||||
slots = argsObj->mSlots;
|
||||
// Add the 'arguments' property
|
||||
String name(widenCString("arguments"));
|
||||
ASSERT(localBindings[name] == NULL);
|
||||
|
@ -5155,22 +5200,16 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
localBindings.insert(name, lbe);
|
||||
}
|
||||
|
||||
uint32 slotCount = (plural->slots) ? plural->slots->size() : 0;
|
||||
|
||||
uint32 i;
|
||||
for (i = 0; (i < argCount); i++) {
|
||||
if (i < slotCount) {
|
||||
(*slots)[i] = argBase[i];
|
||||
}
|
||||
if (plural->buildArguments)
|
||||
meta->objectClass->WritePublic(meta, OBJECT_TO_JS2VAL(argsObj), meta->engine->numberToString(i), true, argBase[i]);
|
||||
}
|
||||
while (i++ < length) {
|
||||
if (i < slotCount) {
|
||||
(*slots)[i] = JS2VAL_UNDEFINED;
|
||||
}
|
||||
if (plural->buildArguments)
|
||||
meta->objectClass->WritePublic(meta, OBJECT_TO_JS2VAL(argsObj), meta->engine->numberToString(i), true, JS2VAL_UNDEFINED);
|
||||
}
|
||||
if (plural->buildArguments) {
|
||||
setLength(meta, argsObj, argCount);
|
||||
|
@ -5188,6 +5227,9 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
|
||||
ParameterFrame::~ParameterFrame()
|
||||
{
|
||||
if (buildArguments) {
|
||||
slots = NULL; // the slots are in the arguments object, let it do the delete
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
|
@ -5202,6 +5244,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
GCMARKOBJECT(type)
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
*
|
||||
* BlockFrame
|
||||
|
@ -5211,7 +5254,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
void BlockFrame::instantiate(Environment *env)
|
||||
{
|
||||
if (pluralFrame)
|
||||
env->instantiateFrame(pluralFrame, this);
|
||||
env->instantiateFrame(pluralFrame, this, true);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ class FunctionInstance;
|
|||
class ArrayInstance;
|
||||
class RegExpInstance;
|
||||
class Package;
|
||||
class ArgumentsInstance;
|
||||
|
||||
typedef void (Invokable)();
|
||||
typedef js2val (Callor)(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc);
|
||||
|
@ -270,6 +271,7 @@ public:
|
|||
ROOTKEEPER_CONSTRUCTOR(SimpleInstance)
|
||||
ROOTKEEPER_CONSTRUCTOR(FunctionInstance)
|
||||
ROOTKEEPER_CONSTRUCTOR(DateInstance)
|
||||
ROOTKEEPER_CONSTRUCTOR(ArgumentsInstance)
|
||||
|
||||
#ifdef DEBUG
|
||||
RootKeeper(js2val *p, int line, char *pfile) : is_js2val(true), js2val_count(0), p(p) { init(line, pfile); }
|
||||
|
@ -528,8 +530,6 @@ public:
|
|||
virtual void mark();
|
||||
};
|
||||
|
||||
|
||||
|
||||
// A LOCALBINDING describes the member to which one qualified name is bound in a frame. Multiple
|
||||
// qualified names may be bound to the same member in a frame, but a qualified name may not be
|
||||
// bound to multiple members in a frame (except when one binding is for reading only and
|
||||
|
@ -752,7 +752,7 @@ public:
|
|||
void lexicalInit(JS2Metadata *meta, Multiname *multiname, js2val newValue);
|
||||
bool lexicalDelete(JS2Metadata *meta, Multiname *multiname, Phase phase);
|
||||
|
||||
void instantiateFrame(NonWithFrame *pluralFrame, NonWithFrame *singularFrame);
|
||||
void instantiateFrame(NonWithFrame *pluralFrame, NonWithFrame *singularFrame, bool buildSlots);
|
||||
|
||||
void markChildren();
|
||||
|
||||
|
@ -855,6 +855,16 @@ public:
|
|||
virtual bool BracketDelete(JS2Metadata *meta, js2val base, js2val indexVal, bool *result) { return false; }
|
||||
};
|
||||
|
||||
class JS2ArgumentsClass : public JS2Class {
|
||||
public:
|
||||
JS2ArgumentsClass(JS2Class *super, js2val proto, Namespace *privateNamespace, bool dynamic, bool final, const String *name)
|
||||
: JS2Class(super, proto, privateNamespace, dynamic, final, name) { }
|
||||
|
||||
virtual bool Read(JS2Metadata *meta, js2val *base, Multiname *multiname, Environment *env, Phase phase, js2val *rval);
|
||||
virtual bool Write(JS2Metadata *meta, js2val base, Multiname *multiname, Environment *env, bool createIfMissing, js2val newValue, bool initFlag);
|
||||
virtual bool Delete(JS2Metadata *meta, js2val base, Multiname *multiname, Environment *env, bool *result);
|
||||
};
|
||||
|
||||
class Package : public NonWithFrame {
|
||||
public:
|
||||
typedef enum { InTransit, InHand } PackageStatus;
|
||||
|
@ -1049,6 +1059,19 @@ public:
|
|||
virtual ~RegExpInstance() { }
|
||||
};
|
||||
|
||||
class ArgumentsInstance : public SimpleInstance {
|
||||
public:
|
||||
ArgumentsInstance(JS2Metadata *meta, js2val parent, JS2Class *type) : SimpleInstance(meta, parent, type), mSlots(NULL) { }
|
||||
|
||||
ValueList *mSlots;
|
||||
|
||||
virtual void markChildren();
|
||||
virtual ~ArgumentsInstance();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// A helper class for 'for..in' statements
|
||||
class ForIteratorObject : public JS2Object {
|
||||
public:
|
||||
|
@ -1076,6 +1099,7 @@ private:
|
|||
|
||||
// Base class for all references (lvalues)
|
||||
// References are generated during the eval stage (bytecode generation), but shouldn't live beyond that
|
||||
// so they're allocated from an arena carried in the metadata class and cleared after each bytecode gen pass.
|
||||
class Reference : public ArenaObject {
|
||||
public:
|
||||
virtual ~Reference() { }
|
||||
|
@ -1092,7 +1116,7 @@ public:
|
|||
|
||||
virtual void emitDeleteBytecode(BytecodeContainer *, size_t) { ASSERT(false); }
|
||||
|
||||
// indicate whether building the reference generate any stack deposits
|
||||
// indicate whether building the reference generates any stack deposits
|
||||
virtual int hasStackEffect() { ASSERT(false); return 0; }
|
||||
|
||||
};
|
||||
|
@ -1329,7 +1353,8 @@ public:
|
|||
// available because this function hasn't been called yet.
|
||||
|
||||
bool prototype; // true if this function is not an instance method but defines this anyway
|
||||
bool buildArguments;
|
||||
bool buildArguments; // true if the 'arguments' variable is referenced, it will be constructed
|
||||
// by 'assignArguments' and contain the slots for this frame.
|
||||
bool isConstructor;
|
||||
bool isInstance;
|
||||
bool callsSuperConstructor;
|
||||
|
@ -1489,8 +1514,9 @@ public:
|
|||
void invokeInit(JS2Class *c, js2val thisValue, js2val* argv, uint32 argc);
|
||||
|
||||
DynamicVariable *createDynamicProperty(JS2Object *obj, const char *name, js2val initVal, Access access, bool sealed, bool enumerable);
|
||||
DynamicVariable *createDynamicProperty(JS2Object *obj, QualifiedName *qName, js2val initVal, Access access, bool sealed, bool enumerable);
|
||||
// DynamicVariable *createDynamicProperty(JS2Object *obj, QualifiedName *qName, js2val initVal, Access access, bool sealed, bool enumerable);
|
||||
DynamicVariable *createDynamicProperty(JS2Object *obj, const String *name, js2val initVal, Access access, bool sealed, bool enumerable);
|
||||
void addPublicVariableToLocalMap(LocalBindingMap *lMap, const String *name, LocalMember *v, Access access, bool enumerable);
|
||||
|
||||
FunctionInstance *createFunctionInstance(Environment *env, bool prototype, bool unchecked, NativeCode *code, uint32 length, DynamicVariable **lengthProperty);
|
||||
|
||||
|
@ -1582,6 +1608,7 @@ public:
|
|||
JS2Class *syntaxErrorClass;
|
||||
JS2Class *typeErrorClass;
|
||||
JS2Class *uriErrorClass;
|
||||
JS2Class *argumentsClass;
|
||||
|
||||
BytecodeContainer *bCon; // the current output container
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче