Ignore:
Timestamp:
Nov 19, 2013, 1:55:16 PM (12 years ago)
Author:
[email protected]
Message:

Add tracking of endColumn for Executables.
https://bugs.webkit.org/show_bug.cgi?id=124245.

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

  1. Fixed computation of columns to take into account the startColumn from <script> tags. Previously, we were only computing the column relative to the char after the <script> tag. Now, the column number that JSC computes is always the column number you'll see when viewing the source in a text editor (assuming the first column position is 1, not 0).
  1. Previously, unlinkedExecutables kept the a base-1 startColumn for ProgramExecutables and EvalExecutables, but uses base-0 columns for FunctionExecutables. This has been fixed so that they all use base-0 columns. When the executable gets linked, the column is adjusted into a base-1 value.
  1. In the UnlinkedFunctionExecutable, renamed m_functionStartOffset to m_unlinkedFunctionNameStart because it actually points to the start column in the name part of the function declaration.

Similarly, renamed m_functionStartColumn to m_unlinkedBodyStartColumn
because it points to the first character in the function body. This is
usually '{' except for functions created from "global code" which
excludes its braces. See FunctionExecutable::fromGlobalCode().

The exclusion of braces for the global code case is needed so that

computed start and end columns will more readily map to what a JS
developer would expect them to be. Otherwise, the first column of the
function source will not be 1 (includes prepended characters added in
constructFunctionSkippingEvalEnabledCheck()).

Also, similarly, a m_unlinkedBodyEndColumn has been added to track the
end column of the UnlinkedFunctionExecutable.

  1. For unlinked executables, end column values are either:
    1. Relative to the start of the last line if (last line != first line).
    2. Relative to the start column position if (last line == first line).

The second case is needed so that we can add an appropriate adjustment
to the end column value (just like we do for the start column) when we
link the executable.

  1. This is not new to this patch, but it worth noting that the lineCount values used through this patch has the following meaning:
    • a lineCount of 0 means the source for this code block is on 1 line.
    • a lineCount of N means there are N + l lines of source.

This interpretation is janky, but was present before this patch. We can
clean that up later in another patch.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • In order to implement WebCore::Internals::parserMetaData(), we need to move some seemingly unrelated header files from the Project section to the Private section so that they can be #include'd by the forwarding CodeBlock.h from WebCore.
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::sourceCodeForTools):
(JSC::CodeBlock::CodeBlock):

  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::generateFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):

  • m_isFromGlobalCode is needed to support the exclusion of the open brace / prepended code for functions created from "global code".

(JSC::UnlinkedFunctionExecutable::link):
(JSC::UnlinkedFunctionExecutable::fromGlobalCode):
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):

  • bytecode/UnlinkedCodeBlock.h:

(JSC::UnlinkedFunctionExecutable::create):
(JSC::UnlinkedFunctionExecutable::unlinkedFunctionNameStart):
(JSC::UnlinkedFunctionExecutable::unlinkedBodyStartColumn):
(JSC::UnlinkedFunctionExecutable::unlinkedBodyEndColumn):
(JSC::UnlinkedFunctionExecutable::recordParse):
(JSC::UnlinkedCodeBlock::recordParse):
(JSC::UnlinkedCodeBlock::endColumn):

  • bytecompiler/NodesCodegen.cpp:

(JSC::FunctionBodyNode::emitBytecode):

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::createFunctionBody):
(JSC::ASTBuilder::setFunctionNameStart):

  • parser/Lexer.cpp:

(JSC::::shiftLineTerminator):

  • Removed an unused SourceCode Lexer<T>::sourceCode() function.
  • parser/Lexer.h:

(JSC::Lexer::positionBeforeLastNewline):
(JSC::Lexer::prevTerminator):

  • Added tracking of m_positionBeforeLastNewline in the Lexer to enable us to exclude the close brace / appended code for functions created from "global code".
  • parser/Nodes.cpp:

