mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-13 03:24:26 +00:00
Fixed length fields for various functions, behavioiur of string functions
to match tests. Added missing virtuals to BoundFunction. Fixed eval access to parameters and locals.
This commit is contained in:
parent
534fd0c9a6
commit
24391bf195
@ -650,6 +650,8 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
||||
}
|
||||
|
||||
mScopeChain->addScope(target->getParameterBarrel());
|
||||
mScopeChain->addScope(target->getActivation());
|
||||
|
||||
mCurModule = target->getByteCode();
|
||||
pc = mCurModule->mCodeBase;
|
||||
endPC = mCurModule->mCodeBase + mCurModule->mLength;
|
||||
@ -799,8 +801,12 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
||||
const String &name = *mCurModule->getString(index);
|
||||
PropertyIterator it;
|
||||
if (obj->hasOwnProperty(name, CURRENT_ATTR, Read, &it))
|
||||
obj->deleteProperty(name, CURRENT_ATTR);
|
||||
pushValue(kTrueValue);
|
||||
if (obj->deleteProperty(name, CURRENT_ATTR))
|
||||
pushValue(kTrueValue);
|
||||
else
|
||||
pushValue(kFalseValue);
|
||||
else
|
||||
pushValue(kTrueValue);
|
||||
}
|
||||
break;
|
||||
case TypeOfOp:
|
||||
@ -2408,6 +2414,26 @@ JSValue JSValue::valueToInteger(Context *cx, const JSValue& value)
|
||||
return v;
|
||||
}
|
||||
|
||||
int32 JSValue::float64ToInt32(float64 d)
|
||||
{
|
||||
d = fd::fmod(d, two32);
|
||||
d = (d >= 0) ? d : d + two32;
|
||||
if (d >= two31)
|
||||
return (int32)(d - two32);
|
||||
else
|
||||
return (int32)(d);
|
||||
}
|
||||
|
||||
uint32 JSValue::float64ToUInt32(float64 d)
|
||||
{
|
||||
bool neg = (d < 0);
|
||||
d = fd::floor(neg ? -d : d);
|
||||
d = neg ? -d : d;
|
||||
d = fd::fmod(d, two32);
|
||||
d = (d >= 0) ? d : d + two32;
|
||||
return (uint32)d;
|
||||
}
|
||||
|
||||
JSValue JSValue::valueToInt32(Context *, const JSValue& value)
|
||||
{
|
||||
float64 d;
|
||||
@ -2433,12 +2459,7 @@ JSValue JSValue::valueToInt32(Context *, const JSValue& value)
|
||||
}
|
||||
if ((d == 0.0) || !JSDOUBLE_IS_FINITE(d) )
|
||||
return JSValue((float64)0);
|
||||
d = fd::fmod(d, two32);
|
||||
d = (d >= 0) ? d : d + two32;
|
||||
if (d >= two31)
|
||||
return JSValue((float64)(d - two32));
|
||||
else
|
||||
return JSValue((float64)d);
|
||||
return JSValue((float64)float64ToInt32(d));
|
||||
}
|
||||
|
||||
JSValue JSValue::valueToUInt32(Context *, const JSValue& value)
|
||||
@ -2466,12 +2487,7 @@ JSValue JSValue::valueToUInt32(Context *, const JSValue& value)
|
||||
}
|
||||
if ((d == 0.0) || !JSDOUBLE_IS_FINITE(d))
|
||||
return JSValue((float64)0);
|
||||
bool neg = (d < 0);
|
||||
d = fd::floor(neg ? -d : d);
|
||||
d = neg ? -d : d;
|
||||
d = fd::fmod(d, two32);
|
||||
d = (d >= 0) ? d : d + two32;
|
||||
return JSValue((float64)d);
|
||||
return JSValue((float64)float64ToUInt32(d));
|
||||
}
|
||||
|
||||
JSValue JSValue::valueToUInt16(Context *, const JSValue& value)
|
||||
|
@ -172,6 +172,16 @@ bool JSObject::hasProperty(const String &name, NamespaceList *names, Access acc,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JSObject::deleteProperty(const String &name, NamespaceList *names)
|
||||
{
|
||||
PropertyIterator i = findNamespacedProperty(name, names);
|
||||
if ((PROPERTY_ATTR(i) & Property::DontDelete) == 0) {
|
||||
mProperties.erase(i);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// get a property value
|
||||
JSValue JSObject::getPropertyValue(PropertyIterator &i)
|
||||
@ -423,6 +433,7 @@ void JSObject::setProperty(Context *cx, const String &name, NamespaceList *names
|
||||
{
|
||||
PropertyIterator i;
|
||||
if (hasProperty(name, names, Write, &i)) {
|
||||
if (PROPERTY_ATTR(i) & Property::ReadOnly) return;
|
||||
Property *prop = PROPERTY(i);
|
||||
switch (prop->mFlag) {
|
||||
case ValuePointer:
|
||||
@ -459,6 +470,7 @@ void JSInstance::setProperty(Context *cx, const String &name, NamespaceList *nam
|
||||
{
|
||||
PropertyIterator i;
|
||||
if (hasOwnProperty(name, names, Write, &i)) {
|
||||
if (PROPERTY_ATTR(i) & Property::ReadOnly) return;
|
||||
Property *prop = PROPERTY(i);
|
||||
switch (prop->mFlag) {
|
||||
case Slot:
|
||||
@ -536,6 +548,8 @@ void JSArrayInstance::setProperty(Context *cx, const String &name, NamespaceList
|
||||
}
|
||||
}
|
||||
|
||||
// get a named property from a string instance, but intercept
|
||||
// 'length' by returning the known value
|
||||
void JSStringInstance::getProperty(Context *cx, const String &name, NamespaceList *names)
|
||||
{
|
||||
if (name.compare(cx->Length_StringAtom) == 0) {
|
||||
@ -545,7 +559,9 @@ void JSStringInstance::getProperty(Context *cx, const String &name, NamespaceLis
|
||||
JSInstance::getProperty(cx, name, names);
|
||||
}
|
||||
|
||||
|
||||
// construct an instance of a type
|
||||
// - allocate memory for the slots, load the instance variable names into the
|
||||
// property map.
|
||||
void JSInstance::initInstance(Context *cx, JSType *type)
|
||||
{
|
||||
if (type->mVariableCount)
|
||||
@ -637,12 +653,18 @@ void ScopeChain::setNameValue(Context *cx, const String& name, AttributeStmtNode
|
||||
{
|
||||
PropertyIterator i;
|
||||
if ((*s)->hasProperty(name, names, Write, &i)) {
|
||||
if (PROPERTY_KIND(i) == ValuePointer) {
|
||||
PropertyFlag flag = PROPERTY_KIND(i);
|
||||
switch (flag) {
|
||||
case ValuePointer:
|
||||
*PROPERTY_VALUEPOINTER(i) = v;
|
||||
break;
|
||||
}
|
||||
else
|
||||
case Slot:
|
||||
(*s)->setSlotValue(cx, PROPERTY_INDEX(i), v);
|
||||
break;
|
||||
default:
|
||||
ASSERT(false); // what else needs to be implemented ?
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
cx->getGlobalObject()->defineVariable(cx, name, attr, Object_Type, v);
|
||||
@ -734,13 +756,49 @@ Reference *ParameterBarrel::genReference(bool /* hasBase */, const String& name,
|
||||
|
||||
JSValue ParameterBarrel::getSlotValue(Context *cx, uint32 slotIndex)
|
||||
{
|
||||
// Assume that the appropriate argument chunk is the topmost one
|
||||
// find the appropriate activation object:
|
||||
if (cx->mArgumentBase == NULL) {// then must be in eval code,
|
||||
Activation *prev = cx->mActivationStack.top();
|
||||
return prev->mArgumentBase[slotIndex];
|
||||
}
|
||||
return cx->mArgumentBase[slotIndex];
|
||||
}
|
||||
|
||||
void ParameterBarrel::setSlotValue(Context *cx, uint32 slotIndex, JSValue &v)
|
||||
{
|
||||
// find the appropriate activation object:
|
||||
if (cx->mArgumentBase == NULL) {// then must be in eval code,
|
||||
Activation *prev = cx->mActivationStack.top();
|
||||
prev->mArgumentBase[slotIndex] = v;
|
||||
}
|
||||
else
|
||||
cx->mArgumentBase[slotIndex] = v;
|
||||
}
|
||||
|
||||
|
||||
|
||||
JSValue Activation::getSlotValue(Context *cx, uint32 slotIndex)
|
||||
{
|
||||
// find the appropriate activation object:
|
||||
if (cx->mArgumentBase == NULL) {// then must be in eval code,
|
||||
Activation *prev = cx->mActivationStack.top();
|
||||
return prev->mLocals[slotIndex];
|
||||
}
|
||||
return cx->mLocals[slotIndex];
|
||||
}
|
||||
|
||||
void Activation::setSlotValue(Context *cx, uint32 slotIndex, JSValue &v)
|
||||
{
|
||||
// find the appropriate activation object:
|
||||
if (cx->mArgumentBase == NULL) {// then must be in eval code,
|
||||
Activation *prev = cx->mActivationStack.top();
|
||||
prev->mLocals[slotIndex] = v;
|
||||
}
|
||||
else
|
||||
cx->mLocals[slotIndex] =v;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -873,19 +931,19 @@ bool ScopeChain::isPossibleUncheckedFunction(FunctionDefinition *f)
|
||||
{
|
||||
bool result = false;
|
||||
if ((f->resultType == NULL)
|
||||
&& (f->restParameter == NULL)
|
||||
&& (f->optParameters == NULL)
|
||||
&& (f->prefix == FunctionName::normal)
|
||||
&& (topClass() == NULL)) {
|
||||
result = true;
|
||||
VariableBinding *b = f->parameters;
|
||||
while (b) {
|
||||
if (b->type != NULL) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
b = b->next;
|
||||
}
|
||||
&& (f->restParameter == NULL)
|
||||
&& (f->optParameters == NULL)
|
||||
&& (f->prefix == FunctionName::normal)
|
||||
&& (topClass() == NULL)) {
|
||||
result = true;
|
||||
VariableBinding *b = f->parameters;
|
||||
while (b) {
|
||||
if (b->type != NULL) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
b = b->next;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -1294,15 +1352,9 @@ bool JSType::hasProperty(const String &name, NamespaceList *names, Access acc, P
|
||||
if (hasOwnProperty(name, names, acc, p))
|
||||
return true;
|
||||
else
|
||||
|
||||
// XXX with this change we get unknown type failure for
|
||||
|
||||
if (mSuperType)
|
||||
return mSuperType->hasProperty(name, names, acc, p);
|
||||
else
|
||||
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1374,9 +1426,9 @@ JSType::JSType(Context *cx, const StringAtom *name, JSType *super, JSObject *pro
|
||||
mPrototypeObject->mPrototype = mSuperType->mPrototypeObject;
|
||||
|
||||
if (mSuperType)
|
||||
defineVariable(cx, cx->Prototype_StringAtom, NULL, Object_Type, JSValue(mPrototypeObject));
|
||||
defineVariable(cx, cx->Prototype_StringAtom, (NamespaceList *)NULL, Property::ReadOnly | Property::DontDelete, Object_Type, JSValue(mPrototypeObject));
|
||||
else // must be Object_Type
|
||||
defineVariable(cx, cx->Prototype_StringAtom, NULL, this, JSValue(mPrototypeObject));
|
||||
defineVariable(cx, cx->Prototype_StringAtom, (NamespaceList *)NULL, Property::ReadOnly | Property::DontDelete, this, JSValue(mPrototypeObject));
|
||||
|
||||
if (mSuperType)
|
||||
mPrototype = mSuperType->mPrototypeObject;
|
||||
@ -1849,9 +1901,10 @@ static JSValue Function_Constructor(Context *cx, const JSValue& thisValue, JSVal
|
||||
}
|
||||
fnc->setArgCounts(cx, reqArgCount, optArgCount, (f->function.restParameter != NULL));
|
||||
|
||||
if (cx->mScopeChain->isPossibleUncheckedFunction(&f->function))
|
||||
if (cx->mScopeChain->isPossibleUncheckedFunction(&f->function)) {
|
||||
fnc->setIsPrototype(true);
|
||||
|
||||
fnc->setIsUnchecked();
|
||||
}
|
||||
cx->buildRuntimeForFunction(f->function, fnc);
|
||||
ByteCodeGen bcg(cx, cx->mScopeChain);
|
||||
bcg.genCodeForFunction(f->function, f->pos, fnc, false, NULL);
|
||||
@ -1859,13 +1912,16 @@ static JSValue Function_Constructor(Context *cx, const JSValue& thisValue, JSVal
|
||||
}
|
||||
/***************************************************************/
|
||||
|
||||
JSObject *fncPrototype = Object_Type->newInstance(cx);
|
||||
fncPrototype->defineVariable(cx, cx->Constructor_StringAtom, (NamespaceList *)NULL, Property::Enumerable, Object_Type, JSValue(fnc));
|
||||
fnc->defineVariable(cx, cx->Prototype_StringAtom, (NamespaceList *)NULL, Property::Enumerable, Object_Type, JSValue(fncPrototype));
|
||||
v = JSValue(fnc);
|
||||
return v;
|
||||
}
|
||||
|
||||
static JSValue Function_toString(Context *, const JSValue& thisValue, JSValue * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
ASSERT(thisValue.isFunction());
|
||||
ASSERT(thisValue.isFunction() || (thisValue.isObject() && (thisValue.object->getType() == Function_Type)) );
|
||||
return JSValue(new String(widenCString("function () { }")));
|
||||
}
|
||||
|
||||
@ -2085,7 +2141,6 @@ JSFunction::JSFunction(Context *cx, JSType *resultType, ScopeChain *scopeChain)
|
||||
if (Function_Type) // protect against bootstrap
|
||||
mPrototype = Function_Type->mPrototypeObject;
|
||||
mActivation.mContainer = this;
|
||||
defineVariable(cx, cx->Length_StringAtom, (NamespaceList *)NULL, Property::NoAttribute, Number_Type, JSValue((float64)0));
|
||||
}
|
||||
|
||||
JSFunction::JSFunction(Context *cx, NativeCode *code, JSType *resultType)
|
||||
@ -2110,7 +2165,6 @@ JSFunction::JSFunction(Context *cx, NativeCode *code, JSType *resultType)
|
||||
if (Function_Type) // protect against bootstrap
|
||||
mPrototype = Function_Type->mPrototypeObject;
|
||||
mActivation.mContainer = this;
|
||||
defineVariable(cx, cx->Length_StringAtom, (NamespaceList *)NULL, Property::NoAttribute, Number_Type, JSValue((float64)0));
|
||||
}
|
||||
|
||||
JSValue JSFunction::runArgInitializer(Context *cx, uint32 a, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
@ -2125,7 +2179,7 @@ void JSFunction::setArgCounts(Context *cx, uint32 r, uint32 o, bool hasRest)
|
||||
mRequiredArgs = r;
|
||||
mOptionalArgs = o;
|
||||
mArguments = new ArgumentData[mRequiredArgs + mOptionalArgs + ((hasRest) ? 1 : 0)];
|
||||
setProperty(cx, cx->Length_StringAtom, (NamespaceList *)NULL, JSValue((float64)mRequiredArgs));
|
||||
defineVariable(cx, cx->Length_StringAtom, (NamespaceList *)NULL, Property::DontDelete | Property::ReadOnly, Number_Type, JSValue((float64)mRequiredArgs));
|
||||
}
|
||||
|
||||
|
||||
@ -2247,9 +2301,17 @@ void Context::initBuiltins()
|
||||
Function_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[2].name)], Object_Type, funProto);
|
||||
funProto->mType = Function_Type;
|
||||
|
||||
Number_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[3].name)], Object_Type);
|
||||
JSObject *numProto = new JSObject();
|
||||
Number_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[3].name)], Object_Type, numProto);
|
||||
numProto->mType = Number_Type;
|
||||
numProto->mPrivate = (void *)(new float64(0.0));
|
||||
|
||||
Integer_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[4].name)], Object_Type);
|
||||
String_Type = new JSStringType(this, &mWorld.identifiers[widenCString(builtInClasses[5].name)], Object_Type);
|
||||
|
||||
JSObject *strProto = new JSStringInstance(this, NULL);
|
||||
String_Type = new JSStringType(this, &mWorld.identifiers[widenCString(builtInClasses[5].name)], Object_Type, strProto);
|
||||
strProto->mType = String_Type;
|
||||
strProto->mPrivate = (void *)(&Empty_StringAtom);
|
||||
|
||||
JSArrayInstance *arrayProto = new JSArrayInstance(this, NULL);
|
||||
Array_Type = new JSArrayType(this, Object_Type, &mWorld.identifiers[widenCString(builtInClasses[6].name)], Object_Type, arrayProto);
|
||||
@ -2319,10 +2381,12 @@ void Context::initBuiltins()
|
||||
initClass(Attribute_Type, &builtInClasses[10], NULL);
|
||||
initClass(NamedArgument_Type, &builtInClasses[11], NULL);
|
||||
initClass(Date_Type, &builtInClasses[12], getDateProtos() );
|
||||
initClass(Null_Type, &builtInClasses[13], NULL);
|
||||
initClass(Null_Type, &builtInClasses[13], NULL);
|
||||
|
||||
Type_Type->defineUnaryOperator(Index, new JSFunction(this, arrayMaker, Type_Type));
|
||||
|
||||
Function_Type->mTypeCast = new JSFunction(this, Function_Constructor, Object_Type);
|
||||
|
||||
Array_Type->defineUnaryOperator(Index, new JSFunction(this, Array_GetElement, Object_Type));
|
||||
Array_Type->defineUnaryOperator(IndexEqual, new JSFunction(this, Array_SetElement, Object_Type));
|
||||
|
||||
@ -2330,6 +2394,8 @@ void Context::initBuiltins()
|
||||
Date_Type->defineStaticMethod(this, widenCString("parse"), NULL, new JSFunction(this, Date_parse, Number_Type));
|
||||
Date_Type->defineStaticMethod(this, widenCString("UTC"), NULL, new JSFunction(this, Date_UTC, Number_Type));
|
||||
|
||||
String_Type->mTypeCast = new JSFunction(this, String_Constructor, String_Type);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -2457,17 +2523,18 @@ Context::Context(JSObject **global, World &world, Arena &a, Pragma::Flags flags)
|
||||
initBuiltins();
|
||||
}
|
||||
|
||||
JSType *MathType = new JSType(this, &mWorld.identifiers[widenCString("Math")], Object_Type);
|
||||
JSObject *mathObj = MathType->newInstance(this);
|
||||
|
||||
JSObject *mathObj = Object_Type->newInstance(this);
|
||||
getGlobalObject()->defineVariable(this, Math_StringAtom, (NamespaceList *)(NULL), Property::NoAttribute, Object_Type, JSValue(mathObj));
|
||||
initMathObject(this, mathObj);
|
||||
initDateObject(this);
|
||||
|
||||
Number_Type->defineVariable(this, widenCString("MAX_VALUE"), NULL, Number_Type, JSValue(maxValue));
|
||||
Number_Type->defineVariable(this, widenCString("MIN_VALUE"), NULL, Number_Type, JSValue(minValue));
|
||||
Number_Type->defineVariable(this, widenCString("NaN"), NULL, Number_Type, JSValue(nan));
|
||||
Number_Type->defineVariable(this, widenCString("POSITIVE_INFINITY"), NULL, Number_Type, JSValue(positiveInfinity));
|
||||
Number_Type->defineVariable(this, widenCString("NEGATIVE_INFINITY"), NULL, Number_Type, JSValue(negativeInfinity));
|
||||
Number_Type->defineVariable(this, widenCString("MAX_VALUE"), NULL, Property::ReadOnly | Property::DontDelete, Number_Type, JSValue(maxValue));
|
||||
Number_Type->defineVariable(this, widenCString("MIN_VALUE"), NULL, Property::ReadOnly | Property::DontDelete, Number_Type, JSValue(minValue));
|
||||
Number_Type->defineVariable(this, widenCString("NaN"), NULL, Property::ReadOnly | Property::DontDelete, Number_Type, JSValue(nan));
|
||||
Number_Type->defineVariable(this, widenCString("POSITIVE_INFINITY"), NULL, Property::ReadOnly | Property::DontDelete, Number_Type, JSValue(positiveInfinity));
|
||||
Number_Type->defineVariable(this, widenCString("NEGATIVE_INFINITY"), NULL, Property::ReadOnly | Property::DontDelete, Number_Type, JSValue(negativeInfinity));
|
||||
|
||||
initOperators();
|
||||
|
||||
@ -2628,10 +2695,16 @@ Formatter& operator<<(Formatter& f, const JSValue& value)
|
||||
break;
|
||||
case JSValue::function_tag:
|
||||
if (!value.function->isNative()) {
|
||||
StringFormatter s;
|
||||
PrettyPrinter pp(s);
|
||||
value.function->getFunctionName()->print(pp);
|
||||
f << "function '" << s.getString() << "'\n" << *value.function->getByteCode();
|
||||
FunctionName *fnName = value.function->getFunctionName();
|
||||
if (fnName) {
|
||||
StringFormatter s;
|
||||
PrettyPrinter pp(s);
|
||||
fnName->print(pp);
|
||||
f << "function '" << s.getString() << "'\n" << *value.function->getByteCode();
|
||||
}
|
||||
else {
|
||||
f << "function anonymous\n" << *value.function->getByteCode();
|
||||
}
|
||||
}
|
||||
else
|
||||
f << "function\n";
|
||||
|
@ -221,6 +221,8 @@ static const double two31 = 2147483648.0;
|
||||
|
||||
|
||||
static float64 float64ToInteger(float64 d);
|
||||
static int32 float64ToInt32(float64 d);
|
||||
static uint32 float64ToUInt32(float64 d);
|
||||
|
||||
int operator==(const JSValue& value) const;
|
||||
|
||||
@ -528,16 +530,12 @@ XXX ...couldn't get this to work...
|
||||
// find a property by the given name, and then check to see if there's any
|
||||
// overlap between the supplied attribute list and the property's list.
|
||||
// ***** REWRITE ME -- matching attribute lists for inclusion is a bad idea.
|
||||
PropertyIterator findNamespacedProperty(const String &name, NamespaceList *names);
|
||||
virtual PropertyIterator findNamespacedProperty(const String &name, NamespaceList *names);
|
||||
|
||||
void deleteProperty(const String &name, NamespaceList *names)
|
||||
{
|
||||
PropertyIterator i = findNamespacedProperty(name, names);
|
||||
mProperties.erase(i);
|
||||
}
|
||||
virtual bool deleteProperty(const String &name, NamespaceList *names);
|
||||
|
||||
// see if the property exists by a specific kind of access
|
||||
bool hasOwnProperty(const String &name, NamespaceList *names, Access acc, PropertyIterator *p);
|
||||
virtual bool hasOwnProperty(const String &name, NamespaceList *names, Access acc, PropertyIterator *p);
|
||||
|
||||
virtual bool hasProperty(const String &name, NamespaceList *names, Access acc, PropertyIterator *p);
|
||||
|
||||
@ -602,6 +600,7 @@ XXX ...couldn't get this to work...
|
||||
virtual void defineTempVariable(Context *cx, Reference *&readRef, Reference *&writeRef, JSType *type);
|
||||
|
||||
virtual JSValue getSlotValue(Context * /*cx*/, uint32 /*slotIndex*/) { ASSERT(false); return kUndefinedValue; }
|
||||
virtual void setSlotValue(Context * /*cx*/, uint32 /*slotIndex*/, JSValue & /*v*/) { ASSERT(false); }
|
||||
|
||||
// debug only
|
||||
void printProperties(Formatter &f) const
|
||||
@ -715,6 +714,10 @@ XXX ...couldn't get this to work...
|
||||
{
|
||||
return JSObject::defineVariable(cx, name, attr, type, v);
|
||||
}
|
||||
Property *defineVariable(Context *cx, const String &name, NamespaceList *names, PropertyAttribute attrFlags, JSType *type, const JSValue v)
|
||||
{
|
||||
return JSObject::defineVariable(cx, name, names, attrFlags, type, v);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -848,8 +851,8 @@ XXX ...couldn't get this to work...
|
||||
|
||||
class JSStringType : public JSType {
|
||||
public:
|
||||
JSStringType(Context *cx, const StringAtom *name, JSType *super)
|
||||
: JSType(cx, name, super)
|
||||
JSStringType(Context *cx, const StringAtom *name, JSType *super, JSObject *protoObj = NULL)
|
||||
: JSType(cx, name, super, protoObj)
|
||||
{
|
||||
}
|
||||
virtual ~JSStringType() { } // keeping gcc happy
|
||||
@ -886,6 +889,7 @@ XXX ...couldn't get this to work...
|
||||
Reference *genReference(bool hasBase, const String& name, NamespaceList *names, Access acc, uint32 depth);
|
||||
|
||||
JSValue getSlotValue(Context *cx, uint32 slotIndex);
|
||||
void setSlotValue(Context *cx, uint32 slotIndex, JSValue &v);
|
||||
|
||||
};
|
||||
|
||||
@ -971,6 +975,9 @@ XXX ...couldn't get this to work...
|
||||
|
||||
Reference *genReference(bool hasBase, const String& name, NamespaceList *names, Access acc, uint32 depth);
|
||||
|
||||
JSValue getSlotValue(Context *cx, uint32 slotIndex);
|
||||
void setSlotValue(Context *cx, uint32 slotIndex, JSValue &v);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -1083,10 +1090,10 @@ XXX ...couldn't get this to work...
|
||||
}
|
||||
|
||||
// delete a property from the top object (already know it's there)
|
||||
void deleteProperty(const String &name, NamespaceList *names)
|
||||
bool deleteProperty(const String &name, NamespaceList *names)
|
||||
{
|
||||
JSObject *top = mScopeStack.back();
|
||||
top->deleteProperty(name, names);
|
||||
return top->deleteProperty(name, names);
|
||||
}
|
||||
|
||||
// generate a reference to the given name
|
||||
@ -1221,11 +1228,12 @@ XXX ...couldn't get this to work...
|
||||
virtual bool isNative() { return (mCode != NULL); }
|
||||
virtual bool isPrototype() { return mIsPrototype; }
|
||||
virtual bool isConstructor() { return mIsConstructor; }
|
||||
bool isMethod() { return (mClass != NULL); }
|
||||
virtual bool isMethod() { return (mClass != NULL); }
|
||||
virtual ByteCodeModule *getByteCode() { ASSERT(!isNative()); return mByteCode; }
|
||||
virtual NativeCode *getNativeCode() { ASSERT(isNative()); return mCode; }
|
||||
virtual ParameterBarrel *getParameterBarrel()
|
||||
{ return mParameterBarrel; }
|
||||
virtual Activation *getActivation() { return &mActivation; }
|
||||
|
||||
virtual JSType *getResultType() { return mResultType; }
|
||||
virtual JSType *getArgType(uint32 a) { ASSERT(mArguments && (a < (mRequiredArgs + mOptionalArgs))); return mArguments[a].mType; }
|
||||
@ -1284,10 +1292,12 @@ XXX ...couldn't get this to work...
|
||||
bool isNative() { return mFunction->isNative(); }
|
||||
bool isPrototype() { return mFunction->isPrototype(); }
|
||||
bool isConstructor() { return mFunction->isConstructor(); }
|
||||
bool isMethod() { return mFunction->isMethod(); }
|
||||
ByteCodeModule *getByteCode() { return mFunction->getByteCode(); }
|
||||
NativeCode *getNativeCode() { return mFunction->getNativeCode(); }
|
||||
ParameterBarrel *getParameterBarrel()
|
||||
{ return mFunction->mParameterBarrel; }
|
||||
Activation *getActivation() { return &mFunction->mActivation; }
|
||||
JSType *getResultType() { return mFunction->getResultType(); }
|
||||
JSType *getArgType(uint32 a) { return mFunction->getArgType(a); }
|
||||
bool argHasInitializer(uint32 a){ return mFunction->argHasInitializer(a); }
|
||||
@ -1316,6 +1326,12 @@ XXX ...couldn't get this to work...
|
||||
{ mFunction->setProperty(cx, name, names, v); }
|
||||
bool hasProperty(const String &name, NamespaceList *names, Access acc, PropertyIterator *p)
|
||||
{ return mFunction->hasProperty(name, names, acc, p); }
|
||||
bool hasOwnProperty(const String &name, NamespaceList *names, Access acc, PropertyIterator *p)
|
||||
{ return mFunction->hasOwnProperty(name, names, acc, p); }
|
||||
PropertyIterator findNamespacedProperty(const String &name, NamespaceList *names)
|
||||
{ return mFunction->findNamespacedProperty(name, names); }
|
||||
bool deleteProperty(const String &name, NamespaceList *names)
|
||||
{ return mFunction->deleteProperty(name, names); }
|
||||
|
||||
JSFunction *getFunction() { return mFunction; }
|
||||
|
||||
|
@ -145,10 +145,12 @@ static JSValue Math_log(Context *cx, const JSValue& /*thisValue*/, JSValue *argv
|
||||
static JSValue Math_max(Context *cx, const JSValue& /*thisValue*/, JSValue *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return kNaNValue;
|
||||
return kNegativeInfinity;
|
||||
float64 result = argv[0].toNumber(cx).f64;
|
||||
if (JSDOUBLE_IS_NaN(result)) return kNaNValue;
|
||||
for (uint32 i = 1; i < argc; ++i) {
|
||||
float64 arg = argv[i].toNumber(cx).f64;
|
||||
if (JSDOUBLE_IS_NaN(arg)) return kNaNValue;
|
||||
if (arg > result)
|
||||
result = arg;
|
||||
}
|
||||
@ -157,11 +159,13 @@ static JSValue Math_max(Context *cx, const JSValue& /*thisValue*/, JSValue *argv
|
||||
static JSValue Math_min(Context *cx, const JSValue& /*thisValue*/, JSValue *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return kNaNValue;
|
||||
return kPositiveInfinity;
|
||||
float64 result = argv[0].toNumber(cx).f64;
|
||||
if (JSDOUBLE_IS_NaN(result)) return kNaNValue;
|
||||
for (uint32 i = 1; i < argc; ++i) {
|
||||
float64 arg = argv[i].toNumber(cx).f64;
|
||||
if (arg < result)
|
||||
if (JSDOUBLE_IS_NaN(arg)) return kNaNValue;
|
||||
if ((arg < result) || (JSDOUBLE_IS_POSZERO(result) && JSDOUBLE_IS_NEGZERO(arg)))
|
||||
result = arg;
|
||||
}
|
||||
return JSValue(result);
|
||||
@ -220,25 +224,26 @@ struct {
|
||||
struct MathObjectFunctionDef {
|
||||
char *name;
|
||||
JSFunction::NativeCode *imp;
|
||||
uint32 length;
|
||||
} MathObjectFunctions[] = {
|
||||
{ "abs", Math_abs },
|
||||
{ "acos", Math_acos },
|
||||
{ "asin", Math_asin },
|
||||
{ "atan", Math_atan },
|
||||
{ "atan2", Math_atan2 },
|
||||
{ "ceil", Math_ceil },
|
||||
{ "cos", Math_cos },
|
||||
{ "exp", Math_exp },
|
||||
{ "floor", Math_floor },
|
||||
{ "log", Math_log },
|
||||
{ "max", Math_max },
|
||||
{ "min", Math_min },
|
||||
{ "pow", Math_pow },
|
||||
{ "random", Math_random },
|
||||
{ "round", Math_round },
|
||||
{ "sin", Math_sin },
|
||||
{ "sqrt", Math_sqrt },
|
||||
{ "tan", Math_tan },
|
||||
{ "abs", Math_abs, 1 },
|
||||
{ "acos", Math_acos, 1 },
|
||||
{ "asin", Math_asin, 1 },
|
||||
{ "atan", Math_atan, 1 },
|
||||
{ "atan2", Math_atan2, 2 },
|
||||
{ "ceil", Math_ceil, 1 },
|
||||
{ "cos", Math_cos, 1 },
|
||||
{ "exp", Math_exp, 1 },
|
||||
{ "floor", Math_floor, 1 },
|
||||
{ "log", Math_log, 1 },
|
||||
{ "max", Math_max, 2 },
|
||||
{ "min", Math_min, 2 },
|
||||
{ "pow", Math_pow, 2 },
|
||||
{ "random", Math_random, 1 },
|
||||
{ "round", Math_round, 1 },
|
||||
{ "sin", Math_sin, 1 },
|
||||
{ "sqrt", Math_sqrt, 1 },
|
||||
{ "tan", Math_tan, 1 },
|
||||
};
|
||||
|
||||
void initMathObject(Context *cx, JSObject *mathObj)
|
||||
@ -246,13 +251,15 @@ void initMathObject(Context *cx, JSObject *mathObj)
|
||||
uint32 i;
|
||||
for (i = 0; i < M_CONSTANTS_COUNT; i++)
|
||||
mathObj->defineVariable(cx, widenCString(MathObjectConstants[i].name),
|
||||
(NamespaceList *)(NULL), Property::NoAttribute,
|
||||
(NamespaceList *)(NULL), Property::ReadOnly | Property::DontDelete,
|
||||
Number_Type, JSValue(MathObjectConstants[i].value));
|
||||
|
||||
for (i = 0; i < sizeof(MathObjectFunctions) / sizeof(MathObjectFunctionDef); i++) {
|
||||
JSFunction *f = new JSFunction(cx, MathObjectFunctions[i].imp, Number_Type);
|
||||
f->setArgCounts(cx, MathObjectFunctions[i].length, 0, false);
|
||||
mathObj->defineVariable(cx, widenCString(MathObjectFunctions[i].name),
|
||||
(NamespaceList *)(NULL), Property::NoAttribute, Number_Type, JSValue(f));
|
||||
(NamespaceList *)(NULL), Property::ReadOnly | Property::DontDelete,
|
||||
Number_Type, JSValue(f));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ static JSValue String_split(Context *cx, const JSValue& thisValue, JSValue *argv
|
||||
{
|
||||
ContextStackReplacement csr(cx);
|
||||
|
||||
ASSERT(thisValue.isObject());
|
||||
ASSERT(thisValue.isObject() || thisValue.isFunction() || thisValue.isType());
|
||||
JSValue S = thisValue.toString(cx);
|
||||
|
||||
JSArrayInstance *A = (JSArrayInstance *)Array_Type->newInstance(cx);
|
||||
@ -147,11 +147,13 @@ static JSValue String_split(Context *cx, const JSValue& thisValue, JSValue *argv
|
||||
if (lim == 0)
|
||||
return JSValue(A);
|
||||
|
||||
/* XXX standard requires this, but Monkey doesn't do it and the tests break
|
||||
|
||||
if (separatorV.isUndefined()) {
|
||||
A->setProperty(cx, widenCString("0"), NULL, S);
|
||||
return JSValue(A);
|
||||
}
|
||||
|
||||
*/
|
||||
if (s == 0) {
|
||||
MatchResult z;
|
||||
splitMatch(S.string, 0, R, z);
|
||||
@ -194,7 +196,7 @@ step11:
|
||||
|
||||
static JSValue String_charAt(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
{
|
||||
ASSERT(thisValue.isObject());
|
||||
ASSERT(thisValue.isObject() || thisValue.isFunction() || thisValue.isType());
|
||||
const String *str = thisValue.toString(cx).string;
|
||||
|
||||
uint32 pos = 0;
|
||||
@ -210,7 +212,7 @@ static JSValue String_charAt(Context *cx, const JSValue& thisValue, JSValue *arg
|
||||
|
||||
static JSValue String_charCodeAt(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
{
|
||||
ASSERT(thisValue.isObject());
|
||||
ASSERT(thisValue.isObject() || thisValue.isFunction() || thisValue.isType());
|
||||
const String *str = thisValue.toString(cx).string;
|
||||
|
||||
uint32 pos = 0;
|
||||
@ -225,7 +227,7 @@ static JSValue String_charCodeAt(Context *cx, const JSValue& thisValue, JSValue
|
||||
|
||||
static JSValue String_concat(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
{
|
||||
ASSERT(thisValue.isObject());
|
||||
ASSERT(thisValue.isObject() || thisValue.isFunction() || thisValue.isType());
|
||||
const String *str = thisValue.toString(cx).string;
|
||||
String *result = new String(*str);
|
||||
|
||||
@ -238,7 +240,7 @@ static JSValue String_concat(Context *cx, const JSValue& thisValue, JSValue *arg
|
||||
|
||||
static JSValue String_indexOf(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
{
|
||||
ASSERT(thisValue.isObject());
|
||||
ASSERT(thisValue.isObject() || thisValue.isFunction() || thisValue.isType());
|
||||
if (argc == 0)
|
||||
return JSValue(-1.0);
|
||||
|
||||
@ -251,10 +253,10 @@ static JSValue String_indexOf(Context *cx, const JSValue& thisValue, JSValue *ar
|
||||
if (arg1 < 0)
|
||||
pos = 0;
|
||||
else
|
||||
if (toUInt32(arg1) >= str->size())
|
||||
if (arg1 >= str->size())
|
||||
pos = str->size();
|
||||
else
|
||||
pos = toUInt32(arg1);
|
||||
pos = arg1;
|
||||
}
|
||||
pos = str->find(*searchStr, pos);
|
||||
if (pos == String::npos)
|
||||
@ -264,27 +266,26 @@ static JSValue String_indexOf(Context *cx, const JSValue& thisValue, JSValue *ar
|
||||
|
||||
static JSValue String_lastIndexOf(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
{
|
||||
ASSERT(thisValue.isObject());
|
||||
ASSERT(thisValue.isObject() || thisValue.isFunction() || thisValue.isType());
|
||||
if (argc == 0)
|
||||
return JSValue(-1.0);
|
||||
|
||||
const String *str = thisValue.toString(cx).string;
|
||||
const String *searchStr = argv[0].toString(cx).string;
|
||||
uint32 pos = 0;
|
||||
uint32 pos = str->size();
|
||||
|
||||
if (argc > 1) {
|
||||
float64 fpos = argv[1].toNumber(cx).f64;
|
||||
if (fpos != fpos)
|
||||
if (JSDOUBLE_IS_NaN(fpos))
|
||||
pos = str->size();
|
||||
else {
|
||||
int32 arg1 = (int32)(fpos);
|
||||
if (arg1 < 0)
|
||||
if (fpos < 0)
|
||||
pos = 0;
|
||||
else
|
||||
if (toUInt32(arg1) >= str->size())
|
||||
if (fpos >= str->size())
|
||||
pos = str->size();
|
||||
else
|
||||
pos = toUInt32(arg1);
|
||||
pos = (int32)(fpos);
|
||||
}
|
||||
}
|
||||
pos = str->rfind(*searchStr, pos);
|
||||
@ -300,7 +301,7 @@ static JSValue String_localeCompare(Context * /*cx*/, const JSValue& /*thisValue
|
||||
|
||||
static JSValue String_toLowerCase(Context *cx, const JSValue& thisValue, JSValue * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
ASSERT(thisValue.isObject());
|
||||
ASSERT(thisValue.isObject() || thisValue.isFunction() || thisValue.isType());
|
||||
JSValue S = thisValue.toString(cx);
|
||||
|
||||
String *result = new String(*S.string);
|
||||
@ -312,7 +313,7 @@ static JSValue String_toLowerCase(Context *cx, const JSValue& thisValue, JSValue
|
||||
|
||||
static JSValue String_toUpperCase(Context *cx, const JSValue& thisValue, JSValue * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
ASSERT(thisValue.isObject());
|
||||
ASSERT(thisValue.isObject() || thisValue.isFunction() || thisValue.isType());
|
||||
JSValue S = thisValue.toString(cx);
|
||||
|
||||
String *result = new String(*S.string);
|
||||
@ -324,7 +325,7 @@ static JSValue String_toUpperCase(Context *cx, const JSValue& thisValue, JSValue
|
||||
|
||||
static JSValue String_slice(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
{
|
||||
ASSERT(thisValue.isObject());
|
||||
ASSERT(thisValue.isObject() || thisValue.isFunction() || thisValue.isType());
|
||||
const String *sourceString = thisValue.toString(cx).string;
|
||||
|
||||
uint32 sourceLength = sourceString->size();
|
||||
@ -375,34 +376,42 @@ static JSValue String_slice(Context *cx, const JSValue& thisValue, JSValue *argv
|
||||
|
||||
static JSValue String_substring(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
{
|
||||
ASSERT(thisValue.isObject());
|
||||
ASSERT(thisValue.isObject() || thisValue.isFunction() || thisValue.isType());
|
||||
const String *sourceString = thisValue.toString(cx).string;
|
||||
|
||||
uint32 sourceLength = sourceString->size();
|
||||
uint32 start, end;
|
||||
|
||||
if (argc > 0) {
|
||||
int32 arg0 = (int32)(argv[0].toInt32(cx).f64);
|
||||
if (arg0 < 0)
|
||||
float64 farg0 = argv[0].toNumber(cx).f64;
|
||||
if (JSDOUBLE_IS_NaN(farg0) || (farg0 < 0))
|
||||
start = 0;
|
||||
else
|
||||
if (toUInt32(arg0) < sourceLength)
|
||||
start = toUInt32(arg0);
|
||||
else
|
||||
else {
|
||||
if (!JSDOUBLE_IS_FINITE(farg0))
|
||||
start = sourceLength;
|
||||
else {
|
||||
start = JSValue::float64ToUInt32(farg0);
|
||||
if (start > sourceLength)
|
||||
start = sourceLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
start = 0;
|
||||
|
||||
if (argc > 1) {
|
||||
int32 arg1 = (int32)(argv[1].toInt32(cx).f64);
|
||||
if (arg1 < 0)
|
||||
float64 farg1 = argv[1].toNumber(cx).f64;
|
||||
if (JSDOUBLE_IS_NaN(farg1) || (farg1 < 0))
|
||||
end = 0;
|
||||
else
|
||||
if (toUInt32(arg1) < sourceLength)
|
||||
end = toUInt32(arg1);
|
||||
else
|
||||
else {
|
||||
if (!JSDOUBLE_IS_FINITE(farg1))
|
||||
end = sourceLength;
|
||||
else {
|
||||
end = JSValue::float64ToUInt32(farg1);
|
||||
if (end > sourceLength)
|
||||
end = sourceLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
end = sourceLength;
|
||||
@ -427,10 +436,10 @@ Context::PrototypeFunctions *getStringProtos()
|
||||
{ "charCodeAt", Number_Type, 1, String_charCodeAt },
|
||||
{ "concat", String_Type, 1, String_concat },
|
||||
{ "indexOf", Number_Type, 1, String_indexOf },
|
||||
{ "lastIndexOf", Number_Type, 1, String_lastIndexOf },
|
||||
{ "lastIndexOf", Number_Type, 2, String_lastIndexOf }, // XXX ECMA spec says 1, but tests want 2 XXX
|
||||
{ "localeCompare", Number_Type, 1, String_localeCompare },
|
||||
{ "slice", String_Type, 2, String_slice },
|
||||
{ "split", Array_Type, 2, String_split },
|
||||
{ "split", Array_Type, 1, String_split }, // XXX ECMA spec says 2, but tests want 1 XXX
|
||||
{ "substring", String_Type, 2, String_substring },
|
||||
{ "toSource", String_Type, 0, String_toString },
|
||||
{ "toLocaleUpperCase", String_Type, 0, String_toUpperCase }, // (sic)
|
||||
|
@ -1683,6 +1683,8 @@ double JS::stringToDouble(const char16 *str, const char16 *strEnd, const char16
|
||||
double value = strToDouble(cstr.get(), estr);
|
||||
ptrdiff_t i = estr - cstr.get();
|
||||
numEnd = i ? str1 + i : str;
|
||||
if ((value == 0.0) && (i == 0))
|
||||
return nan;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,9 @@ namespace JS2Runtime {
|
||||
Public = 0x00002000,
|
||||
Private = 0x00004000,
|
||||
Final = 0x00008000,
|
||||
Const = 0x00010000
|
||||
Const = 0x00010000,
|
||||
DontDelete = 0x00020000,
|
||||
ReadOnly = 0x00040000
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user