static void initializeOverrideInfo(const SourceCode& origCode, const String& newBody, FunctionOverrides::OverrideInfo& info) { String origProviderStr = origCode.provider()->source(); unsigned origBraceStart = origCode.startOffset(); unsigned origFunctionStart = origProviderStr.reverseFind("function", origBraceStart); unsigned headerLength = origBraceStart - origFunctionStart; String origHeader = origProviderStr.substring(origFunctionStart, headerLength); String newProviderStr; newProviderStr.append(origHeader); newProviderStr.append(newBody); RefPtr<SourceProvider> newProvider = StringSourceProvider::create(newProviderStr, "<overridden>"); info.firstLine = 1; info.lineCount = 1; // Faking it. This doesn't really matter for now. info.startColumn = 1; info.endColumn = 1; // Faking it. This doesn't really matter for now. info.parametersStartOffset = newProviderStr.find("("); info.typeProfilingStartOffset = newProviderStr.find("{"); info.typeProfilingEndOffset = newProviderStr.length() - 1; info.sourceCode = SourceCode(newProvider.release(), info.typeProfilingStartOffset, info.typeProfilingEndOffset + 1, 1, 1); }
SourceCode Lexer::sourceCode(int openBrace, int closeBrace, int firstLine) { if (m_codeWithoutBOMs.isEmpty()) return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine); const UChar* data = m_source->provider()->data(); ASSERT(openBrace < closeBrace); int numBOMsBeforeOpenBrace = 0; int numBOMsBetweenBraces = 0; int i; for (i = m_source->startOffset(); i < openBrace; ++i) numBOMsBeforeOpenBrace += data[i] == byteOrderMark; for (; i < closeBrace; ++i) numBOMsBetweenBraces += data[i] == byteOrderMark; return SourceCode(m_source->provider(), openBrace + numBOMsBeforeOpenBrace, closeBrace + numBOMsBeforeOpenBrace + numBOMsBetweenBraces + 1, firstLine); }
FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& ownerSource, int overrideLineNumber) { SourceCode source = m_sourceOverride ? SourceCode(m_sourceOverride) : ownerSource; unsigned firstLine = source.firstLine() + m_firstLineOffset; unsigned startOffset = source.startOffset() + m_startOffset; // Adjust to one-based indexing. bool startColumnIsOnFirstSourceLine = !m_firstLineOffset; unsigned startColumn = m_unlinkedBodyStartColumn + (startColumnIsOnFirstSourceLine ? source.startColumn() : 1); bool endColumnIsOnStartLine = !m_lineCount; unsigned endColumn = m_unlinkedBodyEndColumn + (endColumnIsOnStartLine ? startColumn : 1); SourceCode code(source.provider(), startOffset, startOffset + m_sourceLength, firstLine, startColumn); FunctionExecutable* result = FunctionExecutable::create(vm, code, this, firstLine, firstLine + m_lineCount, startColumn, endColumn); if (overrideLineNumber != -1) result->setOverrideLineNumber(overrideLineNumber); return result; }
void Debugger::recompileAllJSFunctions(JSGlobalData* globalData) { // 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; typedef HashSet<FunctionExecutable*> FunctionExecutableSet; typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap; FunctionExecutableSet functionExecutables; SourceProviderMap sourceProviders; LiveObjectIterator it = globalData->heap.primaryHeapBegin(); LiveObjectIterator heapEnd = globalData->heap.primaryHeapEnd(); for ( ; it != heapEnd; ++it) { if (!(*it)->inherits(&JSFunction::info)) continue; JSFunction* function = asFunction(*it); if (function->executable()->isHostFunction()) continue; FunctionExecutable* executable = function->jsExecutable(); // Check if the function is already in the set - if so, // we've already retranslated it, nothing to do here. if (!functionExecutables.add(executable).second) continue; ExecState* exec = function->scope().globalObject()->JSGlobalObject::globalExec(); executable->recompile(exec); if (function->scope().globalObject()->debugger() == this) sourceProviders.add(executable->source().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, UString()); }
FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& ownerSource, Optional<int> overrideLineNumber, Intrinsic intrinsic) { SourceCode source = m_sourceOverride ? SourceCode(m_sourceOverride) : ownerSource; unsigned firstLine = source.firstLine() + m_firstLineOffset; unsigned startOffset = source.startOffset() + m_startOffset; unsigned lineCount = m_lineCount; // Adjust to one-based indexing. bool startColumnIsOnFirstSourceLine = !m_firstLineOffset; unsigned startColumn = m_unlinkedBodyStartColumn + (startColumnIsOnFirstSourceLine ? source.startColumn() : 1); bool endColumnIsOnStartLine = !lineCount; unsigned endColumn = m_unlinkedBodyEndColumn + (endColumnIsOnStartLine ? startColumn : 1); SourceCode code(source.provider(), startOffset, startOffset + m_sourceLength, firstLine, startColumn); FunctionOverrides::OverrideInfo overrideInfo; bool hasFunctionOverride = false; if (UNLIKELY(Options::functionOverrides())) { hasFunctionOverride = FunctionOverrides::initializeOverrideFor(code, overrideInfo); if (hasFunctionOverride) { firstLine = overrideInfo.firstLine; lineCount = overrideInfo.lineCount; startColumn = overrideInfo.startColumn; endColumn = overrideInfo.endColumn; code = overrideInfo.sourceCode; } } FunctionExecutable* result = FunctionExecutable::create(vm, code, this, firstLine, firstLine + lineCount, startColumn, endColumn, intrinsic); if (overrideLineNumber) result->setOverrideLineNumber(*overrideLineNumber); if (UNLIKELY(hasFunctionOverride)) { result->overrideParameterAndTypeProfilingStartEndOffsets( overrideInfo.parametersStartOffset, overrideInfo.typeProfilingStartOffset, overrideInfo.typeProfilingEndOffset); } return result; }