void JavaScriptDebugServer::recompileAllJSFunctions(Timer<JavaScriptDebugServer>*) { JSLock lock(false); JSGlobalData* globalData = JSDOMWindow::commonJSGlobalData(); // If JavaScript is running, it's not safe to recompile, since we'll end // up throwing away code that is live on the stack. ASSERT(!globalData->dynamicGlobalObject); if (globalData->dynamicGlobalObject) return; Vector<ProtectedPtr<JSFunction> > functions; Heap::iterator heapEnd = globalData->heap.primaryHeapEnd(); for (Heap::iterator it = globalData->heap.primaryHeapBegin(); it != heapEnd; ++it) { if ((*it)->isObject(&JSFunction::info)) functions.append(static_cast<JSFunction*>(*it)); } typedef HashMap<RefPtr<FunctionBodyNode>, RefPtr<FunctionBodyNode> > FunctionBodyMap; typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap; FunctionBodyMap functionBodies; SourceProviderMap sourceProviders; size_t size = functions.size(); for (size_t i = 0; i < size; ++i) { JSFunction* function = functions[i]; FunctionBodyNode* oldBody = function->body(); pair<FunctionBodyMap::iterator, bool> result = functionBodies.add(oldBody, 0); if (!result.second) { function->setBody(result.first->second.get()); continue; } ExecState* exec = function->scope().globalObject()->JSGlobalObject::globalExec(); const SourceCode& sourceCode = oldBody->source(); RefPtr<FunctionBodyNode> newBody = globalData->parser->parse<FunctionBodyNode>(exec, 0, sourceCode); ASSERT(newBody); newBody->finishParsing(oldBody->copyParameters(), oldBody->parameterCount()); result.first->second = newBody; function->setBody(newBody.release()); if (hasListeners()) sourceProviders.add(sourceCode.provider(), exec); } // Call sourceParsed() after reparsing all functions because it will execute // JavaScript in the inspector. SourceProviderMap::const_iterator end = sourceProviders.end(); for (SourceProviderMap::const_iterator iter = sourceProviders.begin(); iter != end; ++iter) sourceParsed((*iter).second, SourceCode((*iter).first), -1, 0); }
FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception) { JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(lexicalGlobalObject, debugger, exec, source, 0, JSParseNormal, exception); if (!program) { ASSERT(*exception); return 0; } // Uses of this function that would not result in a single function expression are invalid. StatementNode* exprStatement = program->singleStatement(); ASSERT(exprStatement); ASSERT(exprStatement->isExprStatement()); ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr(); ASSERT(funcExpr); ASSERT(funcExpr->isFuncExprNode()); FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body(); ASSERT(body); return FunctionExecutable::create(exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine()); }
PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg) { RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), debugger, exec, source, errLine, errMsg); if (!program) return 0; StatementNode* exprStatement = program->singleStatement(); ASSERT(exprStatement); ASSERT(exprStatement->isExprStatement()); if (!exprStatement || !exprStatement->isExprStatement()) return 0; ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr(); ASSERT(funcExpr); ASSERT(funcExpr->isFuncExprNode()); if (!funcExpr || !funcExpr->isFuncExprNode()) return 0; FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body(); ASSERT(body); return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine()); }