(JSC::ProgramNode::ProgramNode):
(JSC::ProgramNode::create):
(JSC::EvalNode::EvalNode):
(JSC::EvalNode::create):
(JSC::FunctionBodyNode::FunctionBodyNode):
(JSC::FunctionBodyNode::create):
(JSC::FunctionBodyNode::setEndPosition):

  • setEndPosition() is needed to fixed up the end position so that we can exclude the close brace / appended code for functions created from "global code".
  • parser/Nodes.h:

(JSC::ProgramNode::startColumn):
(JSC::ProgramNode::endColumn):
(JSC::EvalNode::startColumn):
(JSC::EvalNode::endColumn):
(JSC::FunctionBodyNode::setFunctionNameStart):
(JSC::FunctionBodyNode::functionNameStart):
(JSC::FunctionBodyNode::endColumn):

  • parser/Parser.cpp:

(JSC::::parseFunctionBody):
(JSC::::parseFunctionInfo):

  • parser/Parser.h:

(JSC::Parser::positionBeforeLastNewline):
(JSC::::parse):

  • Subtracted 1 from startColumn here to keep the node column values consistently base-0. See note 2 above.

(JSC::parse):

  • parser/SourceProviderCacheItem.h:

(JSC::SourceProviderCacheItem::SourceProviderCacheItem):

  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::createFunctionBody):
(JSC::SyntaxChecker::setFunctionNameStart):

  • runtime/CodeCache.cpp:

(JSC::CodeCache::getGlobalCodeBlock):
(JSC::CodeCache::getProgramCodeBlock):
(JSC::CodeCache::getEvalCodeBlock):
(JSC::CodeCache::getFunctionExecutableFromGlobalCode):

  • runtime/CodeCache.h:
  • runtime/Executable.cpp:

(JSC::ScriptExecutable::newCodeBlockFor):
(JSC::FunctionExecutable::FunctionExecutable):
(JSC::ProgramExecutable::initializeGlobalProperties):
(JSC::FunctionExecutable::fromGlobalCode):

  • runtime/Executable.h:

(JSC::ExecutableBase::isEvalExecutable):
(JSC::ExecutableBase::isProgramExecutable):
(JSC::ScriptExecutable::ScriptExecutable):
(JSC::ScriptExecutable::endColumn):
(JSC::ScriptExecutable::recordParse):
(JSC::FunctionExecutable::create):
(JSC::FunctionExecutable::bodyIncludesBraces):

  • runtime/FunctionConstructor.cpp:

(JSC::constructFunctionSkippingEvalEnabledCheck):

  • runtime/FunctionPrototype.cpp:

(JSC::insertSemicolonIfNeeded):
(JSC::functionProtoFuncToString):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::createProgramCodeBlock):
(JSC::JSGlobalObject::createEvalCodeBlock):

Source/WebCore:

Test: js/dom/script-start-end-locations.html

  • ForwardingHeaders/bytecode: Added.
  • ForwardingHeaders/bytecode/CodeBlock.h: Added.
  • WebCore.exp.in:
  • testing/Internals.cpp:

(WebCore::GetCallerCodeBlockFunctor::GetCallerCodeBlockFunctor):
(WebCore::GetCallerCodeBlockFunctor::operator()):
(WebCore::GetCallerCodeBlockFunctor::codeBlock):
(WebCore::Internals::parserMetaData):

  • testing/Internals.h:
  • testing/Internals.idl:

Source/WebKit:

  • WebKit.vcxproj/WebKitExportGenerator/WebKitExports.def.in:
  • Added an exported symbol to make the Win32 build happy. The Win64 symbol is currently a copy of the Win32 one. It'll need to be updated if the mangled symbol is different for Win64.

