mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-21 09:49:14 +00:00
Fixed Array.length & proto functions.
This commit is contained in:
parent
441cd617c5
commit
1f84533442
@ -68,15 +68,31 @@ uint32 getLength(JS2Metadata *meta, JS2Object *obj)
|
||||
|
||||
js2val setLength(JS2Metadata *meta, JS2Object *obj, uint32 length)
|
||||
{
|
||||
Multiname mn(meta->engine->length_StringAtom, meta->publicNamespace);
|
||||
js2val result = meta->engine->allocNumber(length);
|
||||
meta->writeDynamicProperty(obj, &mn, true, result, RunPhase);
|
||||
|
||||
if (obj->kind == PrototypeInstanceKind) {
|
||||
// Can't call 'writeDynamicProperty' as that'll just cycle back here for
|
||||
// ArrayInstances.
|
||||
DynamicPropertyMap *dMap = &checked_cast<PrototypeInstance *>(obj)->dynamicProperties;
|
||||
for (DynamicPropertyIterator i = dMap->begin(), end = dMap->end(); (i != end); i++) {
|
||||
if (i->first == *meta->engine->length_StringAtom) {
|
||||
i->second = result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
const DynamicPropertyMap::value_type e(*meta->engine->length_StringAtom, result);
|
||||
checked_cast<PrototypeInstance *>(obj)->dynamicProperties.insert(e);
|
||||
}
|
||||
else {
|
||||
Multiname mn(meta->engine->length_StringAtom, meta->publicNamespace);
|
||||
meta->writeDynamicProperty(obj, &mn, true, result, RunPhase);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
js2val Array_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
js2val thatValue = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass));
|
||||
js2val thatValue = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass));
|
||||
ArrayInstance *arrInst = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(thatValue));
|
||||
if (argc > 0) {
|
||||
if (argc == 1) {
|
||||
@ -208,7 +224,7 @@ js2val Array_concat(JS2Metadata *meta, const js2val thisValue, js2val *argv, uin
|
||||
{
|
||||
js2val E = thisValue;
|
||||
|
||||
js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass));
|
||||
js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass));
|
||||
ArrayInstance *A = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(result));
|
||||
uint32 n = 0;
|
||||
uint32 i = 0;
|
||||
@ -358,7 +374,7 @@ static js2val Array_slice(JS2Metadata *meta, const js2val thisValue, js2val *arg
|
||||
ASSERT(JS2VAL_IS_OBJECT(thisValue));
|
||||
JS2Object *thisObj = JS2VAL_TO_OBJECT(thisValue);
|
||||
|
||||
js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass));
|
||||
js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass));
|
||||
ArrayInstance *A = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(result));
|
||||
|
||||
uint32 length = getLength(meta, thisObj);
|
||||
@ -584,7 +600,7 @@ static js2val Array_splice(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
||||
JS2Object *thisObj = JS2VAL_TO_OBJECT(thisValue);
|
||||
uint32 length = getLength(meta, thisObj);
|
||||
|
||||
js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass));
|
||||
js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass));
|
||||
ArrayInstance *A = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(result));
|
||||
|
||||
int32 arg0 = meta->toInteger(argv[0]);
|
||||
@ -807,7 +823,8 @@ void initArrayObject(JS2Metadata *meta)
|
||||
publicNamespaceList.push_back(meta->publicNamespace);
|
||||
|
||||
meta->arrayClass->construct = Array_Constructor;
|
||||
meta->arrayClass->prototype = new ArrayInstance(meta->objectClass->prototype, meta->arrayClass);
|
||||
meta->arrayClass->call = Array_Constructor;
|
||||
meta->arrayClass->prototype = new ArrayInstance(meta, meta->objectClass->prototype, meta->arrayClass);
|
||||
|
||||
// Adding "prototype" & "length" as static members of the class - not dynamic properties; XXX
|
||||
meta->env->addFrame(meta->arrayClass);
|
||||
@ -819,11 +836,19 @@ void initArrayObject(JS2Metadata *meta)
|
||||
|
||||
PrototypeFunction *pf = &arrayProtos[0];
|
||||
while (pf->name) {
|
||||
SimpleInstance *fInst = new SimpleInstance(meta->functionClass);
|
||||
fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
|
||||
|
||||
InstanceMember *m = new InstanceMethod(fInst);
|
||||
|
||||
SimpleInstance *callInst = new SimpleInstance(meta->functionClass);
|
||||
callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
|
||||
InstanceMember *m = new InstanceMethod(callInst);
|
||||
meta->defineInstanceMember(meta->arrayClass, &meta->cxt, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0);
|
||||
/*
|
||||
Dynamic property of the prototype:
|
||||
*/
|
||||
FunctionInstance *fInst = new FunctionInstance(meta->functionClass->prototype, meta->functionClass);
|
||||
fInst->fWrap = callInst->fWrap;
|
||||
meta->writeDynamicProperty(meta->arrayClass->prototype, new Multiname(&meta->world.identifiers[pf->name], meta->publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase);
|
||||
meta->writeDynamicProperty(fInst, new Multiname(meta->engine->length_StringAtom, meta->publicNamespace), true, INT_TO_JS2VAL(pf->length), RunPhase);
|
||||
|
||||
pf++;
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ namespace MetaData {
|
||||
// otherwise get a double value
|
||||
js2val JS2Engine::allocNumber(float64 x)
|
||||
{
|
||||
uint32 i;
|
||||
int32 i;
|
||||
js2val retval;
|
||||
if (JSDOUBLE_IS_INT(x, i) && INT_FITS_IN_JS2VAL(i))
|
||||
retval = INT_TO_JS2VAL(i);
|
||||
|
@ -268,7 +268,7 @@ public:
|
||||
|
||||
// The execution stack for expression evaluation, should be empty
|
||||
// between statements.
|
||||
#define INITIAL_EXEC_STACK (40)
|
||||
#define INITIAL_EXEC_STACK (80)
|
||||
|
||||
js2val *execStackLimit;
|
||||
js2val *execStack;
|
||||
|
@ -3066,14 +3066,14 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
||||
writeDynamicProperty(fInst, new Multiname(engine->length_StringAtom, publicNamespace), true, INT_TO_JS2VAL(0), RunPhase);
|
||||
|
||||
/*** ECMA 3 Date Class ***/
|
||||
MAKEBUILTINCLASS(dateClass, objectClass, true, true, true, &world.identifiers["Date"], JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(dateClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["Date"]), JS2VAL_NULL);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(dateClass), true);
|
||||
defineLocalMember(env, &world.identifiers["Date"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
// dateClass->prototype = new PrototypeInstance(NULL, dateClass);
|
||||
initDateObject(this);
|
||||
|
||||
/*** ECMA 3 RegExp Class ***/
|
||||
MAKEBUILTINCLASS(regexpClass, objectClass, true, true, true, &world.identifiers["RegExp"], JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(regexpClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["RegExp"]), JS2VAL_NULL);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(regexpClass), true);
|
||||
defineLocalMember(env, &world.identifiers["RegExp"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
initRegExpObject(this);
|
||||
@ -3094,37 +3094,37 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
||||
initBooleanObject(this);
|
||||
|
||||
/*** ECMA 3 Math Class ***/
|
||||
MAKEBUILTINCLASS(mathClass, objectClass, true, true, true, &world.identifiers["Math"], JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(mathClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["Math"]), JS2VAL_NULL);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(mathClass), true);
|
||||
defineLocalMember(env, &world.identifiers["Math"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
initMathObject(this);
|
||||
|
||||
/*** ECMA 3 Array Class ***/
|
||||
MAKEBUILTINCLASS(arrayClass, objectClass, true, true, true, &world.identifiers["Array"], JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(arrayClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["Array"]), JS2VAL_NULL);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(arrayClass), true);
|
||||
defineLocalMember(env, &world.identifiers["Array"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
initArrayObject(this);
|
||||
|
||||
/*** ECMA 3 Error Classes ***/
|
||||
MAKEBUILTINCLASS(errorClass, objectClass, true, true, true, &world.identifiers["Error"], JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(errorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["Error"]), JS2VAL_NULL);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(errorClass), true);
|
||||
defineLocalMember(env, &world.identifiers["Error"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
MAKEBUILTINCLASS(evalErrorClass, objectClass, true, true, true, &world.identifiers["EvalError"], JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(evalErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["EvalError"]), JS2VAL_NULL);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(evalErrorClass), true);
|
||||
defineLocalMember(env, &world.identifiers["EvalError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
MAKEBUILTINCLASS(rangeErrorClass, objectClass, true, true, true, &world.identifiers["RangeError"], JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(rangeErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["RangeError"]), JS2VAL_NULL);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(rangeErrorClass), true);
|
||||
defineLocalMember(env, &world.identifiers["RangeError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
MAKEBUILTINCLASS(referenceErrorClass, objectClass, true, true, true, &world.identifiers["ReferenceError"], JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(referenceErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["ReferenceError"]), JS2VAL_NULL);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(referenceErrorClass), true);
|
||||
defineLocalMember(env, &world.identifiers["ReferenceError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
MAKEBUILTINCLASS(syntaxErrorClass, objectClass, true, true, true, &world.identifiers["SyntaxError"], JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(syntaxErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["SyntaxError"]), JS2VAL_NULL);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(syntaxErrorClass), true);
|
||||
defineLocalMember(env, &world.identifiers["SyntaxError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
MAKEBUILTINCLASS(typeErrorClass, objectClass, true, true, true, &world.identifiers["TypeError"], JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(typeErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["TypeError"]), JS2VAL_NULL);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(typeErrorClass), true);
|
||||
defineLocalMember(env, &world.identifiers["TypeError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
MAKEBUILTINCLASS(uriErrorClass, objectClass, true, true, true, &world.identifiers["UriError"], JS2VAL_NULL);
|
||||
MAKEBUILTINCLASS(uriErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["UriError"]), JS2VAL_NULL);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(uriErrorClass), true);
|
||||
defineLocalMember(env, &world.identifiers["UriError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
initErrorObject(this);
|
||||
@ -3303,6 +3303,12 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
||||
dynamicProperties->insert(e);
|
||||
}
|
||||
|
||||
void PrototypeInstance::writeProperty(JS2Metadata * /* meta */, const String *name, js2val newValue)
|
||||
{
|
||||
const DynamicPropertyMap::value_type e(*name, newValue);
|
||||
dynamicProperties.insert(e);
|
||||
}
|
||||
|
||||
void ArrayInstance::writeProperty(JS2Metadata *meta, const String *name, js2val newValue)
|
||||
{
|
||||
// An index has to pass the test that :
|
||||
@ -3372,8 +3378,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
||||
}
|
||||
else {
|
||||
PrototypeInstance *pInst = checked_cast<PrototypeInstance *>(container);
|
||||
const DynamicPropertyMap::value_type e(*name, newValue);
|
||||
pInst->dynamicProperties.insert(e);
|
||||
pInst->writeProperty(this, name, newValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -3982,6 +3987,7 @@ deleteClassProperty:
|
||||
GCMARKOBJECT(dateClass);
|
||||
GCMARKOBJECT(regexpClass);
|
||||
GCMARKOBJECT(mathClass);
|
||||
GCMARKOBJECT(arrayClass);
|
||||
GCMARKOBJECT(errorClass);
|
||||
GCMARKOBJECT(evalErrorClass);
|
||||
GCMARKOBJECT(rangeErrorClass);
|
||||
@ -4644,9 +4650,9 @@ deleteClassProperty:
|
||||
ParameterFrame *plural = checked_cast<ParameterFrame *>(pluralFrame);
|
||||
ASSERT((plural->positionalCount == 0) || (plural->positional != NULL));
|
||||
|
||||
js2val argumentsVal = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass));
|
||||
js2val argumentsVal = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass));
|
||||
ArrayInstance *arrInst = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(argumentsVal));
|
||||
uint32 i;
|
||||
uint32 i;
|
||||
for (i = 0; ((i < argCount) && (i < plural->positionalCount)); i++) {
|
||||
ASSERT(plural->positional[i]->cloneContent);
|
||||
ASSERT(plural->positional[i]->cloneContent->kind == Member::Variable);
|
||||
|
@ -187,6 +187,8 @@ public:
|
||||
static void mark(const void *p) { ((PondScum *)p)[-1].mark(); }
|
||||
static void markJS2Value(js2val v);
|
||||
|
||||
virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue) { ASSERT(false); }
|
||||
|
||||
};
|
||||
|
||||
class Attribute : public JS2Object {
|
||||
@ -563,10 +565,11 @@ public:
|
||||
DynamicPropertyMap *dynamicProperties; // A set of this instance's dynamic properties, or NULL if this is a fixed instance
|
||||
FunctionWrapper *fWrap;
|
||||
|
||||
virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue);
|
||||
|
||||
virtual void markChildren();
|
||||
virtual ~SimpleInstance() { }
|
||||
|
||||
virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -584,6 +587,9 @@ public:
|
||||
DynamicPropertyMap dynamicProperties; // A set of this instance's dynamic properties
|
||||
virtual void markChildren();
|
||||
virtual ~PrototypeInstance() { }
|
||||
|
||||
virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue);
|
||||
|
||||
};
|
||||
|
||||
// Date instances are simple instances created by the Date class, they have an extra field
|
||||
@ -644,7 +650,7 @@ public:
|
||||
// are added.
|
||||
class ArrayInstance : public PrototypeInstance {
|
||||
public:
|
||||
ArrayInstance(JS2Object *parent, JS2Class *type) : PrototypeInstance(parent, type) { }
|
||||
ArrayInstance(JS2Metadata *meta, JS2Object *parent, JS2Class *type) : PrototypeInstance(parent, type) { setLength(meta, this, 0); }
|
||||
|
||||
virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue);
|
||||
virtual ~ArrayInstance() { }
|
||||
|
@ -398,14 +398,14 @@
|
||||
pushNumber(z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case eSubtract:
|
||||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = meta->toGeneralNumber(a);
|
||||
b = meta->toGeneralNumber(b);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
|
@ -135,7 +135,7 @@
|
||||
{
|
||||
uint16 argCount = BytecodeContainer::getShort(pc);
|
||||
pc += sizeof(uint16);
|
||||
ArrayInstance *aInst = new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass);
|
||||
ArrayInstance *aInst = new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass);
|
||||
baseVal = OBJECT_TO_JS2VAL(aInst);
|
||||
for (uint16 i = 0; i < argCount; i++) {
|
||||
b = pop();
|
||||
|
@ -142,7 +142,7 @@ namespace MetaData {
|
||||
|
||||
REMatchState *match = REExecute(thisInst->mRegExp, str->begin(), index, toInt32(str->length()), meta->toBoolean(globalMultiline));
|
||||
if (match) {
|
||||
PrototypeInstance *A = new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass);
|
||||
PrototypeInstance *A = new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass);
|
||||
result = OBJECT_TO_JS2VAL(A);
|
||||
js2val matchStr = meta->engine->allocString(str->substr((uint32)match->startIndex, (uint32)match->endIndex - match->startIndex));
|
||||
Multiname mname(&meta->world.identifiers[*meta->toString((long)0)], meta->publicNamespace);
|
||||
|
@ -170,7 +170,7 @@ static js2val String_match(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
||||
return RegExp_exec(meta, regexp, &S, 1);
|
||||
}
|
||||
else {
|
||||
PrototypeInstance *A = new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass);
|
||||
PrototypeInstance *A = new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass);
|
||||
int32 index = 0;
|
||||
int32 lastIndex = 0;
|
||||
while (true) {
|
||||
@ -405,7 +405,7 @@ static js2val String_split(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
||||
{
|
||||
const String *S = meta->toString(thisValue);
|
||||
|
||||
js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass->prototype, meta->arrayClass));
|
||||
js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass));
|
||||
ArrayInstance *A = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(result));
|
||||
|
||||
uint32 lim;
|
||||
|
@ -78,6 +78,8 @@
|
||||
#define INT_TO_JS2VAL(i) (((js2val)(i) << 1) | JS2VAL_INT)
|
||||
#define JS2VAL_TO_INT(v) ((int32)(v) >> 1)
|
||||
#define INT_FITS_IN_JS2VAL(i) ((uint32)((i)+JS2VAL_INT_MAX) <= 2*JS2VAL_INT_MAX)
|
||||
#define INT_FITS_IN_JSVAL(i) ((jsuint)((i)+JSVAL_INT_MAX) <= 2*JSVAL_INT_MAX)
|
||||
|
||||
#define LONG_FITS_IN_JS2VAL(x) (JSLL_CMP((x), >, -JS2VAL_INT_MAX) && JSLL_CMP(JS2VAL_INT_MAX, >, (x)))
|
||||
#define ULONG_FITS_IN_JS2VAL(x) (JSLL_CMP(JS2VAL_INT_MAX, >, (x)))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user