JSObject *Error::create(ExecState *exec, ErrorType errtype, const UString &message, int lineno, int sourceId, const UString &sourceURL) { JSObject *cons; switch (errtype) { case EvalError: cons = exec->lexicalInterpreter()->builtinEvalError(); break; case RangeError: cons = exec->lexicalInterpreter()->builtinRangeError(); break; case ReferenceError: cons = exec->lexicalInterpreter()->builtinReferenceError(); break; case SyntaxError: cons = exec->lexicalInterpreter()->builtinSyntaxError(); break; case TypeError: cons = exec->lexicalInterpreter()->builtinTypeError(); break; case URIError: cons = exec->lexicalInterpreter()->builtinURIError(); break; default: cons = exec->lexicalInterpreter()->builtinError(); break; } List args; if (message.isEmpty()) args.append(jsString(errorNames[errtype])); else args.append(jsString(message)); JSObject *err = static_cast<JSObject *>(cons->construct(exec,args)); if (lineno != -1) err->put(exec, "line", jsNumber(lineno)); if (sourceId != -1) err->put(exec, "sourceId", jsNumber(sourceId)); if(!sourceURL.isNull()) err->put(exec, "sourceURL", jsString(sourceURL)); return err; /* #ifndef NDEBUG const char *msg = err->get(messagePropertyName)->toString().value().ascii(); if (l >= 0) fprintf(stderr, "KJS: %s at line %d. %s\n", estr, l, msg); else fprintf(stderr, "KJS: %s. %s\n", estr, msg); #endif return err; */ }
void JSLazyEventListener::parseCode() const { if (m_parsed) return; m_parsed = true; Frame* frame = windowObj()->impl()->frame(); KJSProxy* proxy = 0; if (frame) proxy = frame->scriptProxy(); if (proxy) { ScriptInterpreter* interpreter = proxy->interpreter(); ExecState* exec = interpreter->globalExec(); JSLock lock; JSObject* constr = interpreter->builtinFunction(); List args; UString sourceURL(frame->loader()->url().url()); args.append(eventParameterName()); args.append(jsString(m_code)); m_listener = constr->construct(exec, args, m_functionName, sourceURL, m_lineNumber); // FIXME: is globalExec ok ? FunctionImp* listenerAsFunction = static_cast<FunctionImp*>(m_listener.get()); if (exec->hadException()) { exec->clearException(); // failed to parse, so let's just make this listener a no-op m_listener = 0; } else if (m_originalNode) { // Add the event's home element to the scope // (and the document, and the form - see JSHTMLElement::eventHandlerScope) ScopeChain scope = listenerAsFunction->scope(); JSValue* thisObj = toJS(exec, m_originalNode); if (thisObj->isObject()) { static_cast<JSEventTargetNode*>(thisObj)->pushEventHandlerScope(exec, scope); listenerAsFunction->setScope(scope); } } } // no more need to keep the unparsed code around m_functionName = String(); m_code = String(); if (m_listener) { Window::ListenersMap& listeners = isHTMLEventListener() ? windowObj()->jsHTMLEventListeners() : windowObj()->jsEventListeners(); listeners.set(m_listener, const_cast<JSLazyEventListener*>(this)); } }
EXPORT JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { JSLock lock; ExecState* exec = toJS(ctx); JSObject* jsObject = toJS(object); List argList; for (size_t i = 0; i < argumentCount; i++) argList.append(toJS(arguments[i])); JSObjectRef result = toRef(jsObject->construct(exec, argList)); // returns NULL if object->implementsCall() is false if (exec->hadException()) { if (exception) *exception = toRef(exec->exception()); exec->clearException(); result = 0; } return result; }
// ECMA 15.3.2 The Function Constructor JSObject *FunctionObjectImp::construct(ExecState *exec, const List &args, const Identifier &functionName, const UString &sourceURL, int lineNumber) { UString p(""); UString body; int argsSize = args.size(); if (argsSize == 0) { body = ""; } else if (argsSize == 1) { body = args[0]->toString(exec); } else { p = args[0]->toString(exec); for (int k = 1; k < argsSize - 1; k++) { p += "," + args[k]->toString(exec); } body = args[argsSize - 1]->toString(exec); } // parse the source code int sourceId; int errLine; UString errMsg; RefPtr<FunctionBodyNode> functionBody = parser().parseFunctionBody(sourceURL, lineNumber, body.data(), body.size(), &sourceId, &errLine, &errMsg); // notify debugger that source has been parsed Debugger *dbg = exec->dynamicInterpreter()->debugger(); if (dbg) { // make sure to pass in sourceURL, since it's useful for lazy event listeners, and empty for actual function ctor dbg->reportSourceParsed(exec, functionBody.get(), sourceId, sourceURL, body, lineNumber, errLine, errMsg); } // no program node == syntax error - throw a syntax error if (!functionBody) // we can't return a Completion(Throw) here, so just set the exception // and return it { return throwError(exec, SyntaxError, errMsg, errLine, sourceId, sourceURL); } ScopeChain scopeChain; scopeChain.push(exec->lexicalInterpreter()->globalObject()); FunctionImp *fimp = new FunctionImp(exec, functionName, functionBody.get(), scopeChain); // parse parameter list. throw syntax error on illegal identifiers int len = p.size(); const UChar *c = p.data(); int i = 0, params = 0; UString param; while (i < len) { while (*c == ' ' && i < len) { c++, i++; } if (Lexer::isIdentStart(c->uc)) { // else error param = UString(c, 1); c++, i++; while (i < len && (Lexer::isIdentPart(c->uc))) { param += UString(c, 1); c++, i++; } while (i < len && *c == ' ') { c++, i++; } if (i == len) { functionBody->addParam(Identifier(param)); params++; break; } else if (*c == ',') { functionBody->addParam(Identifier(param)); params++; c++, i++; continue; } // else error } return throwError(exec, SyntaxError, "Syntax error in parameter list"); } List consArgs; JSObject *objCons = exec->lexicalInterpreter()->builtinObject(); JSObject *prototype = objCons->construct(exec, List::empty()); prototype->put(exec, exec->propertyNames().constructor, fimp, DontEnum | DontDelete | ReadOnly); // ECMA Edition 5.1r6 - 15.3.5.2 - [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false fimp->put(exec, exec->propertyNames().prototype, prototype, Internal | DontDelete | DontEnum); return fimp; }