Fixed parameter handling to match new syntax.

This commit is contained in:
rogerl%netscape.com 2001-12-18 17:21:06 +00:00
Родитель 58605d70d3
Коммит 3f2aa66262
6 изменённых файлов: 249 добавлений и 205 удалений

Просмотреть файл

@ -602,7 +602,7 @@ void ByteCodeGen::genCodeForFunction(FunctionDefinition &f, size_t pos, JSFuncti
// Make sure there's a default constructor with 0 (required) parameters
JSFunction *superConstructor = superClass->getDefaultConstructor();
if (superConstructor) {
if (superConstructor->getRequiredArgumentCount() > 0)
if (superConstructor->getRequiredParameterCount() > 0)
m_cx->reportError(Exception::typeError, "Super class default constructor must be called explicitly - it has required parameters that must be specified", pos);
addOp(LoadThisOp);
addOp(LoadFunctionOp);
@ -641,7 +641,7 @@ void ByteCodeGen::genCodeForFunction(FunctionDefinition &f, size_t pos, JSFuncti
if (v->initializer) {
// this code gets executed if the function is called without
// an argument for this parameter.
fnc->setArgumentInitializer(index, currentOffset());
fnc->setParameterInitializer(index, currentOffset());
genExpr(v->initializer);
addOpSetDepth(ReturnOp, 0);
}
@ -2269,7 +2269,7 @@ BinaryOpEquals:
uint32 reqArgCount = 0;
uint32 optArgCount = 0;
uint32 namedArgCount = 0;
/*
VariableBinding *b = f->function.parameters;
while (b != f->function.optParameters) {
reqArgCount++;
@ -2286,8 +2286,11 @@ BinaryOpEquals:
}
fnc->setArgCounts(m_cx, reqArgCount, optArgCount, namedArgCount,
f->function.restParameter != f->function.namedParameters, f->function.restIsNamed);
*/
fnc->countParameters(m_cx, f->function);
if (mScopeChain->isPossibleUncheckedFunction(&f->function))
if (mScopeChain->isPossibleUncheckedFunction(f->function))
fnc->setIsPrototype(true);
m_cx->buildRuntimeForFunction(f->function, fnc);

Просмотреть файл

@ -275,116 +275,144 @@ JSValue Context::interpret(JS2Runtime::ByteCodeModule *bcm, int offset, ScopeCha
return result;
}
// Assumes arguments are on the top of stack.
// Assumes arguments are on the top of stack. argCount is the number that were pushed by user code
JSValue *Context::buildArgumentBlock(JSFunction *target, uint32 &argCount)
{
JSValue *argBase;
uint32 maxExpectedArgCount = target->getRequiredArgumentCount() + target->getOptionalArgumentCount();
uint32 maxExpectedParameterCount = target->getRequiredParameterCount() + target->getOptionalParameterCount() + target->getNamedParameterCount();
if (target->isChecked()) {
if (argCount < target->getRequiredArgumentCount())
if (argCount < target->getRequiredParameterCount())
reportError(Exception::referenceError, "Insufficient quantity of arguments");
if ((argCount > maxExpectedArgCount) && !target->hasRestParameter())
if ((argCount > maxExpectedParameterCount) && !target->hasRestParameter())
reportError(Exception::referenceError, "Oversufficient quantity of arguments");
}
uint32 i;
uint32 argBlockSize = max(argCount, maxExpectedArgCount) + (target->hasRestParameter() ? 1 : 0);
// room for all required & optional arguments
uint32 argBlockSize = max(argCount, maxExpectedParameterCount) + (target->hasRestParameter() ? 1 : 0);
// room for all required,optional & named arguments
// plus the rest parameter if it exists.
argBase = new JSValue[argBlockSize];
/*
* If the first parameter is required and no positional argument has been supplied for it, then raise an error unless the function
* is unchecked, in which case let undefined be the first parameters value.
*
* If the first parameter is optional and there is a positional argument remaining, use the value of the positional argument
* and raise an error if there is also a named argument with a matching argument name. If there are no remaining positional
* arguments, then if there is a named argument with a matching argument name, use the value of that named argument. Otherwise,
* evaluate the first parameters AssignmentExpression and let it be the first parameters value.
*
* Implicitly coerce the argument (or default) value to type t and bind the parameters Identifier to the result.
*/
uint32 inArgIndex = 0;
uint32 argStart = stackSize() - argCount;
bool *argUsed = new bool[argCount];
for (i = 0; i < argCount; i++)
argUsed[i] = false;
uint32 argStart = stackSize() - argCount;
uint32 argIndex = 0; // the index into argBase, the resolved outgoing arguments
uint32 posArgIndex = 0; // next positional arg from the incoming set
for (i = 0; i < argCount; i++) { // find the first positional (i.e. non-named arg)
JSValue v = getValue(i + argStart);
if (!v.isObject() || (v.object->mType != NamedArgument_Type)) {
posArgIndex = i;
break;
}
}
// for each parameter - see if there's a named arg that matches
// otherwise take the next non-named argument. (unless the parameter
// is an optional one)
while (argIndex < maxExpectedArgCount) {
bool foundNamedArg = false;
// find a matching named argument
for (uint32 i = 0; i < argCount; i++) {
JSValue v = getValue(i + argStart);
if (v.isObject() && (v.object->mType == NamedArgument_Type)) {
NamedArgument *arg = static_cast<NamedArgument *>(v.object);
if (target->findParameterName(arg->mName) == argIndex) {
// mark this arg has having been used
argUsed[i] = true;
foundNamedArg = true;
argBase[argIndex] = arg->mValue;
break;
}
}
}
if (!foundNamedArg) {
if (target->argHasInitializer(argIndex)) {
argBase[argIndex] = target->runArgInitializer(this, argIndex, mThis, argBase, maxExpectedArgCount);
}
else {
if (posArgIndex < argCount) {
argUsed[posArgIndex] = true;
argBase[argIndex] = getValue(posArgIndex++ + argStart);
argUsed[i] = false;
uint32 restParameterIndex;
uint32 pCount = maxExpectedParameterCount + (target->hasRestParameter() ? 1 : 0);
for (uint32 pIndex = 0; pIndex < pCount; pIndex++) {
bool needDefault = true;
if (target->parameterIsRequired(pIndex)) {
if (inArgIndex < argCount) {
JSValue v = getValue(inArgIndex + argStart);
bool isPositionalArg = !(v.isObject() && (v.object->mType == NamedArgument_Type));
// if the next argument is named, then we've run out of positional args
if (!isPositionalArg) {
if (!target->isChecked())
needDefault = false; // the undefined value is already assigned in the arg block
}
else {
if (target->isChecked())
reportError(Exception::referenceError, "Missing positional argument");
else
argBase[argIndex] = kUndefinedValue;
argBase[pIndex] = getValue(inArgIndex + argStart);
argUsed[inArgIndex++] = true;
needDefault = false;
}
}
if (needDefault)
reportError(Exception::referenceError, "missing required argument");
}
argIndex++;
else {
if (target->parameterIsOptional(pIndex)) {
bool tookPositionalArg = false;
if (inArgIndex < argCount) {
JSValue v = getValue(inArgIndex + argStart);
if (!(v.isObject() && (v.object->mType == NamedArgument_Type))) {
argBase[pIndex] = v;
argUsed[inArgIndex++] = true;
needDefault = false;
}
}
}
else {
if (target->parameterIsNamed(pIndex)) {
const String *parameterName = target->getParameterName(pIndex);
for (uint32 i = inArgIndex; i < argCount; i++) {
if (!argUsed[i]) {
JSValue v = getValue(i + argStart);
if (v.isObject() && (v.object->mType == NamedArgument_Type)) {
NamedArgument *arg = static_cast<NamedArgument *>(v.object);
if (arg->mName == parameterName) {
argBase[pIndex] = arg->mValue;
argUsed[i] = true;
needDefault = false;
break;
}
}
}
}
}
else
restParameterIndex = pIndex;
}
}
if (needDefault)
if (target->parameterHasInitializer(pIndex))
argBase[pIndex] = target->runParameterInitializer(this, pIndex, mThis, argBase, maxExpectedParameterCount);
}
// now find a place for any left-overs:
/*
* If there is a RestParameter with a type that does not allow the dynamic addition of named properties and one or more of the
* remaining arguments is named, raise an error.
*
* If there is a RestParameter with an Identifier, bind that Identifier to an array of the remaining positional and/or named
* arguments. The remaining positional arguments are assigned indices starting from 0.
*
* If there is no RestParameter and any arguments remain, raise an error unless the function is unchecked.
*/
JSValue restArgument;
if (target->hasRestParameter() && target->getRestParameterName()) {
restArgument = target->getRestParameterType()->newInstance(this);
argBase[maxExpectedArgCount] = JSValue(restArgument);
bool haveRestArg = false;
if (target->hasRestParameter() && target->getParameterName(restParameterIndex)) {
restArgument = target->getParameterType(restParameterIndex)->newInstance(this);
argBase[restParameterIndex] = JSValue(restArgument);
haveRestArg = true;
}
posArgIndex = 0; // re-number the non-named arguments that end up in the rest arg
// now find a place for any left-overs
inArgIndex = 0; // re-number the non-named arguments that end up in the rest arg
for (i = 0; i < argCount; i++) {
if (!argUsed[i]) {
JSValue v = getValue(i + argStart);
if (v.isObject() && (v.object->mType == NamedArgument_Type)) {
bool isNamedArg = v.isObject() && (v.object->mType == NamedArgument_Type);
if (isNamedArg) {
NamedArgument *arg = static_cast<NamedArgument *>(v.object);
// if this argument matches a parameter name, that's bad because
// it's a duplicate case
if (target->findParameterName(arg->mName) != NotABanana)
reportError(Exception::referenceError, "Duplicate named argument");
else {
if (target->hasRestParameter()) {
if (!restArgument.isUndefined())
// XXX is it an error to have duplicate named rest properties?
restArgument.object->setProperty(this, *arg->mName, (NamespaceList *)(NULL), arg->mValue);
}
else
reportError(Exception::referenceError, "Unknown named argument, no rest argument");
}
if (haveRestArg)
restArgument.object->setProperty(this, *arg->mName, (NamespaceList *)(NULL), arg->mValue);
else
reportError(Exception::referenceError, "Unused named argument, no rest argument");
}
else {
if (target->hasRestParameter()) {
if (!restArgument.isUndefined()) {
const String *id = numberToString(posArgIndex++);
restArgument.object->setProperty(this, *id, (NamespaceList *)(NULL), v);
}
if (haveRestArg) {
const String *id = numberToString(inArgIndex++);
restArgument.object->setProperty(this, *id, (NamespaceList *)(NULL), v);
}
else {
if (target->isChecked())
reportError(Exception::referenceError, "Extra argument, no rest argument");
else {
JSValue v = getValue(i + argStart);
if (v.isObject() && (v.object->mType == NamedArgument_Type)) {
if (isNamedArg) {
NamedArgument *arg = static_cast<NamedArgument *>(v.object);
argBase[i] = arg->mValue;
}
@ -395,6 +423,7 @@ JSValue *Context::buildArgumentBlock(JSFunction *target, uint32 &argCount)
}
}
}
argCount = argBlockSize;
return argBase;
}

Просмотреть файл

@ -350,7 +350,7 @@ Reference *JSObject::genReference(bool hasBase, const String& name, NamespaceLis
return new GetterFunctionReference(prop->mData.fPair.getterF, prop->mAttributes);
else {
JSFunction *f = prop->mData.fPair.setterF;
return new SetterFunctionReference(f, f->getArgType(0), prop->mAttributes);
return new SetterFunctionReference(f, f->getParameterType(0), prop->mAttributes);
}
default:
NOT_REACHED("bad storage kind");
@ -948,15 +948,15 @@ JS2Runtime::ByteCodeModule *Context::genCode(StmtNode *p, const String &/*source
the function does not have a declared return type;
the function is not a getter or setter.
*/
bool ScopeChain::isPossibleUncheckedFunction(FunctionDefinition *f)
bool ScopeChain::isPossibleUncheckedFunction(FunctionDefinition &f)
{
bool result = false;
if ((f->resultType == NULL)
&& (f->optParameters == NULL)
&& (f->prefix == FunctionName::normal)
if ((f.resultType == NULL)
&& (f.optParameters == NULL)
&& (f.prefix == FunctionName::normal)
&& (topClass() == NULL)) {
result = true;
VariableBinding *b = f->parameters;
VariableBinding *b = f.parameters;
while (b) {
if (b->type != NULL) {
result = false;
@ -968,6 +968,29 @@ bool ScopeChain::isPossibleUncheckedFunction(FunctionDefinition *f)
return result;
}
void JSFunction::countParameters(Context *cx, FunctionDefinition &f)
{
uint32 requiredParameterCount = 0;
uint32 optionalParameterCount = 0;
uint32 namedParameterCount = 0;
VariableBinding *b = f.parameters;
while (b != f.optParameters) {
requiredParameterCount++;
b = b->next;
}
while (b != f.restParameter) {
optionalParameterCount++;
b = b->next;
}
b = f.namedParameters;
while (b) {
namedParameterCount++;
b = b->next;
}
setParameterCounts(cx, requiredParameterCount, optionalParameterCount, namedParameterCount, f.restParameter != f.namedParameters);
}
// The first pass over the tree - it just installs the names of each declaration
void ScopeChain::collectNames(StmtNode *p)
{
@ -1094,36 +1117,17 @@ void ScopeChain::collectNames(StmtNode *p)
*/
if (!isPrototype
&& (!isOperator)
&& isPossibleUncheckedFunction(&f->function)) {
&& isPossibleUncheckedFunction(f->function)) {
isPrototype = true;
fnc->setIsUnchecked();
}
fnc->setIsPrototype(isPrototype);
fnc->setIsConstructor(isConstructor);
fnc->setFunctionName(&f->function);
fnc->setFunctionName(f->function);
f->mFunction = fnc;
uint32 reqArgCount = 0;
uint32 optArgCount = 0;
uint32 namedArgCount = 0;
VariableBinding *b = f->function.parameters;
while (b != f->function.optParameters) {
reqArgCount++;
b = b->next;
}
while (b != f->function.restParameter) {
optArgCount++;
b = b->next;
}
b = f->function.namedParameters;
while (b) {
namedArgCount++;
b = b->next;
}
fnc->setArgCounts(m_cx, reqArgCount, optArgCount, namedArgCount,
f->function.restParameter != f->function.namedParameters, f->function.restIsNamed);
fnc->countParameters(m_cx, f->function);
if (isOperator) {
// no need to do anything yet, all operators are 'pre-declared'
@ -1203,7 +1207,7 @@ void ScopeChain::collectNames(StmtNode *p)
// make a function into a const declaration, but only if any types
// have been specified - otherwise it's a 1.5 atyle definition and
// duplicates are allowed
if (!isPossibleUncheckedFunction(&f->function))
if (!isPossibleUncheckedFunction(f->function))
f->attributeValue->mTrueFlags |= Property::Const;
if (isStatic)
defineStaticMethod(m_cx, name, f, fnc);
@ -1400,7 +1404,7 @@ Reference *JSType::genReference(bool hasBase, const String& name, NamespaceList
return new GetterFunctionReference(prop->mData.fPair.getterF, prop->mAttributes);
else {
JSFunction *f = prop->mData.fPair.setterF;
return new SetterFunctionReference(f, f->getArgType(0), prop->mAttributes);
return new SetterFunctionReference(f, f->getParameterType(0), prop->mAttributes);
}
case ValuePointer:
return new StaticFieldReference(name, acc, this, prop->mType, prop->mAttributes);
@ -1410,7 +1414,7 @@ Reference *JSType::genReference(bool hasBase, const String& name, NamespaceList
return new GetterMethodReference(prop->mData.iPair.getterI, this, prop->mType, prop->mAttributes);
else {
JSFunction *f = mMethods[prop->mData.iPair.setterI];
return new SetterMethodReference(prop->mData.iPair.setterI, this, f->getArgType(0), prop->mAttributes);
return new SetterMethodReference(prop->mData.iPair.setterI, this, f->getParameterType(0), prop->mAttributes);
}
case Slot:
return new FieldReference(prop->mData.index, acc, prop->mType, prop->mAttributes);
@ -1679,9 +1683,18 @@ void Context::buildRuntimeForStmt(StmtNode *p)
VariableBinding *v = f->function.parameters;
uint32 parameterCount = 0;
JSFunction::ParameterFlag flag = JSFunction::RequiredParameter;
while (v) {
// XXX if no type is specified for the rest parameter - is it Array?
fnc->setArgument(parameterCount++, v->name, mScopeChain->extractType(v->type));
if (v == f->function.optParameters)
flag = JSFunction::OptionalParameter;
else
if (v == f->function.restParameter)
flag = JSFunction::RestParameter;
else
if (v == f->function.namedParameters)
flag = JSFunction::NamedParameter;
fnc->setParameter(parameterCount++, v->name, mScopeChain->extractType(v->type), flag);
v = v->next;
}
@ -1926,28 +1939,10 @@ static JSValue Function_Constructor(Context *cx, const JSValue& thisValue, JSVal
fnc = new JSFunction(cx, NULL, cx->mScopeChain);
uint32 reqArgCount = 0;
uint32 optArgCount = 0;
uint32 namedArgCount = 0;
fnc->countParameters(cx, f->function);
VariableBinding *b = f->function.parameters;
while (b != f->function.optParameters) {
reqArgCount++;
b = b->next;
}
while (b != f->function.restParameter) {
optArgCount++;
b = b->next;
}
b = f->function.namedParameters;
while (b) {
namedArgCount++;
b = b->next;
}
fnc->setArgCounts(cx, reqArgCount, optArgCount, namedArgCount,
f->function.restParameter != f->function.namedParameters, f->function.restIsNamed);
if (cx->mScopeChain->isPossibleUncheckedFunction(&f->function)) {
if (cx->mScopeChain->isPossibleUncheckedFunction(f->function)) {
fnc->setIsPrototype(true);
fnc->setIsUnchecked();
}
@ -2463,15 +2458,15 @@ JSFunction::JSFunction(Context *, JSType *resultType, ScopeChain *scopeChain)
mByteCode(NULL),
mCode(NULL),
mResultType(resultType),
mRequiredArgs(0),
mOptionalArgs(0),
mArguments(NULL),
mRequiredParameters(0),
mOptionalParameters(0),
mNamedParameters(0),
mParameters(NULL),
mScopeChain(NULL),
mIsPrototype(false),
mIsConstructor(false),
mIsChecked(true),
mHasRestParameter(false),
mRestParameterName(NULL),
mClass(NULL),
mFunctionName(NULL)
{
@ -2490,15 +2485,15 @@ JSFunction::JSFunction(Context *, NativeCode *code, JSType *resultType)
mByteCode(NULL),
mCode(code),
mResultType(resultType),
mRequiredArgs(0),
mOptionalArgs(0),
mArguments(NULL),
mRequiredParameters(0),
mOptionalParameters(0),
mNamedParameters(0),
mParameters(NULL),
mScopeChain(NULL),
mIsPrototype(false),
mIsConstructor(false),
mIsChecked(false), // native functions aren't checked (?)
mHasRestParameter(false),
mRestParameterName(NULL),
mClass(NULL),
mFunctionName(NULL)
{
@ -2507,34 +2502,24 @@ JSFunction::JSFunction(Context *, NativeCode *code, JSType *resultType)
mActivation.mContainer = this;
}
JSValue JSFunction::runArgInitializer(Context *cx, uint32 a, const JSValue& thisValue, JSValue *argv, uint32 argc)
JSValue JSFunction::runParameterInitializer(Context *cx, uint32 a, const JSValue& thisValue, JSValue *argv, uint32 argc)
{
ASSERT(mArguments && (a < (mRequiredArgs + mOptionalArgs)));
return cx->interpret(getByteCode(), (int32)mArguments[a].mInitializer, getScopeChain(), thisValue, argv, argc);
ASSERT(mParameters && (a < maxParameterIndex()));
return cx->interpret(getByteCode(), (int32)mParameters[a].mInitializer, getScopeChain(), thisValue, argv, argc);
}
void JSFunction::setArgCounts(Context *cx, uint32 r, uint32 o, uint32 n, bool hasRest, bool restIsNamed)
void JSFunction::setParameterCounts(Context *cx, uint32 r, uint32 o, uint32 n, bool hasRest)
{
mHasRestParameter = hasRest;
mRestIsNamed = restIsNamed;
mRequiredArgs = r;
mOptionalArgs = o;
mNamedArgs = n;
mArguments = new ArgumentData[mRequiredArgs + mOptionalArgs + ((hasRest) ? 1 : 0)];
defineVariable(cx, cx->Length_StringAtom, (NamespaceList *)NULL, Property::DontDelete | Property::ReadOnly, Number_Type, JSValue((float64)mRequiredArgs));
mRequiredParameters = r;
mOptionalParameters = o;
mNamedParameters = n;
mParameters = new ParameterData[mRequiredParameters + mOptionalParameters + + mNamedParameters + ((hasRest) ? 1 : 0)];
defineVariable(cx, cx->Length_StringAtom, (NamespaceList *)NULL, Property::DontDelete | Property::ReadOnly, Number_Type, JSValue((float64)mRequiredParameters));
}
uint32 JSFunction::findParameterName(const String *name)
{
uint32 maxArgs = mRequiredArgs + mOptionalArgs + ((mHasRestParameter) ? 1 : 0);
ASSERT(mArguments || (maxArgs == 0));
for (uint32 i = 0; i < maxArgs; i++) {
if (mArguments[i].mName->compare(*name) == 0)
return i;
}
return NotABanana;
}
void Context::assureStackSpace(uint32 s)
{
@ -2568,7 +2553,7 @@ void Context::initClass(JSType *type, ClassDef *cdef, PrototypeFunctions *pdef)
// fun->setClass(type); don't do this, it makes the function a method
StringAtom *name = &mWorld.identifiers[widenCString(pdef->mDef[i].name)];
fun->setFunctionName(name);
fun->setArgCounts(this, pdef->mDef[i].length, 0, 0, false, false);
fun->setParameterCounts(this, pdef->mDef[i].length, 0, 0, false);
type->mPrototypeObject->defineVariable(this, *name,
(NamespaceList *)(NULL),
Property::NoAttribute,
@ -2978,7 +2963,7 @@ Context::Context(JSObject **global, World &world, Arena &a, Pragma::Flags flags)
for (i = 0; i < (sizeof(globalObjectFunctions) / sizeof(ProtoFunDef)); i++) {
x = new JSFunction(this, globalObjectFunctions[i].imp, globalObjectFunctions[i].result);
x->setArgCounts(this, globalObjectFunctions[i].length, 0, 0, false, false);
x->setParameterCounts(this, globalObjectFunctions[i].length, 0, 0, false);
x->setIsPrototype(true);
getGlobalObject()->defineVariable(this, widenCString(globalObjectFunctions[i].name), (NamespaceList *)(NULL), Property::NoAttribute, globalObjectFunctions[i].result, JSValue(x));
}

Просмотреть файл

@ -1129,7 +1129,7 @@ XXX ...couldn't get this to work...
return obj->isNestedFunction();
}
bool isPossibleUncheckedFunction(FunctionDefinition *f);
bool isPossibleUncheckedFunction(FunctionDefinition &f);
void defineTempVariable(Context *cx, Reference *&readRef, Reference *&writeRef, JSType *type)
{
@ -1187,12 +1187,15 @@ XXX ...couldn't get this to work...
JSFunction() : JSObject(Function_Type), mActivation() { mActivation.mContainer = this; mPrototype = Function_Type->mPrototypeObject; } // for JSBoundFunction (XXX ask Patrick about this structure)
public:
class ArgumentData {
typedef enum { Invalid, RequiredParameter, OptionalParameter, RestParameter, NamedParameter } ParameterFlag;
class ParameterData {
public:
ArgumentData() : mName(NULL), mType(NULL), mInitializer((uint32)(-1)) { }
ParameterData() : mName(NULL), mType(NULL), mInitializer((uint32)(-1)), mFlag(Invalid) { }
const String *mName;
JSType *mType;
uint32 mInitializer;
ParameterFlag mFlag;
};
@ -1210,18 +1213,22 @@ XXX ...couldn't get this to work...
void operator delete(void* t) { trace_release("JSFunction", t); STD::free(t); }
#endif
#ifdef DEBUG
uint32 maxParameterIndex() { return mRequiredParameters + mOptionalParameters + mNamedParameters + ((mHasRestParameter) ? 1 : 0); }
#endif
void setByteCode(ByteCodeModule *b) { ASSERT(!isNative()); mByteCode = b; }
void setResultType(JSType *r) { mResultType = r; }
void setArgCounts(Context *cx, uint32 r, uint32 o, uint32 n, bool hasRest, bool restIsNamed);
void setArgument(uint32 index, const String *n, JSType *t)
{ ASSERT(mArguments && (index < (mRequiredArgs + mOptionalArgs + ((mHasRestParameter) ? 1 : 0) ))); mArguments[index].mType = t; mArguments[index].mName = n; }
void setArgumentInitializer(uint32 index, uint32 offset)
{ ASSERT(mArguments && (index < (mRequiredArgs + mOptionalArgs + ((mHasRestParameter) ? 1 : 0) ))); mArguments[index].mInitializer = offset; }
void setParameterCounts(Context *cx, uint32 r, uint32 o, uint32 n, bool hasRest);
void setParameter(uint32 index, const String *n, JSType *t, ParameterFlag flag)
{ ASSERT(mParameters && (index < maxParameterIndex()));
mParameters[index].mType = t; mParameters[index].mName = n; mParameters[index].mFlag = flag; }
void setParameterInitializer(uint32 index, uint32 offset)
{ ASSERT(mParameters && (index < maxParameterIndex())); mParameters[index].mInitializer = offset; }
void setIsPrototype(bool i) { mIsPrototype = i; }
void setIsConstructor(bool i) { mIsConstructor = i; }
void setIsUnchecked() { mIsChecked = false; }
void setFunctionName(FunctionName *n) { mFunctionName = new FunctionName(); mFunctionName->prefix = n->prefix; mFunctionName->name = n->name; }
void setFunctionName(FunctionName &n) { mFunctionName = new FunctionName(); mFunctionName->prefix = n.prefix; mFunctionName->name = n.name; }
void setFunctionName(const StringAtom *n)
{ mFunctionName = new FunctionName(); mFunctionName->name = n; }
void setClass(JSType *c) { mClass = c; }
@ -1237,47 +1244,61 @@ XXX ...couldn't get this to work...
{ 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; }
virtual bool argHasInitializer(uint32 a){ ASSERT(mArguments && (a < (mRequiredArgs + mOptionalArgs))); return (mArguments[a].mInitializer != (uint32)(-1)); }
virtual JSValue runArgInitializer(Context *cx, uint32 a, const JSValue& thisValue, JSValue *argv, uint32 argc);
virtual ScopeChain *getScopeChain() { return mScopeChain; }
virtual JSValue getThisValue() { return kNullValue; }
virtual JSType *getClass() { return mClass; }
virtual FunctionName *getFunctionName() { return mFunctionName; }
virtual uint32 findParameterName(const String *name);
virtual uint32 getRequiredArgumentCount()
{ return mRequiredArgs; }
virtual uint32 getOptionalArgumentCount()
{ return mOptionalArgs; }
virtual bool hasOptionalArguments() { return (mOptionalArgs > 0); }
virtual bool isChecked() { return mIsChecked; }
virtual JSType *getResultType() { return mResultType; }
virtual JSType *getParameterType(uint32 a)
{ ASSERT(mParameters && (a < maxParameterIndex())); return mParameters[a].mType; }
virtual bool parameterHasInitializer(uint32 a)
{ ASSERT(mParameters && (a < maxParameterIndex())); return (mParameters[a].mInitializer != (uint32)(-1)); }
virtual JSValue runParameterInitializer(Context *cx, uint32 a, const JSValue& thisValue, JSValue *argv, uint32 argc);
virtual uint32 getRequiredParameterCount()
{ return mRequiredParameters; }
virtual uint32 getOptionalParameterCount()
{ return mOptionalParameters; }
virtual uint32 getNamedParameterCount() { return mNamedParameters; }
virtual bool hasOptionalParameters() { return (mOptionalParameters > 0); }
virtual bool parameterIsRequired(uint32 index)
{ ASSERT(mParameters && (index < maxParameterIndex())); return (mParameters[index].mFlag == RequiredParameter); }
virtual bool parameterIsOptional(uint32 index)
{ ASSERT(mParameters && (index < maxParameterIndex())); return (mParameters[index].mFlag == OptionalParameter); }
virtual bool parameterIsNamed(uint32 index)
{ ASSERT(mParameters && (index < maxParameterIndex())); return (mParameters[index].mFlag == NamedParameter); }
virtual uint32 getRestParameterIndex() { ASSERT(mHasRestParameter); return (mRequiredParameters + mOptionalParameters); }
virtual const String *getParameterName(uint32 index)
{ ASSERT(mParameters && (index < maxParameterIndex())); return mParameters[index].mName; }
virtual bool hasRestParameter() { return mHasRestParameter; }
virtual const String *getRestParameterName()
{ ASSERT(mHasRestParameter); return mArguments[(mRequiredArgs + mOptionalArgs)].mName; }
virtual JSType *getRestParameterType() { ASSERT(mHasRestParameter); return mArguments[(mRequiredArgs + mOptionalArgs)].mType; }
virtual JSFunction *getFunction() { return this; }
bool isEqual(JSFunction *f) { return (getFunction() == f->getFunction()); }
void countParameters(Context *cx, FunctionDefinition &f);
ParameterBarrel *mParameterBarrel;
Activation mActivation; // not used during execution (XXX so maybe we should handle it differently, hmmm?)
private:
ByteCodeModule *mByteCode;
NativeCode *mCode;
JSType *mResultType;
uint32 mRequiredArgs; // total # parameters
uint32 mOptionalArgs;
uint32 mNamedArgs;
ArgumentData *mArguments;
uint32 mRequiredParameters;
uint32 mOptionalParameters;
uint32 mNamedParameters;
ParameterData *mParameters;
ScopeChain *mScopeChain;
bool mIsPrototype; // set for functions with prototype attribute
bool mIsConstructor;
bool mIsChecked;
bool mHasRestParameter;
bool mRestIsNamed;
const String *mRestParameterName;
JSType *mClass; // pointer to owning class if this function is a method
FunctionName *mFunctionName;
};
@ -1303,26 +1324,32 @@ XXX ...couldn't get this to work...
{ 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); }
JSValue runArgInitializer(Context *cx, uint32 a, const JSValue& thisValue, JSValue *argv, uint32 argc)
{ return mFunction->runArgInitializer(cx, a, thisValue, argv, argc); }
JSType *getParameterType(uint32 a) { return mFunction->getParameterType(a); }
bool parameterHasInitializer(uint32 a){ return mFunction->parameterHasInitializer(a); }
JSValue runParameterInitializer(Context *cx, uint32 a, const JSValue& thisValue, JSValue *argv, uint32 argc)
{ return mFunction->runParameterInitializer(cx, a, thisValue, argv, argc); }
ScopeChain *getScopeChain() { return mFunction->getScopeChain(); }
JSValue getThisValue() { return (mThis) ? JSValue(mThis) : kNullValue; }
JSType *getClass() { return mFunction->getClass(); }
FunctionName *getFunctionName() { return mFunction->getFunctionName(); }
uint32 findParameterName(const String *name)
{ return mFunction->findParameterName(name); }
uint32 getRequiredArgumentCount()
{ return mFunction->getRequiredArgumentCount(); }
uint32 getOptionalArgumentCount()
{ return mFunction->getOptionalArgumentCount(); }
bool hasOptionalArguments() { return mFunction->hasOptionalArguments(); }
uint32 getRequiredParameterCount()
{ return mFunction->getRequiredParameterCount(); }
uint32 getOptionalParameterCount()
{ return mFunction->getOptionalParameterCount(); }
uint32 getNamedParameterCount() { return mFunction->getNamedParameterCount(); }
virtual bool parameterIsRequired(uint32 index)
{ return mFunction->parameterIsRequired(index); }
virtual bool parameterIsOptional(uint32 index)
{ return mFunction->parameterIsOptional(index); }
virtual bool parameterIsNamed(uint32 index)
{ return mFunction->parameterIsNamed(index); }
virtual uint32 getRestParameterIndex()
{ return mFunction->getRestParameterIndex(); }
virtual const String *getParameterName(uint32 index)
{ return mFunction->getParameterName(index); }
bool isChecked() { return mFunction->isChecked(); }
bool hasRestParameter() { return mFunction->hasRestParameter(); }
const String *getRestParameterName()
{ return mFunction->getRestParameterName(); }
JSType *getRestParameterType() { return mFunction->getRestParameterType(); }
void getProperty(Context *cx, const String &name, NamespaceList *names)
{ mFunction->getProperty(cx, name, names); }

Просмотреть файл

@ -256,7 +256,7 @@ void initMathObject(Context *cx, JSObject *mathObj)
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, 0, false, false);
f->setParameterCounts(cx, MathObjectFunctions[i].length, 0, 0, false);
mathObj->defineVariable(cx, widenCString(MathObjectFunctions[i].name),
(NamespaceList *)(NULL), Property::ReadOnly | Property::DontDelete,
Number_Type, JSValue(f));

Просмотреть файл

@ -41,7 +41,7 @@ RSC=rc.exe
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /GX /O2 /Ob2 /D "_LIB" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "XP_PC" /YX /FD /c
# ADD CPP /nologo /GR /GX /O2 /Ob2 /D "_LIB" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "XP_PC" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe