int main(int argc, char **argv) { // expecting a filename if (argc < 2) { fprintf(stderr, "You have to specify at least one filename\n"); return -1; } bool ret = true; { JSLock lock; // create interpreter w/ global object Global* global = new Global(); RefPtr<Interpreter> interp = new Interpreter(global); ExecState *exec = interp->globalExec(); MyObject *myObject = (MyObject *)_NPN_CreateObject (NPP(0), myFunctionPtrs); // FIXME // global->put(exec, Identifier("myInterface"), Instance::createRuntimeObject(Instance::CLanguage, (void *)myObject)); for (int i = 1; i < argc; i++) { const char *code = readJavaScriptFromFile(argv[i]); if (code) { // run Completion comp(interp->evaluate("", 0, code)); if (comp.complType() == Throw) { JSValue *exVal = comp.value(); char *msg = exVal->toString(exec).ascii(); int lineno = -1; if (exVal->type() == ObjectType) { JSValue *lineVal = exVal->getObject()->get(exec, Identifier("line")); if (lineVal->type() == NumberType) lineno = int(lineVal->toNumber(exec)); } if (lineno != -1) fprintf(stderr,"Exception, line %d: %s\n",lineno,msg); else fprintf(stderr,"Exception: %s\n",msg); ret = false; } else if (comp.complType() == ReturnValue) { char *msg = comp.value()->toString(interp->globalExec()).ascii(); fprintf(stderr,"Return value: %s\n",msg); } } } _NPN_ReleaseObject ((NPObject *)myObject); } // end block, so that Interpreter and global get deleted return ret ? 0 : 3; }
JSObject* BalRuntimeObjectImp::construct(ExecState* exec, const ArgList& args) { // ECMA 15.2.2.1 (?) CallData callData; CallType callType = getCallData(callData); JSValue* val = call(exec, this, callType, callData, this, args); if (!val || val->type() == NullType || val->type() == UndefinedType) return new (exec) JSObject(exec->lexicalGlobalObject()->objectPrototype()->prototype()); else return val->toObject(exec); }
bool UserObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) { if (!fJSUserObject) return false; CFStringRef cfPropName = IdentifierToCFString(propertyName); JSUserObject *jsResult = fJSUserObject->CopyProperty(cfPropName); ReleaseCFType(cfPropName); if (jsResult) { slot.setCustom(this, userObjectGetter); jsResult->Release(); return true; } else { JSValue *kjsValue = toPrimitive(exec); if (kjsValue->type() != NullType && kjsValue->type() != UndefinedType) { JSObject *kjsObject = kjsValue->toObject(exec); if (kjsObject->getPropertySlot(exec, propertyName, slot)) return true; } } return JSObject::getOwnPropertySlot(exec, propertyName, slot); }
void JSObject::defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc) { JSValue *o = getDirect(propertyName); GetterSetterImp *gs; if (o && o->type() == GetterSetterType) { gs = static_cast<GetterSetterImp *>(o); } else { gs = new GetterSetterImp; putDirect(propertyName, gs, GetterSetter); } _prop.setHasGetterSetterProperties(true); gs->setSetter(setterFunc); }
static ALWAYS_INLINE JSValue *tryGetAndCallProperty(ExecState *exec, const JSObject *object, const Identifier &propertyName) { JSValue *v = object->get(exec, propertyName); if (v->isObject()) { JSObject *o = static_cast<JSObject*>(v); if (o->implementsCall()) { // spec says "not primitive type" but ... JSObject *thisObj = const_cast<JSObject*>(object); JSValue *def = o->call(exec, thisObj, List::empty()); JSType defType = def->type(); ASSERT(defType != GetterSetterType); if (defType != ObjectType) return def; } } return NULL; }
// ECMA 15.2.2 JSObject* ObjectObjectImp::construct(ExecState* exec, const List& args) { JSValue* arg = args[0]; switch (arg->type()) { case StringType: case BooleanType: case NumberType: case ObjectType: return arg->toObject(exec); case NullType: case UndefinedType: return new JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()); default: //### ASSERT_NOT_REACHED(); return 0; } }
//#ifndef NDEBUG void printInfo(ExecState *exec, const char *s, JSValue *o, int lineno) { UString vString; if (!o) { fprintf(stderr, "KJS: %s: (null)", s); } else { JSValue *v = o; unsigned int arrayLength = 0; bool hadExcep = exec->hadException(); UString name; switch (v->type()) { case UnspecifiedType: name = "Unspecified"; break; case UndefinedType: name = "Undefined"; break; case NullType: name = "Null"; break; case BooleanType: name = "Boolean"; break; case StringType: name = "String"; break; case NumberType: name = "Number"; break; case ObjectType: { JSObject *obj = static_cast<JSObject *>(v); name = obj->className(); if (name.isNull()) { name = "(unknown class)"; } if (obj->inherits(&ArrayInstance::info)) { arrayLength = obj->get(exec, exec->propertyNames().length)->toUInt32(exec); } vString = "[object " + name + "]"; // krazy:exclude=doublequote_chars break; } case GetterSetterType: name = "GetterSetter"; break; } // Avoid calling toString on a huge array (e.g. 4 billion elements, in mozilla/js/js1_5/Array/array-001.js) if (arrayLength > 100) { vString = UString("[ Array with ") + UString::from(arrayLength) + " elements ]"; } else if (v->type() != ObjectType) { // Don't want to call a user toString function! vString = v->toString(exec); } if (!hadExcep) { exec->clearException(); } if (vString.size() > 350) { vString = vString.substr(0, 350) + "..."; } // Can't use two UString::ascii() in the same fprintf call CString tempString(vString.cstring()); fprintf(stderr, "KJS: %s: %s : %s (%p)", s, tempString.c_str(), name.ascii(), (void *)v); if (lineno >= 0) { fprintf(stderr, ", line %d\n", lineno); } else { fprintf(stderr, "\n"); } } }
JSValue *ObjectProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) { switch (id) { case ValueOf: return thisObj; case HasOwnProperty: { PropertySlot slot; return jsBoolean(thisObj->getOwnPropertySlot(exec, Identifier(args[0]->toString(exec)), slot)); } case IsPrototypeOf: { if (!args[0]->isObject()) return jsBoolean(false); JSValue *v = static_cast<JSObject *>(args[0])->prototype(); while (true) { if (!v->isObject()) return jsBoolean(false); if (thisObj == static_cast<JSObject *>(v)) return jsBoolean(true); v = static_cast<JSObject *>(v)->prototype(); } } case DefineGetter: case DefineSetter: { if (!args[1]->isObject() || !static_cast<JSObject *>(args[1])->implementsCall()) { if (id == DefineGetter) return throwError(exec, SyntaxError, "invalid getter usage"); else return throwError(exec, SyntaxError, "invalid setter usage"); } if (id == DefineGetter) thisObj->defineGetter(exec, Identifier(args[0]->toString(exec)), static_cast<JSObject *>(args[1])); else thisObj->defineSetter(exec, Identifier(args[0]->toString(exec)), static_cast<JSObject *>(args[1])); return jsUndefined(); } case LookupGetter: case LookupSetter: { Identifier propertyName = Identifier(args[0]->toString(exec)); JSObject *obj = thisObj; while (true) { JSValue *v = obj->getDirect(propertyName); if (v) { if (v->type() != GetterSetterType) return jsUndefined(); JSObject *funcObj; if (id == LookupGetter) funcObj = static_cast<GetterSetterImp *>(v)->getGetter(); else funcObj = static_cast<GetterSetterImp *>(v)->getSetter(); if (!funcObj) return jsUndefined(); else return funcObj; } if (!obj->prototype() || !obj->prototype()->isObject()) return jsUndefined(); obj = static_cast<JSObject *>(obj->prototype()); } } case PropertyIsEnumerable: return jsBoolean(thisObj->propertyIsEnumerable(exec, Identifier(args[0]->toString(exec)))); case ToLocaleString: return jsString(thisObj->toString(exec)); case ToString: default: return jsString("[object " + thisObj->className() + "]"); } }