LayoutTests:

  • fast/events/window-onerror2-expected.txt:
  • inspector-protocol/debugger/setBreakpoint-actions-expected.txt:
  • js/dom/script-start-end-locations-expected.txt: Added.
  • js/dom/script-start-end-locations.html: Added.
  • js/dom/script-tests/script-start-end-locations.js: Added.
  • js/dom/stack-trace-expected.txt:
  • js/dom/stack-trace.html:
  • Changed tabs to spaces. The tabs were making it hard to visually confirm the exected column values for 2 functions.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/parser/Nodes.cpp

    r156785 r159520  
    115115// ------------------------------ ProgramNode -----------------------------
    116116
    117 inline ProgramNode::ProgramNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
     117inline ProgramNode::ProgramNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
    118118    : ScopeNode(vm, startLocation, endLocation, source, children, varStack, funcStack, capturedVariables, features, numConstants)
    119119    , m_startColumn(startColumn)
    120 {
    121 }
    122 
    123 PassRefPtr<ProgramNode> ProgramNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
    124 {
    125     RefPtr<ProgramNode> node = new ProgramNode(vm, startLocation, endLocation, startColumn, children, varStack, funcStack,  capturedVariables, source, features, numConstants);
     120    , m_endColumn(endColumn)
     121{
     122}
     123
     124PassRefPtr<ProgramNode> ProgramNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
     125{
     126    RefPtr<ProgramNode> node = new ProgramNode(vm, startLocation, endLocation, startColumn, endColumn, children, varStack, funcStack,  capturedVariables, source, features, numConstants);
    126127
    127128    ASSERT(node->m_arena.last() == node);
     
    134135// ------------------------------ EvalNode -----------------------------
    135136
    136 inline EvalNode::EvalNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
     137inline EvalNode::EvalNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned endColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
    137138    : ScopeNode(vm, startLocation, endLocation, source, children, varStack, funcStack, capturedVariables, features, numConstants)
    138 {
    139 }
    140 
    141 PassRefPtr<EvalNode> EvalNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
    142 {
    143     RefPtr<EvalNode> node = new EvalNode(vm, startLocation, endLocation, children, varStack, funcStack, capturedVariables, source, features, numConstants);
     139    , m_endColumn(endColumn)
     140{
     141}
     142
     143PassRefPtr<EvalNode> EvalNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, unsigned endColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
     144{
     145    RefPtr<EvalNode> node = new EvalNode(vm, startLocation, endLocation, endColumn, children, varStack, funcStack, capturedVariables, source, features, numConstants);
    144146
    145147    ASSERT(node->m_arena.last() == node);
     
    180182}
    181183
    182 inline FunctionBodyNode::FunctionBodyNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, bool inStrictContext)
     184inline FunctionBodyNode::FunctionBodyNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, bool inStrictContext)
    183185    : ScopeNode(vm, startLocation, endLocation, inStrictContext)
    184186    , m_startColumn(startColumn)
    185 {
    186 }
    187 
    188 inline FunctionBodyNode::FunctionBodyNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
     187    , m_endColumn(endColumn)
     188{
     189}
     190
     191inline FunctionBodyNode::FunctionBodyNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
    189192    : ScopeNode(vm, startLocation, endLocation, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants)
    190193    , m_startColumn(startColumn)
     194    , m_endColumn(endColumn)
    191195{
    192196}
     
    206210}
    207211
    208 FunctionBodyNode* FunctionBodyNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, bool inStrictContext)
    209 {
    210     return new FunctionBodyNode(vm, startLocation, endLocation, startColumn, inStrictContext);
    211 }
    212 
    213 PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
    214 {
    215     RefPtr<FunctionBodyNode> node = new FunctionBodyNode(vm, startLocation, endLocation, startColumn, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants);
     212FunctionBodyNode* FunctionBodyNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, bool inStrictContext)
     213{
     214    return new FunctionBodyNode(vm, startLocation, endLocation, startColumn, endColumn, inStrictContext);
     215}
     216
     217PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
     218{
     219    RefPtr<FunctionBodyNode> node = new FunctionBodyNode(vm, startLocation, endLocation, startColumn, endColumn , children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants);
    216220
    217221    ASSERT(node->m_arena.last() == node);
     
    222226}
    223227
     228void FunctionBodyNode::setEndPosition(JSTextPosition position)
     229{
     230    m_lastLine = position.line;
     231    m_endColumn = position.offset - position.lineStartOffset;
     232}
     233
    224234} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.