Add tracking of endColumn for Executables.
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 19 Nov 2013 21:55:16 +0000 (21:55 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 19 Nov 2013 21:55:16 +0000 (21:55 +0000)
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).

2. 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.

3. 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.

4. For unlinked executables, end column values are either:
   a. Relative to the start of the last line if (last line != first line).
   b. 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.

5. 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.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@159520 268f45cc-cd09-0410-ab3c-d52691b4dbfc

38 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/events/window-onerror2-expected.txt
LayoutTests/inspector-protocol/debugger/setBreakpoint-actions-expected.txt
LayoutTests/js/dom/script-start-end-locations-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/script-start-end-locations.html [new file with mode: 0644]
LayoutTests/js/dom/script-tests/script-start-end-locations.js [new file with mode: 0644]
LayoutTests/js/dom/stack-trace-expected.txt
LayoutTests/js/dom/stack-trace.html
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/parser/ASTBuilder.h
Source/JavaScriptCore/parser/Lexer.cpp
Source/JavaScriptCore/parser/Lexer.h
Source/JavaScriptCore/parser/Nodes.cpp
Source/JavaScriptCore/parser/Nodes.h
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/parser/SourceProviderCacheItem.h
Source/JavaScriptCore/parser/SyntaxChecker.h
Source/JavaScriptCore/runtime/CodeCache.cpp
Source/JavaScriptCore/runtime/CodeCache.h
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/FunctionConstructor.cpp
Source/JavaScriptCore/runtime/FunctionPrototype.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/WebCore/ChangeLog
Source/WebCore/ForwardingHeaders/bytecode/CodeBlock.h [new file with mode: 0644]
Source/WebCore/WebCore.exp.in
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl
Source/WebKit/ChangeLog
Source/WebKit/WebKit.vcxproj/WebKitExportGenerator/WebKitExports.def.in

index b0b181189715a37af006ac1fcc15a759c1eef250..da214e792cbff9606704f7c14b16895006832bd9 100644 (file)
@@ -1,3 +1,20 @@
+2013-11-19  Mark Lam  <mark.lam@apple.com>
+
+        Add tracking of endColumn for Executables.
+        https://bugs.webkit.org/show_bug.cgi?id=124245.
+
+        Reviewed by Geoffrey Garen.
+
+        * 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.
+
 2013-11-15  Jer Noble  <jer.noble@apple.com>
 
         [MSE] Support fastSeek() in MediaSource.
index 889c309b762594c1472a04a07f09054a604a2089..09cd78754431c420e8c45184c34b081429d8f607 100644 (file)
@@ -1,6 +1,6 @@
 Test that uncaught exceptions will be reported to the window.onerror handler. Bug 8519.
 
 Main frame window.onerror: Error: Inline script exception at window-onerror2.html, line: 34, column: 47
-Main frame window.onerror: Exception in onload at window-onerror2.html, line: 2, column: 150
+Main frame window.onerror: Exception in onload at window-onerror2.html, line: 2, column: 66
 Main frame window.onerror: Error: Exception in setTimeout at window-onerror2.html, line: 29, column: 47
 
index a6c6974f8583faf25adf5a4e186bf082ebcb13d8..27b66ab24edf806398ecfb9d9729ec4c334f5e05 100644 (file)
@@ -14,11 +14,11 @@ inside breakpointActions a:(2) b:(12)
 inside breakpointActions a:(2) b:([object Object])
 Running breakpointActions to triggering the breakpoint actions
 inside breakpointActions a:(12) b:([object Object])
-PASS: Console Message: {"source":"javascript","level":"log","text":"log-action-before","location":"breakpoint.js:19:1"}
+PASS: Console Message: {"source":"javascript","level":"log","text":"log-action-before","location":"breakpoint.js:19:2"}
 PASS: Console Message: {"source":"console-api","level":"log","text":"eval-action","location":"???:1:26","parameters":[{"type":"string"},{"type":"number"},{"type":"object"}]}
-PASS: Console Message: {"source":"javascript","level":"log","text":"log-action-after","location":"breakpoint.js:19:1"}
+PASS: Console Message: {"source":"javascript","level":"log","text":"log-action-after","location":"breakpoint.js:19:2"}
 inside breakpointActions a:(100) b:([object HTMLBodyElement])
-PASS: Console Message: {"source":"javascript","level":"log","text":"log-action-before","location":"breakpoint.js:19:1"}
+PASS: Console Message: {"source":"javascript","level":"log","text":"log-action-before","location":"breakpoint.js:19:2"}
 PASS: Console Message: {"source":"console-api","level":"log","text":"eval-action","location":"???:1:26","parameters":[{"type":"string"},{"type":"number"},{"type":"object","subtype":"node"}]}
-PASS: Console Message: {"source":"javascript","level":"log","text":"log-action-after","location":"breakpoint.js:19:1"}
+PASS: Console Message: {"source":"javascript","level":"log","text":"log-action-after","location":"breakpoint.js:19:2"}
 
diff --git a/LayoutTests/js/dom/script-start-end-locations-expected.txt b/LayoutTests/js/dom/script-start-end-locations-expected.txt
new file mode 100644 (file)
index 0000000..1ba6d15
--- /dev/null
@@ -0,0 +1,280 @@
+program { 7:9 - 19:1 }
+program { 21:9 - 21:50 }
+program { 21:68 - 21:109 }
+program { 23:9 - 23:50 }
+program { 23:68 - 23:109 }
+program { 25:9 - 26:1 }
+program { 27:13 - 28:1 }
+function "hf1" { 30:24 - 30:38 }
+function "hf2" { 31:28 - 31:42 }
+function "hf3" { 32:32 - 32:46 }
+function "hf4" { 34:24 - 36:9 }
+function "hf5" { 37:28 - 39:9 }
+function "hf6" { 40:32 - 42:9 }
+function "hf7" { 45:16 - 47:5 }
+function "hf8" { 49:35 - 49:45 }
+function "hf9" { 49:97 - 49:107 }
+
+program { 1:1 - 474:1 }
+
+  On first line:
+function "f0" { 1:115 - 1:266 }
+function "f0a" { 1:142 - 1:257 }
+function "f0b" { 1:170 - 1:248 }
+eval { 1:1 - 1:56 }
+function "x0" { 1:298 - 1:476 }
+function "x0a" { 1:330 - 1:466 }
+function "x0b" { 1:364 - 1:456 }
+eval { 1:1 - 1:56 }
+
+  Functions Declarations in a function:
+function "f1" { 9:22 - 9:113 }
+eval { 1:1 - 1:56 }
+function "f2" { 12:22 - 16:5 }
+function "f2a" { 14:24 - 14:116 }
+eval { 1:1 - 1:56 }
+function "f3" { 19:22 - 31:5 }
+function "f3a" { 21:24 - 29:9 }
+function "f3b" { 23:28 - 27:13 }
+eval { 1:1 - 1:56 }
+function "f4" { 34:22 - 34:71 }
+function "f4a" { 34:49 - 34:50 }
+function "f5" { 36:22 - 36:151 }
+function "f5a" { 36:49 - 36:141 }
+eval { 1:1 - 1:56 }
+function "f6" { 38:22 - 38:189 }
+function "f6a" { 38:49 - 38:179 }
+function "f6b" { 38:77 - 38:169 }
+eval { 1:1 - 1:56 }
+
+  Indented Functions Declarations in a function:
+function "fi1" { 43:27 - 43:119 }
+eval { 1:1 - 1:56 }
+function "fi2" { 46:27 - 50:9 }
+function "fi2a" { 48:29 - 48:122 }
+eval { 1:1 - 1:56 }
+function "fi3" { 53:27 - 65:9 }
+function "fi3a" { 55:29 - 63:13 }
+function "fi3b" { 57:33 - 61:17 }
+eval { 1:1 - 1:56 }
+function "fi4" { 68:27 - 68:80 }
+function "fi4a" { 68:56 - 68:57 }
+function "fi5" { 70:27 - 70:160 }
+function "fi5a" { 70:56 - 70:149 }
+eval { 1:1 - 1:56 }
+function "fi6" { 72:27 - 72:201 }
+function "fi6a" { 72:56 - 72:190 }
+function "fi6b" { 72:86 - 72:179 }
+eval { 1:1 - 1:56 }
+
+  Functions Expressions in a function:
+function "x1" { 77:28 - 77:119 }
+eval { 1:1 - 1:56 }
+function "x2" { 80:28 - 84:5 }
+function "x2a" { 82:30 - 82:122 }
+eval { 1:1 - 1:56 }
+function "x3" { 87:28 - 99:5 }
+function "x3a" { 89:30 - 97:9 }
+function "x3b" { 91:34 - 95:13 }
+eval { 1:1 - 1:56 }
+function "x4" { 102:28 - 102:83 }
+function "x4a" { 102:61 - 102:62 }
+function "x5" { 104:28 - 104:163 }
+function "x5a" { 104:61 - 104:153 }
+eval { 1:1 - 1:56 }
+function "x6" { 106:28 - 106:207 }
+function "x6a" { 106:61 - 106:197 }
+function "x6b" { 106:95 - 106:187 }
+eval { 1:1 - 1:56 }
+
+  Indented Functions Expressions in a function:
+function "xi1" { 111:33 - 111:125 }
+eval { 1:1 - 1:56 }
+function "xi2" { 114:33 - 118:9 }
+function "xi2a" { 116:35 - 116:128 }
+eval { 1:1 - 1:56 }
+function "xi3" { 121:33 - 133:9 }
+function "xi3a" { 123:35 - 131:13 }
+function "xi3b" { 125:39 - 129:17 }
+eval { 1:1 - 1:56 }
+function "xi4" { 136:33 - 136:92 }
+function "xi4a" { 136:68 - 136:69 }
+function "xi5" { 138:33 - 138:172 }
+function "xi5a" { 138:68 - 138:161 }
+eval { 1:1 - 1:56 }
+function "xi6" { 140:33 - 140:219 }
+function "xi6a" { 140:68 - 140:208 }
+function "xi6b" { 140:104 - 140:197 }
+eval { 1:1 - 1:56 }
+
+  Anonymous Function Declaration in a function:
+function "" { 146:58 - 151:5 }
+eval { 1:1 - 1:56 }
+
+  Global eval:
+eval { 1:1 - 1:56 }
+
+  Global Functions Declarations:
+function "gf1" { 161:19 - 161:111 }
+eval { 1:1 - 1:56 }
+function "gf2" { 164:19 - 168:1 }
+function "gf2a" { 166:21 - 166:114 }
+eval { 1:1 - 1:56 }
+function "gf3" { 171:19 - 183:1 }
+function "gf3a" { 173:21 - 181:5 }
+function "gf3b" { 175:25 - 179:9 }
+eval { 1:1 - 1:56 }
+function "gf4" { 186:19 - 186:72 }
+function "gf4a" { 186:48 - 186:49 }
+function "gf5" { 188:19 - 188:152 }
+function "gf5a" { 188:48 - 188:141 }
+eval { 1:1 - 1:56 }
+function "gf6" { 190:19 - 190:193 }
+function "gf6a" { 190:48 - 190:182 }
+function "gf6b" { 190:78 - 190:171 }
+eval { 1:1 - 1:56 }
+
+  Indented Global Functions Declarations:
+function "gfi1" { 195:24 - 195:117 }
+eval { 1:1 - 1:56 }
+function "gfi2" { 198:24 - 202:5 }
+function "gfi2a" { 200:26 - 200:120 }
+eval { 1:1 - 1:56 }
+function "gfi3" { 205:24 - 217:5 }
+function "gfi3a" { 207:26 - 215:9 }
+function "gfi3b" { 209:30 - 213:13 }
+eval { 1:1 - 1:56 }
+function "gfi4" { 220:24 - 220:81 }
+function "gfi4a" { 220:55 - 220:56 }
+function "gfi5" { 222:24 - 222:161 }
+function "gfi5a" { 222:55 - 222:149 }
+eval { 1:1 - 1:56 }
+function "gfi6" { 224:24 - 224:205 }
+function "gfi6a" { 224:55 - 224:193 }
+function "gfi6b" { 224:87 - 224:181 }
+eval { 1:1 - 1:56 }
+
+  Global Functions Expressions:
+function "gx1" { 229:25 - 229:117 }
+eval { 1:1 - 1:56 }
+function "gx2" { 232:25 - 236:1 }
+function "gx2a" { 234:27 - 234:120 }
+eval { 1:1 - 1:56 }
+function "gx3" { 239:25 - 251:1 }
+function "gx3a" { 241:27 - 249:5 }
+function "gx3b" { 243:31 - 247:9 }
+eval { 1:1 - 1:56 }
+function "gx4" { 254:25 - 254:84 }
+function "gx4a" { 254:60 - 254:61 }
+function "gx5" { 256:25 - 256:164 }
+function "gx5a" { 256:60 - 256:153 }
+eval { 1:1 - 1:56 }
+function "gx6" { 258:25 - 258:211 }
+function "gx6a" { 258:60 - 258:200 }
+function "gx6b" { 258:96 - 258:189 }
+eval { 1:1 - 1:56 }
+
+  Indented Functions Declarations:
+function "gxi1" { 263:30 - 263:123 }
+eval { 1:1 - 1:56 }
+function "gxi2" { 266:30 - 270:5 }
+function "gxi2a" { 268:32 - 268:126 }
+eval { 1:1 - 1:56 }
+function "gxi3" { 273:30 - 285:5 }
+function "gxi3a" { 275:32 - 283:9 }
+function "gxi3b" { 277:36 - 281:13 }
+eval { 1:1 - 1:56 }
+function "gxi4" { 288:30 - 288:93 }
+function "gxi4a" { 288:67 - 288:68 }
+function "gxi5" { 290:30 - 290:173 }
+function "gxi5a" { 290:67 - 290:161 }
+eval { 1:1 - 1:56 }
+function "gxi6" { 292:30 - 292:223 }
+function "gxi6a" { 292:67 - 292:211 }
+function "gxi6b" { 292:105 - 292:199 }
+eval { 1:1 - 1:56 }
+
+  Anonymous Global Function Declarations:
+function "" { 299:56 - 304:1 }
+eval { 1:1 - 1:56 }
+
+  Function Declarations in an eval:
+eval { 1:1 - 16:7 }
+function "ef1" { 3:20 - 14:5 }
+function "ef1a" { 5:25 - 12:9 }
+function "ef1b" { 7:29 - 10:13 }
+eval { 1:1 - 1:56 }
+eval { 1:1 - 1:225 }
+function "ef2" { 1:59 - 1:217 }
+function "ef2a" { 1:88 - 1:207 }
+function "ef2b" { 1:118 - 1:197 }
+eval { 1:1 - 1:56 }
+eval { 1:1 - 17:8 }
+function "efi1" { 4:21 - 15:5 }
+function "efi1a" { 6:26 - 13:9 }
+function "efi1b" { 8:30 - 11:13 }
+eval { 1:1 - 1:56 }
+eval { 1:1 - 1:234 }
+function "efi2" { 1:60 - 1:225 }
+function "efi2a" { 1:91 - 1:214 }
+function "efi2b" { 1:123 - 1:203 }
+eval { 1:1 - 1:56 }
+
+  Function Expressions in an eval:
+eval { 1:1 - 16:7 }
+function "ex1" { 3:26 - 14:5 }
+function "ex1a" { 5:31 - 12:9 }
+function "ex1b" { 7:35 - 10:13 }
+eval { 1:1 - 1:56 }
+eval { 1:1 - 1:246 }
+function "ex2" { 1:65 - 1:237 }
+function "ex2a" { 1:100 - 1:226 }
+function "ex2b" { 1:136 - 1:215 }
+eval { 1:1 - 1:56 }
+eval { 1:1 - 17:8 }
+function "exi1" { 4:27 - 15:5 }
+function "exi1a" { 6:32 - 13:9 }
+function "exi1b" { 8:36 - 11:13 }
+eval { 1:1 - 1:56 }
+eval { 1:1 - 1:255 }
+function "exi2" { 1:66 - 1:245 }
+function "exi2a" { 1:103 - 1:233 }
+function "exi2b" { 1:141 - 1:221 }
+eval { 1:1 - 1:56 }
+
+  new Function Object:
+function "" { 1:1 - 1:228 }
+function "nf1a" { 1:60 - 1:219 }
+function "nf1b" { 1:90 - 1:209 }
+function "nf1c" { 1:120 - 1:199 }
+eval { 1:1 - 1:56 }
+function "" { 1:1 - 17:8 }
+function "nf2a" { 4:21 - 15:5 }
+function "nf2b" { 6:25 - 13:9 }
+function "nf2c" { 8:29 - 11:13 }
+eval { 1:1 - 1:56 }
+function "" { 1:1 - 1:228 }
+function "nf1a" { 1:60 - 1:219 }
+function "nf1b" { 1:90 - 1:209 }
+function "nf1c" { 1:120 - 1:199 }
+eval { 1:1 - 1:56 }
+function "" { 1:1 - 1:237 }
+function "nfi1a" { 1:61 - 1:227 }
+function "nfi1b" { 1:93 - 1:216 }
+function "nfi1c" { 1:125 - 1:205 }
+eval { 1:1 - 1:56 }
+function "" { 1:1 - 17:8 }
+function "nf2a" { 4:21 - 15:5 }
+function "nf2b" { 6:25 - 13:9 }
+function "nf2c" { 8:29 - 11:13 }
+eval { 1:1 - 1:56 }
+function "" { 1:1 - 17:9 }
+function "nfi2a" { 4:22 - 15:5 }
+function "nfi2b" { 6:26 - 13:9 }
+function "nfi2c" { 8:30 - 11:13 }
+eval { 1:1 - 1:56 }
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/script-start-end-locations.html b/LayoutTests/js/dom/script-start-end-locations.html
new file mode 100644 (file)
index 0000000..2f974e1
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+
+    // Convenience function so that script-tests/script-start-end-locations.js
+    // can be less verbose for cases where we have a function whose bounds we
+    // want to dump.
+    function dump(func) {
+        debug(window.internals.parserMetaData(func));
+    }
+
+    debug(window.internals.parserMetaData());
+
+    var dummy = 5;
+</script>
+
+<script>debug(window.internals.parserMetaData());</script> <script>debug(window.internals.parserMetaData());</script> 
+
+<script>debug(window.internals.parserMetaData());</script> <script>debug(window.internals.parserMetaData());</script>
+
+<script>debug(window.internals.parserMetaData());
+</script>
+    <script>debug(window.internals.parserMetaData());
+</script>
+
+<script>function hf1() { dummy += 5; } hf1(); dump(hf1);</script>
+    <script>function hf2() { dummy += 5; } hf2(); dump(hf2); </script>
+        <script>function hf3() { dummy += 5; } hf3(); dump(hf3); </script>
+
+<script>function hf4() {
+            dummy += 5; 
+        } hf4(); dump(hf4);</script>
+    <script>function hf5() {
+            dummy += 5; 
+        } hf5(); dump(hf5);</script>
+        <script>function hf6() {
+            dummy += 5; 
+        } hf6(); dump(hf6);</script>
+
+<script>
+function hf7() {
+        dummy += 5; 
+    } hf7(); dump(hf7);</script>
+
+<script>var v = 1; function hf8() { v += 5; } hf8(); dump(hf8);</script> <script>function hf9() { v += 5; } hf9(); dump(hf9); debug("");</script>
+
+<script src="script-tests/script-start-end-locations.js"></script> 
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/script-tests/script-start-end-locations.js b/LayoutTests/js/dom/script-tests/script-start-end-locations.js
new file mode 100644 (file)
index 0000000..573bc84
--- /dev/null
@@ -0,0 +1,473 @@
+var value = 10; var sum = 1; debug(window.internals.parserMetaData()); debug("\n  On first line:"); function f0() { dump(f0); function f0a() { dump(f0a); function f0b() { dump(f0b); eval('sum += value; debug(window.internals.parserMetaData());'); } f0b(); } f0a(); } f0();  var x0 = function(key) { dump(x0);var x0a = function() { dump(x0a); var x0b = function() { dump(x0b); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; x0b(); }; x0a(); }; x0();
+
+function globalFunc() {
+    var array = [2];
+    var sum = 0;
+    var value = 5;
+
+    debug("\n  Functions Declarations in a function:");
+    function f1(key) { dump(f1); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+    f1();
+
+    function f2(key) {
+        dump(f2);
+        function f2a() { dump(f2a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+        f2a();
+    }
+    f2();
+
+    function f3(key) {
+        dump(f3);
+        function f3a() {
+            dump(f3a);
+            function f3b() {
+                dump(f3b);
+                sum += value; sum *= value;
+                eval('sum += value; debug(window.internals.parserMetaData());');
+            }
+            f3b();
+        }
+        f3a();
+    }
+    f3();
+
+    function f4(key) { dump(f4); function f4a() {}; dump(f4a); f4a(); }
+    f4();
+    function f5(key) { dump(f5); function f5a() { dump(f5a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; f5a(); }
+    f5();
+    function f6(key) { dump(f6); function f6a() { dump(f6a); function f6b() { dump(f6b); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; f6b(); }; f6a(); }
+    f6();
+
+    debug("\n  Indented Functions Declarations in a function:");
+    {
+        function fi1(key) { dump(fi1); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+        fi1();
+
+        function fi2(key) {
+            dump(fi2);
+            function fi2a() { dump(fi2a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+            fi2a();
+        }
+        fi2();
+
+        function fi3(key) {
+            dump(fi3);
+            function fi3a() {
+                dump(fi3a);
+                function fi3b() {
+                    dump(fi3b);
+                    sum += value; sum *= value;
+                    eval('sum += value; debug(window.internals.parserMetaData());');
+                }
+                fi3b();
+            }
+            fi3a();
+        }
+        fi3();
+
+        function fi4(key) { dump(fi4); function fi4a() {}; dump(fi4a); fi4a(); }
+        fi4();
+        function fi5(key) { dump(fi5); function fi5a() { dump(fi5a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; fi5a(); }
+        fi5();
+        function fi6(key) { dump(fi6); function fi6a() { dump(fi6a); function fi6b() { dump(fi6b); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; fi6b(); }; fi6a(); }
+        fi6();
+    }
+
+    debug("\n  Functions Expressions in a function:");
+    var x1 = function(key) { dump(x1); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+    x1();
+
+    var x2 = function(key) {
+        dump(x2);
+        var x2a = function() { dump(x2a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+        x2a();
+    }
+    x2();
+
+    var x3 = function(key) {
+        dump(x3);
+        var x3a = function() {
+            dump(x3a);
+            var x3b = function() {
+                dump(x3b);
+                sum += value;
+                eval('sum += value; debug(window.internals.parserMetaData());');
+            }
+            x3b();
+        }
+        x3a();
+    }
+    x3();
+
+    var x4 = function(key) { dump(x4); var x4a = function() {}; dump(x4a); x4a(); }
+    x4();
+    var x5 = function(key) { dump(x5); var x5a = function() { dump(x5a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; x5a(); }
+    x5();
+    var x6 = function(key) { dump(x6); var x6a = function() { dump(x6a); var x6b = function() { dump(x6b); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; x6b(); }; x6a(); }
+    x6();
+
+    debug("\n  Indented Functions Expressions in a function:");
+    {
+        var xi1 = function(key) { dump(xi1); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+        xi1();
+
+        var xi2 = function(key) {
+            dump(xi2);
+            var xi2a = function() { dump(xi2a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+            xi2a();
+        }
+        xi2();
+
+        var xi3 = function(key) {
+            dump(xi3);
+            var xi3a = function() {
+                dump(xi3a);
+                var xi3b = function() {
+                    dump(xi3b);
+                    sum += value; sum *= value;
+                    eval('sum += value; debug(window.internals.parserMetaData());');
+                }
+                xi3b();
+            }
+            xi3a();
+        }
+        xi3();
+
+        var xi4 = function(key) { dump(xi4); var xi4a = function() {}; dump(xi4a); xi4a(); }
+        xi4();
+        var xi5 = function(key) { dump(xi5); var xi5a = function() { dump(xi5a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; xi5a(); }
+        xi5();
+        var xi6 = function(key) { dump(xi6); var xi6a = function() { dump(xi6a); var xi6b = function() { dump(xi6b); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; xi6b(); }; xi6a(); }
+        xi6();
+    }
+
+    debug("\n  Anonymous Function Declaration in a function:");
+    var forEach = [ ].forEach;
+    var boundForEach = forEach.bind(array, function(key) {
+        debug(window.internals.parserMetaData());
+        sum += value;
+        sum *= value;
+        eval('sum += value; debug(window.internals.parserMetaData());');
+    });
+    boundForEach();
+
+}
+globalFunc();
+
+debug("\n  Global eval:");
+eval('sum += value; debug(window.internals.parserMetaData());');
+
+debug("\n  Global Functions Declarations:");
+function gf1(key) { dump(gf1); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+gf1();
+
+function gf2(key) {
+    dump(gf2);
+    function gf2a() { dump(gf2a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+    gf2a();
+}
+gf2();
+
+function gf3(key) {
+    dump(gf3);
+    function gf3a() {
+        dump(gf3a);
+        function gf3b() {
+            dump(gf3b);
+            sum += value; sum *= value;
+            eval('sum += value; debug(window.internals.parserMetaData());');
+        }
+        gf3b();
+    }
+    gf3a();
+}
+gf3();
+
+function gf4(key) { dump(gf4); function gf4a() {}; dump(gf4a); gf4a(); }
+gf4();
+function gf5(key) { dump(gf5); function gf5a() { dump(gf5a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; gf5a(); }
+gf5();
+function gf6(key) { dump(gf6); function gf6a() { dump(gf6a); function gf6b() { dump(gf6b); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; gf6b(); }; gf6a(); }
+gf6();
+
+debug("\n  Indented Global Functions Declarations:");
+{
+    function gfi1(key) { dump(gfi1); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+    gfi1();
+
+    function gfi2(key) {
+        dump(gfi2);
+        function gfi2a() { dump(gfi2a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+        gfi2a();
+    }
+    gfi2();
+
+    function gfi3(key) {
+        dump(gfi3);
+        function gfi3a() {
+            dump(gfi3a);
+            function gfi3b() {
+                dump(gfi3b);
+                sum += value; sum *= value;
+                eval('sum += value; debug(window.internals.parserMetaData());');
+            }
+            gfi3b();
+        }
+        gfi3a();
+    }
+    gfi3();
+
+    function gfi4(key) { dump(gfi4); function gfi4a() {}; dump(gfi4a); gfi4a(); }
+    gfi4();
+    function gfi5(key) { dump(gfi5); function gfi5a() { dump(gfi5a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; gfi5a(); }
+    gfi5();
+    function gfi6(key) { dump(gfi6); function gfi6a() { dump(gfi6a); function gfi6b() { dump(gfi6b); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; gfi6b(); }; gfi6a(); }
+    gfi6();
+}
+
+debug("\n  Global Functions Expressions:");
+var gx1 = function(key) { dump(gx1); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+gx1();
+
+var gx2 = function(key) {
+    dump(gx2);
+    var gx2a = function() { dump(gx2a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+    gx2a();
+}
+gx2();
+
+var gx3 = function(key) {
+    dump(gx3);
+    var gx3a = function() {
+        dump(gx3a);
+        var gx3b = function() {
+            dump(gx3b);
+            sum += value;
+            eval('sum += value; debug(window.internals.parserMetaData());');
+        }
+        gx3b();
+    }
+    gx3a();
+}
+gx3();
+
+var gx4 = function(key) { dump(gx4); var gx4a = function() {}; dump(gx4a); gx4a(); }
+gx4();
+var gx5 = function(key) { dump(gx5); var gx5a = function() { dump(gx5a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; gx5a(); }
+gx5();
+var gx6 = function(key) { dump(gx6); var gx6a = function() { dump(gx6a); var gx6b = function() { dump(gx6b); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; gx6b(); }; gx6a(); }
+gx6();
+
+debug("\n  Indented Functions Declarations:");
+{
+    var gxi1 = function(key) { dump(gxi1); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+    gxi1();
+
+    var gxi2 = function(key) {
+        dump(gxi2);
+        var gxi2a = function() { dump(gxi2a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }
+        gxi2a();
+    }
+    gxi2();
+
+    var gxi3 = function(key) {
+        dump(gxi3);
+        var gxi3a = function() {
+            dump(gxi3a);
+            var gxi3b = function() {
+                dump(gxi3b);
+                sum += value; sum *= value;
+                eval('sum += value; debug(window.internals.parserMetaData());');
+            }
+            gxi3b();
+        }
+        gxi3a();
+    }
+    gxi3();
+
+    var gxi4 = function(key) { dump(gxi4); var gxi4a = function() {}; dump(gxi4a); gxi4a(); }
+    gxi4();
+    var gxi5 = function(key) { dump(gxi5); var gxi5a = function() { dump(gxi5a); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; gxi5a(); }
+    gxi5();
+    var gxi6 = function(key) { dump(gxi6); var gxi6a = function() { dump(gxi6a); var gxi6b = function() { dump(gxi6b); sum += value; eval('sum += value; debug(window.internals.parserMetaData());'); }; gxi6b(); }; gxi6a(); }
+    gxi6();
+}
+
+debug("\n  Anonymous Global Function Declarations:");
+var array = [2];
+var gforEach = [ ].forEach;
+var gboundForEach = gforEach.bind(array, function(key) {
+    debug(window.internals.parserMetaData());
+    sum += value;
+    sum *= value;
+    eval('sum += value; debug(window.internals.parserMetaData());');
+});
+gboundForEach();
+
+debug("\n  Function Declarations in an eval:");
+eval(" \n" +
+"    debug(window.internals.parserMetaData());\n" +
+"    function ef1() {\n" +
+"        dump(ef1);\n" +
+"        function ef1a() {\n" +
+"            dump(ef1a);\n" +
+"            function ef1b() {\n" +
+"                dump(ef1b);\n" +
+"                eval('sum += value; debug(window.internals.parserMetaData());');\n" +
+"            }\n" +
+"            ef1b();\n" +
+"        }\n" +
+"        ef1a();\n" +
+"    }\n" +
+"\n" +
+"ef1();"
+);
+
+eval(" debug(window.internals.parserMetaData()); function ef2() { dump(ef2); function ef2a() { dump(ef2a); function ef2b() { dump(ef2b); eval('sum += value; debug(window.internals.parserMetaData());'); } ef2b(); } ef2a(); } ef2();");
+
+{
+    eval(" \n" +
+         "    debug(window.internals.parserMetaData());\n" +
+         "    // Test indented function with inner functions. \n" +
+         "    function efi1() {\n" +
+         "        dump(efi1);\n" +
+         "        function efi1a() {\n" +
+         "            dump(efi1a);\n" +
+         "            function efi1b() {\n" +
+         "                dump(efi1b);\n" +
+         "                eval('sum += value; debug(window.internals.parserMetaData());');\n" +
+         "            }\n" +
+         "            efi1b();\n" +
+         "        }\n" +
+         "        efi1a();\n" +
+         "    }\n" +
+         "\n" +
+         "efi1();"
+        );
+
+    eval(" debug(window.internals.parserMetaData()); function efi2() { dump(efi2); function efi2a() { dump(efi2a); function efi2b() { dump(efi2b); eval('sum += value; debug(window.internals.parserMetaData());'); } efi2b(); } efi2a(); } efi2();");
+}
+
+debug("\n  Function Expressions in an eval:");
+eval(" \n" +
+"    debug(window.internals.parserMetaData());\n" +
+"    var ex1 = function() {\n" +
+"        dump(ex1);\n" +
+"        var ex1a = function() {\n" +
+"            dump(ex1a);\n" +
+"            var ex1b = function() {\n" +
+"                dump(ex1b);\n" +
+"                eval('sum += value; debug(window.internals.parserMetaData());');\n" +
+"            }\n" +
+"            ex1b();\n" +
+"        }\n" +
+"        ex1a();\n" +
+"    }\n" +
+"\n" +
+"ex1();"
+);
+
+eval(" debug(window.internals.parserMetaData()); var ex2 = function() { dump(ex2); var ex2a = function() { dump(ex2a); var ex2b = function() { dump(ex2b); eval('sum += value; debug(window.internals.parserMetaData());'); }; ex2b(); }; ex2a(); }; ex2();");
+
+{
+    eval(" \n" +
+         "    debug(window.internals.parserMetaData());\n" +
+         "    // Test indented function with inner functions. \n" +
+         "    var exi1 = function() {\n" +
+         "        dump(exi1);\n" +
+         "        var exi1a = function() {\n" +
+         "            dump(exi1a);\n" +
+         "            var exi1b = function() {\n" +
+         "                dump(exi1b);\n" +
+         "                eval('sum += value; debug(window.internals.parserMetaData());');\n" +
+         "            }\n" +
+         "            exi1b();\n" +
+         "        }\n" +
+         "        exi1a();\n" +
+         "    }\n" +
+         "\n" +
+         "exi1();"
+        );
+
+    eval(" debug(window.internals.parserMetaData()); var exi2 = function() { dump(exi2); var exi2a = function() { dump(exi2a); var exi2b = function() { dump(exi2b); eval('sum += value; debug(window.internals.parserMetaData());'); }; exi2b(); }; exi2a(); }; exi2();");
+}
+
+debug("\n  new Function Object:");
+var nf1Str =
+" debug(window.internals.parserMetaData()); function nf1a() { dump(nf1a); function nf1b() { dump(nf1b); function nf1c() { dump(nf1c); eval('sum += value; debug(window.internals.parserMetaData());'); } nf1c(); } nf1b(); } nf1a();";
+var nf1 = new Function("a", "b", nf1Str);
+nf1();
+
+var nf2Str =
+" \n" +
+"    debug(window.internals.parserMetaData());\n" +
+"    // Test indented function with inner functions. \n" +
+"    function nf2a() {\n" +
+"        dump(nf2a);\n" +
+"        function nf2b() {\n" +
+"            dump(nf2b);\n" +
+"            function nf2c() {\n" +
+"                dump(nf2c);\n" +
+"                eval('sum += value; debug(window.internals.parserMetaData());');\n" +
+"            }\n" +
+"            nf2c();\n" +
+"        }\n" +
+"        nf2b();\n" +
+"    }\n" +
+"\n" +
+"nf2a();";
+var nf2 = new Function("a", "b", nf2Str);
+nf2();
+
+{
+    // nfi1_0 has an identical script string as nf1 except we indented it here.
+    var nfi1_0 = new Function("a", "b", " debug(window.internals.parserMetaData()); function nf1a() { dump(nf1a); function nf1b() { dump(nf1b); function nf1c() { dump(nf1c); eval('sum += value; debug(window.internals.parserMetaData());'); } nf1c(); } nf1b(); } nf1a();");
+    nfi1_0();
+
+    var nfi1 = new Function("a", "b", " debug(window.internals.parserMetaData()); function nfi1a() { dump(nfi1a); function nfi1b() { dump(nfi1b); function nfi1c() { dump(nfi1c); eval('sum += value; debug(window.internals.parserMetaData());'); } nfi1c(); } nfi1b(); } nfi1a();");
+    nfi1();
+
+    // nfi2_0 has an identical script string as nf2 except we indented it here.
+    var nfi2_0 = new Function("a", "b",
+        " \n" +
+        "    debug(window.internals.parserMetaData());\n" +
+        "    // Test indented function with inner functions. \n" +
+        "    function nf2a() {\n" +
+        "        dump(nf2a);\n" +
+        "        function nf2b() {\n" +
+        "            dump(nf2b);\n" +
+        "            function nf2c() {\n" +
+        "                dump(nf2c);\n" +
+        "                eval('sum += value; debug(window.internals.parserMetaData());');\n" +
+        "            }\n" +
+        "            nf2c();\n" +
+        "        }\n" +
+        "        nf2b();\n" +
+        "    }\n" +
+        "\n" +
+        "nf2a();"
+    );
+    nfi2_0();
+
+    var nfi2 = new Function("a", "b",
+        " \n" +
+        "    debug(window.internals.parserMetaData());\n" +
+        "    // Test indented function with inner functions. \n" +
+        "    function nfi2a() {\n" +
+        "        dump(nfi2a);\n" +
+        "        function nfi2b() {\n" +
+        "            dump(nfi2b);\n" +
+        "            function nfi2c() {\n" +
+        "                dump(nfi2c);\n" +
+        "                eval('sum += value; debug(window.internals.parserMetaData());');\n" +
+        "            }\n" +
+        "            nfi2c();\n" +
+        "        }\n" +
+        "        nfi2b();\n" +
+        "    }\n" +
+        "\n" +
+        "nfi2a();"
+    );
+    nfi2();
+}
+debug("");
index 9020f24c596a86504d0138925df2eff5ba7d2eab..b64a58018613fcc341c67fc553a7977436ad4aac 100644 (file)
@@ -38,13 +38,13 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
     2   global code at stack-trace.js:47:18
 
 --> Stack Trace:
-    0   htmlInner at stack-trace.html:10:39
+    0   htmlInner at stack-trace.html:10:51
     1   scripterInner at stack-trace.js:32:37
     2   global code at stack-trace.js:49:20
 
 --> Stack Trace:
-    0   htmlInner at stack-trace.html:10:39
-    1   htmlOuter at stack-trace.html:11:33
+    0   htmlInner at stack-trace.html:10:51
+    1   htmlOuter at stack-trace.html:11:45
     2   scripterOuter at stack-trace.js:33:37
     3   global code at stack-trace.js:50:20
 
index be8cacfe49a57d13f0bd8a38f9230aa8494b2a8a..eb29d303e18636ef1c9bf23cc18cfd60dcbda815 100644 (file)
@@ -5,10 +5,10 @@
 </head>
 
 <body>
-       <p id="description"></p>
-       <p id="console"></p>
-       <script>function htmlInner() { throw new Error("Error in HTML"); }</script>
-       <script>function htmlOuter() { htmlInner(); }</script>
-       <script src="script-tests/stack-trace.js"></script>
+    <p id="description"></p>
+    <p id="console"></p>
+    <script>function htmlInner() { throw new Error("Error in HTML"); }</script>
+    <script>function htmlOuter() { htmlInner(); }</script>
+    <script src="script-tests/stack-trace.js"></script>
 </body>
 </html>
index 4cb785df4fcf28fbe2c505def354f10e8e8eae65..266228f9d4e186c9fd68b9d6f94f9225dcb3df11 100644 (file)
@@ -1,3 +1,156 @@
+2013-11-19  Mark Lam  <mark.lam@apple.com>
+
+        Add tracking of endColumn for Executables.
+        https://bugs.webkit.org/show_bug.cgi?id=124245.
+
+        Reviewed by Geoffrey Garen.
+
+        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).
+
+        2. 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.
+
+        3. 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.
+
+        4. For unlinked executables, end column values are either:
+           a. Relative to the start of the last line if (last line != first line).
+           b. 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.
+
+        5. 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):
+
 2013-11-19  Dean Jackson  <dino@apple.com>
 
         MarkedSpace::resumeAllocating needs to delay release
index 2d18e4aae15bee794fb25e999d67de8cac4d51ed..c0cdd49e89aa2c14e2066a7adcd06e77d3d15869 100644 (file)
                0F24E54C17EE274900ABB217 /* JITOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F24E54517EE274900ABB217 /* JITOperations.cpp */; };
                0F24E54D17EE274900ABB217 /* JITOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E54617EE274900ABB217 /* JITOperations.h */; };
                0F24E54E17EE274900ABB217 /* JITOperationWrappers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E54717EE274900ABB217 /* JITOperationWrappers.h */; };
-               0F24E54F17EE274900ABB217 /* TempRegisterSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E54817EE274900ABB217 /* TempRegisterSet.h */; };
+               0F24E54F17EE274900ABB217 /* TempRegisterSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E54817EE274900ABB217 /* TempRegisterSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F24E55017EE274900ABB217 /* Repatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F24E54917EE274900ABB217 /* Repatch.cpp */; };
                0F24E55117EE274900ABB217 /* Repatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E54A17EE274900ABB217 /* Repatch.h */; };
                0F24E55217EE274900ABB217 /* ScratchRegisterAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F24E54B17EE274900ABB217 /* ScratchRegisterAllocator.h */; };
                A7BDAEC917F4EA1400F6140C /* ArrayIteratorPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = A7BDAEC317F4EA1400F6140C /* ArrayIteratorPrototype.h */; };
                A7BDAECA17F4EA1400F6140C /* JSArrayIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */; };
                A7BDAECB17F4EA1400F6140C /* JSArrayIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */; };
-               A7BFF3C0179868940002F462 /* DFGFiltrationResult.h in Headers */ = {isa = PBXBuildFile; fileRef = A7BFF3BF179868940002F462 /* DFGFiltrationResult.h */; };
+               A7BFF3C0179868940002F462 /* DFGFiltrationResult.h in Headers */ = {isa = PBXBuildFile; fileRef = A7BFF3BF179868940002F462 /* DFGFiltrationResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7C0C4AC168103020017011D /* JSScriptRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C0C4AB167C08CD0017011D /* JSScriptRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7C0C4AD1681067E0017011D /* JSScriptRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7C0C4AA167C08CD0017011D /* JSScriptRef.cpp */; };
                A7C1E8E4112E72EF00A37F98 /* JITPropertyAccess32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7C1E8C8112E701C00A37F98 /* JITPropertyAccess32_64.cpp */; };
                C2F0F2D116BAEEE900187C19 /* StructureRareData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F0F2D016BAEEE900187C19 /* StructureRareData.cpp */; };
                C2FC9BD316644DFB00810D33 /* CopiedBlockInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FC9BD216644DFB00810D33 /* CopiedBlockInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
                C2FCAE1017A9C24E0034C735 /* BytecodeBasicBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FCAE0C17A9C24E0034C735 /* BytecodeBasicBlock.cpp */; };
-               C2FCAE1117A9C24E0034C735 /* BytecodeBasicBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FCAE0D17A9C24E0034C735 /* BytecodeBasicBlock.h */; };
+               C2FCAE1117A9C24E0034C735 /* BytecodeBasicBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FCAE0D17A9C24E0034C735 /* BytecodeBasicBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
                C2FCAE1217A9C24E0034C735 /* BytecodeLivenessAnalysis.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FCAE0E17A9C24E0034C735 /* BytecodeLivenessAnalysis.cpp */; };
-               C2FCAE1317A9C24E0034C735 /* BytecodeLivenessAnalysis.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FCAE0F17A9C24E0034C735 /* BytecodeLivenessAnalysis.h */; };
+               C2FCAE1317A9C24E0034C735 /* BytecodeLivenessAnalysis.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FCAE0F17A9C24E0034C735 /* BytecodeLivenessAnalysis.h */; settings = {ATTRIBUTES = (Private, ); }; };
                C2FE18A416BAEC4000AF3061 /* StructureRareData.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FE18A316BAEC4000AF3061 /* StructureRareData.h */; settings = {ATTRIBUTES = (Private, ); }; };
                DDF7ABD411F60ED200108E36 /* GCActivityCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */ = {isa = PBXBuildFile; fileRef = E124A8F50E555775003091F1 /* OpaqueJSString.h */; settings = {ATTRIBUTES = (Private, ); }; };
                                86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
                                86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */,
                                65C0285D1717966800351E35 /* ARMv7DOpcode.h in Headers */,
+                               0F24E54F17EE274900ABB217 /* TempRegisterSet.h in Headers */,
+                               A7BFF3C0179868940002F462 /* DFGFiltrationResult.h in Headers */,
+                               C2FCAE1117A9C24E0034C735 /* BytecodeBasicBlock.h in Headers */,
+                               C2FCAE1317A9C24E0034C735 /* BytecodeLivenessAnalysis.h in Headers */,
                                0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */,
                                FEA08620182B7A0400F6D851 /* Breakpoint.h in Headers */,
                                A7A8AF3517ADB5F3005AB174 /* ArrayBuffer.h in Headers */,
                                A7A8AF3717ADB5F3005AB174 /* ArrayBufferView.h in Headers */,
                                BC18C3E60E16F5CD00B34460 /* ArrayConstructor.h in Headers */,
                                0FB7F39515ED8E4600F167B2 /* ArrayConventions.h in Headers */,
-                               C2FCAE1117A9C24E0034C735 /* BytecodeBasicBlock.h in Headers */,
                                A7BDAEC717F4EA1400F6140C /* ArrayIteratorConstructor.h in Headers */,
                                A7BDAEC917F4EA1400F6140C /* ArrayIteratorPrototype.h in Headers */,
                                0F63945515D07057006A597C /* ArrayProfile.h in Headers */,
                                A7986D5717A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h in Headers */,
                                0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */,
                                A78A9775179738B8009DF744 /* DFGFailedFinalizer.h in Headers */,
-                               A7BFF3C0179868940002F462 /* DFGFiltrationResult.h in Headers */,
                                A78A9777179738B8009DF744 /* DFGFinalizer.h in Headers */,
                                0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */,
                                0F9D339717FFC4E60073C2BC /* DFGFlushedAt.h in Headers */,
                                A730B6121250068F009D25B1 /* StrictEvalActivation.h in Headers */,
                                BC18C4660E16F5CD00B34460 /* StringConstructor.h in Headers */,
                                BC18C4680E16F5CD00B34460 /* StringObject.h in Headers */,
-                               C2FCAE1317A9C24E0034C735 /* BytecodeLivenessAnalysis.h in Headers */,
                                BC18C46A0E16F5CD00B34460 /* StringPrototype.h in Headers */,
                                142E313B134FF0A600AFADB5 /* Strong.h in Headers */,
                                145722861437E140005FDE26 /* StrongInlines.h in Headers */,
                                C2DF44301707AC0100A5CA96 /* SuperRegion.h in Headers */,
                                BC18C46B0E16F5CD00B34460 /* SymbolTable.h in Headers */,
                                A784A26411D16622005776AC /* SyntaxChecker.h in Headers */,
-                               0F24E54F17EE274900ABB217 /* TempRegisterSet.h in Headers */,
                                0FA2C17C17D7CF84009D015F /* TestRunnerUtils.h in Headers */,
                                0F572D4F16879FDD00E57FBD /* ThunkGenerator.h in Headers */,
                                A7386556118697B400540279 /* ThunkGenerators.h in Headers */,
index e63b1929f29a41f560e761264c53af1ce110c435..e3fefee46690b637faf6d6bd6ba75a01e3f7634b 100644 (file)
@@ -114,7 +114,7 @@ CString CodeBlock::sourceCodeForTools() const
     unsigned unlinkedStartOffset = unlinked->startOffset();
     unsigned linkedStartOffset = executable->source().startOffset();
     int delta = linkedStartOffset - unlinkedStartOffset;
-    unsigned rangeStart = delta + unlinked->functionStartOffset();
+    unsigned rangeStart = delta + unlinked->unlinkedFunctionNameStart();
     unsigned rangeEnd = delta + unlinked->startOffset() + unlinked->sourceLength();
     return toCString(
         "function ",
@@ -1638,12 +1638,14 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
         UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
         unsigned lineCount = unlinkedExecutable->lineCount();
         unsigned firstLine = ownerExecutable->lineNo() + unlinkedExecutable->firstLineOffset();
-        unsigned startColumn = unlinkedExecutable->functionStartColumn();
-        startColumn += (unlinkedExecutable->firstLineOffset() ? 1 : ownerExecutable->startColumn());
+        bool startColumnIsOnOwnerStartLine = !unlinkedExecutable->firstLineOffset();
+        unsigned startColumn = unlinkedExecutable->unlinkedBodyStartColumn() + (startColumnIsOnOwnerStartLine ? ownerExecutable->startColumn() : 1);
+        bool endColumnIsOnStartLine = !lineCount;
+        unsigned endColumn = unlinkedExecutable->unlinkedBodyEndColumn() + (endColumnIsOnStartLine ? startColumn : 1);
         unsigned startOffset = sourceOffset + unlinkedExecutable->startOffset();
         unsigned sourceLength = unlinkedExecutable->sourceLength();
         SourceCode code(m_source, startOffset, startOffset + sourceLength, firstLine, startColumn);
-        FunctionExecutable* executable = FunctionExecutable::create(*m_vm, code, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn);
+        FunctionExecutable* executable = FunctionExecutable::create(*m_vm, code, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn, endColumn);
         m_functionDecls[i].set(*m_vm, ownerExecutable, executable);
     }
 
@@ -1652,12 +1654,14 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
         UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i);
         unsigned lineCount = unlinkedExecutable->lineCount();
         unsigned firstLine = ownerExecutable->lineNo() + unlinkedExecutable->firstLineOffset();
-        unsigned startColumn = unlinkedExecutable->functionStartColumn();
-        startColumn += (unlinkedExecutable->firstLineOffset() ? 1 : ownerExecutable->startColumn());
+        bool startColumnIsOnOwnerStartLine = !unlinkedExecutable->firstLineOffset();
+        unsigned startColumn = unlinkedExecutable->unlinkedBodyStartColumn() + (startColumnIsOnOwnerStartLine ? ownerExecutable->startColumn() : 1);
+        bool endColumnIsOnStartLine = !lineCount;
+        unsigned endColumn = unlinkedExecutable->unlinkedBodyEndColumn() + (endColumnIsOnStartLine ? startColumn : 1);
         unsigned startOffset = sourceOffset + unlinkedExecutable->startOffset();
         unsigned sourceLength = unlinkedExecutable->sourceLength();
         SourceCode code(m_source, startOffset, startOffset + sourceLength, firstLine, startColumn);
-        FunctionExecutable* executable = FunctionExecutable::create(*m_vm, code, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn);
+        FunctionExecutable* executable = FunctionExecutable::create(*m_vm, code, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn, endColumn);
         m_functionExprs[i].set(*m_vm, ownerExecutable, executable);
     }
 
index d13aa65a533e2ca36d3339a0663e0d3efd6d9ab8..9ef6dcf46c6ec7a5e15ae7e14f68e399ba760659 100644 (file)
@@ -59,7 +59,7 @@ static UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(VM& vm, UnlinkedFunc
     if (executable->forceUsesArguments())
         body->setUsesArguments();
     body->finishParsing(executable->parameters(), executable->name(), executable->functionNameIsInScopeToggle());
-    executable->recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
+    executable->recordParse(body->features(), body->hasCapturedVariables());
     
     UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(body->needsActivation(), body->usesEval(), body->isStrictMode(), kind == CodeForConstruct));
     OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(vm, body.get(), result, debuggerMode, profilerMode)));
@@ -80,19 +80,21 @@ unsigned UnlinkedCodeBlock::addOrFindConstant(JSValue v)
     return addConstant(v);
 }
 
-UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, FunctionBodyNode* node)
+UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, FunctionBodyNode* node, bool isFromGlobalCode)
     : Base(*vm, structure)
     , m_numCapturedVariables(node->capturedVariableCount())
     , m_forceUsesArguments(node->usesArguments())
     , m_isInStrictContext(node->isStrictMode())
     , m_hasCapturedVariables(node->hasCapturedVariables())
+    , m_isFromGlobalCode(isFromGlobalCode)
     , m_name(node->ident())
     , m_inferredName(node->inferredName())
     , m_parameters(node->parameters())
     , m_firstLineOffset(node->firstLine() - source.firstLine())
     , m_lineCount(node->lastLine() - node->firstLine())
-    , m_functionStartOffset(node->functionStart() - source.startOffset())
-    , m_functionStartColumn(node->startColumn())
+    , m_unlinkedFunctionNameStart(node->functionNameStart() - source.startOffset())
+    , m_unlinkedBodyStartColumn(node->startColumn())
+    , m_unlinkedBodyEndColumn(m_lineCount ? node->endColumn() : node->endColumn() - node->startColumn())
     , m_startOffset(node->source().startOffset() - source.startOffset())
     , m_sourceLength(node->source().length())
     , m_features(node->features())
@@ -123,16 +125,20 @@ FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& s
 {
     unsigned firstLine = lineOffset + m_firstLineOffset;
     unsigned startOffset = sourceOffset + m_startOffset;
-    unsigned startColumn = m_functionStartColumn + 1; // startColumn should start from 1, not 0.
+    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);
-    return FunctionExecutable::create(vm, code, this, firstLine, firstLine + m_lineCount, startColumn);
+    return FunctionExecutable::create(vm, code, this, firstLine, firstLine + m_lineCount, startColumn, endColumn);
 }
 
 UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger*, const SourceCode& source, JSObject** exception)
 {
     ParserError error;
-    CodeCache* codeCache = exec->vm().codeCache();
-    UnlinkedFunctionExecutable* executable = codeCache->getFunctionExecutableFromGlobalCode(exec->vm(), name, source, error);
+    VM& vm = exec->vm();
+    CodeCache* codeCache = vm.codeCache();
+    UnlinkedFunctionExecutable* executable = codeCache->getFunctionExecutableFromGlobalCode(vm, name, source, error);
 
     if (exec->lexicalGlobalObject()->hasDebugger())
         exec->lexicalGlobalObject()->debugger()->sourceParsed(exec, source.provider(), error.m_line, error.m_message);
@@ -204,6 +210,7 @@ UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType code
     , m_hasCapturedVariables(false)
     , m_firstLine(0)
     , m_lineCount(0)
+    , m_endColumn(UINT_MAX)
     , m_features(0)
     , m_codeType(codeType)
     , m_arrayProfileCount(0)
index 48a9ba1c20fcb8cf2d58beda145798eea897cddb..545e87f7a2eabfe98a2cf41dd49551d59b5aed17 100644 (file)
@@ -83,9 +83,9 @@ class UnlinkedFunctionExecutable : public JSCell {
 public:
     friend class CodeCache;
     typedef JSCell Base;
-    static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionBodyNode* node)
+    static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionBodyNode* node, bool isFromGlobalCode = false)
     {
-        UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node);
+        UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node, isFromGlobalCode);
         instance->finishCreation(*vm);
         return instance;
     }
@@ -103,8 +103,9 @@ public:
 
     unsigned firstLineOffset() const { return m_firstLineOffset; }
     unsigned lineCount() const { return m_lineCount; }
-    unsigned functionStartOffset() const { return m_functionStartOffset; }
-    unsigned functionStartColumn() const { return m_functionStartColumn; }
+    unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; }
+    unsigned unlinkedBodyStartColumn() const { return m_unlinkedBodyStartColumn; }
+    unsigned unlinkedBodyEndColumn() const { return m_unlinkedBodyEndColumn; }
     unsigned startOffset() const { return m_startOffset; }
     unsigned sourceLength() { return m_sourceLength; }
 
@@ -126,11 +127,10 @@ public:
 
     FunctionParameters* parameters() { return m_parameters.get(); }
 
-    void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
+    void recordParse(CodeFeatures features, bool hasCapturedVariables)
     {
         m_features = features;
         m_hasCapturedVariables = hasCapturedVariables;
-        m_lineCount = lastLine - firstLine;
     }
 
     bool forceUsesArguments() const { return m_forceUsesArguments; }
@@ -143,7 +143,7 @@ public:
     static void destroy(JSCell*);
 
 private:
-    UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionBodyNode*);
+    UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionBodyNode*, bool isFromGlobalCode);
     WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
     WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
 
@@ -151,6 +151,7 @@ private:
     bool m_forceUsesArguments : 1;
     bool m_isInStrictContext : 1;
     bool m_hasCapturedVariables : 1;
+    bool m_isFromGlobalCode : 1;
 
     Identifier m_name;
     Identifier m_inferredName;
@@ -160,8 +161,9 @@ private:
     RefPtr<FunctionParameters> m_parameters;
     unsigned m_firstLineOffset;
     unsigned m_lineCount;
-    unsigned m_functionStartOffset;
-    unsigned m_functionStartColumn;
+    unsigned m_unlinkedFunctionNameStart;
+    unsigned m_unlinkedBodyStartColumn;
+    unsigned m_unlinkedBodyEndColumn;
     unsigned m_startOffset;
     unsigned m_sourceLength;
 
@@ -186,7 +188,7 @@ public:
 
     static const unsigned StructureFlags = OverridesVisitChildren | JSCell::StructureFlags;
 
-    DECLARE_INFO;
+    DECLARE_EXPORT_INFO;
 };
 
 struct UnlinkedStringJumpTable {
@@ -441,18 +443,22 @@ public:
     void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
         int& startOffset, int& endOffset, unsigned& line, unsigned& column);
 
-    void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount)
+    void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn)
     {
         m_features = features;
         m_hasCapturedVariables = hasCapturedVariables;
         m_firstLine = firstLine;
         m_lineCount = lineCount;
+        // For the UnlinkedCodeBlock, startColumn is always 0.
+        m_endColumn = endColumn;
     }
 
     CodeFeatures codeFeatures() const { return m_features; }
     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
     unsigned firstLine() const { return m_firstLine; }
     unsigned lineCount() const { return m_lineCount; }
+    ALWAYS_INLINE unsigned startColumn() const { return 0; }
+    unsigned endColumn() const { return m_endColumn; }
 
 protected:
     UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&);
@@ -492,6 +498,7 @@ private:
     bool m_hasCapturedVariables : 1;
     unsigned m_firstLine;
     unsigned m_lineCount;
+    unsigned m_endColumn;
 
     CodeFeatures m_features;
     CodeType m_codeType;
index 9d3b151723044775b6a54c18f66f6f58304f5a37..33f0d9454001b78c45dd8237538d59de9c47d6bc 100644 (file)
@@ -2254,8 +2254,8 @@ void FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
     // If there is no return we must automatically insert one.
     if (!returnNode) {
         RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
-        ASSERT((startOffset() -  1) >= lineStartOffset());
-        generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset() - 1, lineStartOffset());
+        ASSERT(startOffset() >= lineStartOffset());
+        generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
         generator.emitReturn(r0);
         return;
     }
index c16a7fd0dde383854f0127eaa9d91ed7dc21186b..eac1e7d3d32e8bc6717c197c19a1afa90d555c23 100644 (file)
@@ -283,14 +283,14 @@ public:
         return result;
     }
 
-    FunctionBodyNode* createFunctionBody(const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, bool inStrictContext)
+    FunctionBodyNode* createFunctionBody(const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, bool inStrictContext)
     {
-        return FunctionBodyNode::create(m_vm, startLocation, endLocation, startColumn, inStrictContext);
+        return FunctionBodyNode::create(m_vm, startLocation, endLocation, startColumn, endColumn, inStrictContext);
     }
 
-    void setFunctionStart(FunctionBodyNode* body, int functionStart)
+    void setFunctionNameStart(FunctionBodyNode* body, int functionNameStart)
     {
-        body->setFunctionStart(functionStart);
+        body->setFunctionNameStart(functionNameStart);
     }
     
     template <bool> PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, unsigned openBraceOffset, unsigned closeBraceOffset, int bodyStartLine, int bodyEndLine, unsigned bodyStartColumn)
index e5321f97b6255440a3ba51cfe03247e264916b22..2211f552bd725cb3915418cfcd7a34ababd6836d 100644 (file)
@@ -618,6 +618,7 @@ void Lexer<T>::shiftLineTerminator()
 {
     ASSERT(isLineTerminator(m_current));
 
+    m_positionBeforeLastNewline = currentPosition();
     T prev = m_current;
     shift();
 
@@ -1853,14 +1854,6 @@ void Lexer<T>::clear()
     m_isReparsing = false;
 }
 
-template <typename T>
-SourceCode Lexer<T>::sourceCode(int openBrace, int closeBrace, int firstLine, unsigned startColumn)
-{
-    ASSERT(m_source->provider()->source()[openBrace] == '{');
-    ASSERT(m_source->provider()->source()[closeBrace] == '}');
-    return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine, startColumn);
-}
-
 // Instantiate the two flavors of Lexer we need instead of putting most of this file in Lexer.h
 template class Lexer<LChar>;
 template class Lexer<UChar>;
index 91b322637da9a55d9b3b7098b530709ab85537e5..28c61ba198d2c15a49bb1852ed30befeb8904008 100644 (file)
@@ -95,10 +95,10 @@ public:
     {
         return JSTextPosition(m_lineNumber, currentOffset(), currentLineStartOffset());
     }
+    JSTextPosition positionBeforeLastNewline() const { return m_positionBeforeLastNewline; }
     void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; }
     int lastLineNumber() const { return m_lastLineNumber; }
     bool prevTerminator() const { return m_terminator; }
-    SourceCode sourceCode(int openBrace, int closeBrace, int firstLine, unsigned startColumn);
     bool scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix = 0);
     bool skipRegExp();
 
@@ -227,6 +227,7 @@ private:
     const T* m_codeEnd;
     const T* m_codeStartPlusOffset;
     const T* m_lineStart;
+    JSTextPosition m_positionBeforeLastNewline;
     bool m_isReparsing;
     bool m_atLineStart;
     bool m_error;
index d8ddeafaeeb01aac8c2fd8105f15e92715c0b9bf..fc9ccd9f6c576c1aef547f211fdd596f42e05806 100644 (file)
@@ -114,15 +114,16 @@ StatementNode* ScopeNode::singleStatement() const
 
 // ------------------------------ ProgramNode -----------------------------
 
-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)
+inline 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)
     : ScopeNode(vm, startLocation, endLocation, source, children, varStack, funcStack, capturedVariables, features, numConstants)
     , m_startColumn(startColumn)
+    , m_endColumn(endColumn)
 {
 }
 
-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)
+PassRefPtr<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)
 {
-    RefPtr<ProgramNode> node = new ProgramNode(vm, startLocation, endLocation, startColumn, children, varStack, funcStack,  capturedVariables, source, features, numConstants);
+    RefPtr<ProgramNode> node = new ProgramNode(vm, startLocation, endLocation, startColumn, endColumn, children, varStack, funcStack,  capturedVariables, source, features, numConstants);
 
     ASSERT(node->m_arena.last() == node);
     node->m_arena.removeLast();
@@ -133,14 +134,15 @@ PassRefPtr<ProgramNode> ProgramNode::create(VM* vm, const JSTokenLocation& start
 
 // ------------------------------ EvalNode -----------------------------
 
-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)
+inline 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)
     : ScopeNode(vm, startLocation, endLocation, source, children, varStack, funcStack, capturedVariables, features, numConstants)
+    , m_endColumn(endColumn)
 {
 }
 
-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)
+PassRefPtr<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)
 {
-    RefPtr<EvalNode> node = new EvalNode(vm, startLocation, endLocation, children, varStack, funcStack, capturedVariables, source, features, numConstants);
+    RefPtr<EvalNode> node = new EvalNode(vm, startLocation, endLocation, endColumn, children, varStack, funcStack, capturedVariables, source, features, numConstants);
 
     ASSERT(node->m_arena.last() == node);
     node->m_arena.removeLast();
@@ -179,15 +181,17 @@ FunctionParameters::~FunctionParameters()
         patterns()[i]->deref();
 }
 
-inline FunctionBodyNode::FunctionBodyNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, bool inStrictContext)
+inline FunctionBodyNode::FunctionBodyNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, bool inStrictContext)
     : ScopeNode(vm, startLocation, endLocation, inStrictContext)
     , m_startColumn(startColumn)
+    , m_endColumn(endColumn)
 {
 }
 
-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)
+inline 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)
     : ScopeNode(vm, startLocation, endLocation, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants)
     , m_startColumn(startColumn)
+    , m_endColumn(endColumn)
 {
 }
 
@@ -205,14 +209,14 @@ void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters,
     m_functionNameIsInScopeToggle = functionNameIsInScopeToggle;
 }
 
-FunctionBodyNode* FunctionBodyNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, bool inStrictContext)
+FunctionBodyNode* FunctionBodyNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, bool inStrictContext)
 {
-    return new FunctionBodyNode(vm, startLocation, endLocation, startColumn, inStrictContext);
+    return new FunctionBodyNode(vm, startLocation, endLocation, startColumn, endColumn, inStrictContext);
 }
 
-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)
+PassRefPtr<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)
 {
-    RefPtr<FunctionBodyNode> node = new FunctionBodyNode(vm, startLocation, endLocation, startColumn, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants);
+    RefPtr<FunctionBodyNode> node = new FunctionBodyNode(vm, startLocation, endLocation, startColumn, endColumn , children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants);
 
     ASSERT(node->m_arena.last() == node);
     node->m_arena.removeLast();
@@ -221,4 +225,10 @@ PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(VM* vm, const JSTokenLocat
     return node.release();
 }
 
+void FunctionBodyNode::setEndPosition(JSTextPosition position)
+{
+    m_lastLine = position.line;
+    m_endColumn = position.offset - position.lineStartOffset;
+}
+
 } // namespace JSC
index 5243a1f2d76451b78135fcc49eef1ff03fa30c46..990ff569ab0a211cd017d0fd8bfe582ecb1b651b 100644 (file)
@@ -192,7 +192,7 @@ namespace JSC {
         virtual bool isContinue() const { return false; }
         virtual bool isBlock() const { return false; }
 
-    private:
+    protected:
         int m_lastLine;
     };
 
@@ -1468,33 +1468,38 @@ namespace JSC {
     class ProgramNode : public ScopeNode {
     public:
         static const bool isFunctionNode = false;
-        static PassRefPtr<ProgramNode> create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+        static PassRefPtr<ProgramNode> create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
-        unsigned startColumn() { return m_startColumn; }
+        unsigned startColumn() const { return m_startColumn; }
+        unsigned endColumn() const { return m_endColumn; }
 
         static const bool scopeIsFunction = false;
 
     private:
-        ProgramNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+        ProgramNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) OVERRIDE;
 
         unsigned m_startColumn;
+        unsigned m_endColumn;
     };
 
     class EvalNode : public ScopeNode {
     public:
         static const bool isFunctionNode = false;
-        static PassRefPtr<EvalNode> create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+        static PassRefPtr<EvalNode> create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
-        unsigned startColumn() { return 1; }
+        ALWAYS_INLINE unsigned startColumn() const { return 0; }
+        unsigned endColumn() const { return m_endColumn; }
 
         static const bool scopeIsFunction = false;
 
     private:
-        EvalNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+        EvalNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) OVERRIDE;
+
+        unsigned m_endColumn;
     };
 
     class FunctionParameters : public RefCounted<FunctionParameters> {
@@ -1519,8 +1524,8 @@ namespace JSC {
     class FunctionBodyNode : public ScopeNode {
     public:
         static const bool isFunctionNode = true;
-        static FunctionBodyNode* create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, bool isStrictMode);
-        static PassRefPtr<FunctionBodyNode> create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+        static FunctionBodyNode* create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, bool isStrictMode);
+        static PassRefPtr<FunctionBodyNode> create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         FunctionParameters* parameters() const { return m_parameters.get(); }
         size_t parameterCount() const { return m_parameters->size(); }
@@ -1537,22 +1542,26 @@ namespace JSC {
         bool functionNameIsInScope() { return m_functionNameIsInScopeToggle == FunctionNameIsInScope; }
         FunctionNameIsInScopeToggle functionNameIsInScopeToggle() { return m_functionNameIsInScopeToggle; }
 
-        void setFunctionStart(int functionStart) { m_functionStart = functionStart; }
-        int functionStart() const { return m_functionStart; }
+        void setFunctionNameStart(int functionNameStart) { m_functionNameStart = functionNameStart; }
+        int functionNameStart() const { return m_functionNameStart; }
         unsigned startColumn() const { return m_startColumn; }
+        unsigned endColumn() const { return m_endColumn; }
+
+        void setEndPosition(JSTextPosition);
 
         static const bool scopeIsFunction = true;
 
     private:
-        FunctionBodyNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, bool inStrictContext);
-        FunctionBodyNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+        FunctionBodyNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, bool inStrictContext);
+        FunctionBodyNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         Identifier m_ident;
         Identifier m_inferredName;
         FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
         RefPtr<FunctionParameters> m_parameters;
-        int m_functionStart;
+        int m_functionNameStart;
         unsigned m_startColumn;
+        unsigned m_endColumn;
     };
 
     class FuncExprNode : public ExpressionNode {
index 881c984e36827ec5d4296fab976cb543ffa38558..495259248eb458d82c1e299641a301f7dd068673 100644 (file)
@@ -1162,13 +1162,16 @@ template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBo
     unsigned startColumn = tokenColumn();
     next();
 
-    if (match(CLOSEBRACE))
-        return context.createFunctionBody(startLocation, tokenLocation(), startColumn, strictMode());
+    if (match(CLOSEBRACE)) {
+        unsigned endColumn = tokenColumn();
+        return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, strictMode());
+    }
     DepthManager statementDepth(&m_statementDepth);
     m_statementDepth = 0;
     typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get());
     failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder), "Cannot parse body of this function");
-    return context.createFunctionBody(startLocation, tokenLocation(), startColumn, strictMode());
+    unsigned endColumn = tokenColumn();
+    return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, strictMode());
 }
 
 static const char* stringForFunctionMode(FunctionParseMode mode)
@@ -1190,7 +1193,7 @@ template <FunctionRequirements requirements, FunctionParseMode mode, bool nameIs
 {
     AutoPopScopeRef functionScope(this, pushScope());
     functionScope->setIsFunction();
-    int functionStart = m_token.m_location.startOffset;
+    int functionNameStart = m_token.m_location.startOffset;
     const Identifier* lastFunctionName = m_lastFunctionName;
     m_lastFunctionName = nullptr;
     if (match(IDENT)) {
@@ -1231,16 +1234,21 @@ template <FunctionRequirements requirements, FunctionParseMode mode, bool nameIs
         endLocation.line = cachedInfo->closeBraceLine;
         endLocation.startOffset = cachedInfo->closeBraceOffset;
         endLocation.lineStartOffset = cachedInfo->closeBraceLineStartOffset;
+
+        bool endColumnIsOnStartLine = (endLocation.line == bodyStartLine);
         ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
+        unsigned bodyEndColumn = endColumnIsOnStartLine ?
+            endLocation.startOffset - m_token.m_data.lineStartOffset :
+            endLocation.startOffset - endLocation.lineStartOffset;
 
-        body = context.createFunctionBody(startLocation, endLocation, bodyStartColumn, cachedInfo->strictMode);
+        body = context.createFunctionBody(startLocation, endLocation, bodyStartColumn, bodyEndColumn, cachedInfo->strictMode);
         
         functionScope->restoreFromSourceProviderCache(cachedInfo);
         failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
         
         closeBraceOffset = cachedInfo->closeBraceOffset;
 
-        context.setFunctionStart(body, functionStart);
+        context.setFunctionNameStart(body, functionNameStart);
         m_token = cachedInfo->closeBraceToken();
 
         m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
@@ -1270,7 +1278,7 @@ template <FunctionRequirements requirements, FunctionParseMode mode, bool nameIs
     int functionLength = closeBraceOffset - openBraceOffset;
     if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
         SourceProviderCacheItemCreationParameters parameters;
-        parameters.functionStart = functionStart;
+        parameters.functionNameStart = functionNameStart;
         parameters.closeBraceLine = closeBraceLine;
         parameters.closeBraceOffset = closeBraceOffset;
         parameters.closeBraceLineStartOffset = closeBraceLineStartOffset;
@@ -1278,7 +1286,7 @@ template <FunctionRequirements requirements, FunctionParseMode mode, bool nameIs
         newInfo = SourceProviderCacheItem::create(parameters);
 
     }
-    context.setFunctionStart(body, functionStart);
+    context.setFunctionNameStart(body, functionNameStart);
     
     failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
     matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
index 00c4de8054d86982467ac7c49aa60cf38821202d..4a5ad858954e7ec1f7f75c72054f37bfb02d9bcf 100644 (file)
@@ -414,6 +414,8 @@ public:
     template <class ParsedNode>
     PassRefPtr<ParsedNode> parse(ParserError&);
 
+    JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); }
+
 private:
     struct AllowInOverride {
         AllowInOverride(Parser* parser)
@@ -881,7 +883,8 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error)
     errMsg = String();
 
     JSTokenLocation startLocation(tokenLocation());
-    unsigned startColumn = m_source->startColumn();
+    ASSERT(m_source->startColumn() > 0);
+    unsigned startColumn = m_source->startColumn() - 1;
 
     String parseError = parseInner();
 
@@ -900,13 +903,15 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error)
     RefPtr<ParsedNode> result;
     if (m_sourceElements) {
         JSTokenLocation endLocation;
-        endLocation.line = m_lexer->lastLineNumber();
+        endLocation.line = m_lexer->lineNumber();
         endLocation.lineStartOffset = m_lexer->currentLineStartOffset();
         endLocation.startOffset = m_lexer->currentOffset();
+        unsigned endColumn = endLocation.startOffset - endLocation.lineStartOffset;
         result = ParsedNode::create(m_vm,
                                     startLocation,
                                     endLocation,
                                     startColumn,
+                                    endColumn,
                                     m_sourceElements,
                                     m_varDeclarations ? &m_varDeclarations->data : 0,
                                     m_funcDeclarations ? &m_funcDeclarations->data : 0,
@@ -914,7 +919,7 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error)
                                     *m_source,
                                     m_features,
                                     m_numConstants);
-        result->setLoc(m_source->firstLine(), m_lastTokenEndPosition.line, m_lexer->currentOffset(), m_lexer->currentLineStartOffset());
+        result->setLoc(m_source->firstLine(), m_lexer->lineNumber(), m_lexer->currentOffset(), m_lexer->currentLineStartOffset());
     } else {
         // We can never see a syntax error when reparsing a function, since we should have
         // reported the error when parsing the containing program or eval code. So if we're
@@ -944,17 +949,23 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error)
 }
 
 template <class ParsedNode>
-PassRefPtr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ParserError& error)
+PassRefPtr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ParserError& error, JSTextPosition* positionBeforeLastNewline = 0)
 {
     SamplingRegion samplingRegion("Parsing");
 
     ASSERT(!source.provider()->source().isNull());
     if (source.provider()->source().is8Bit()) {
         Parser<Lexer<LChar>> parser(vm, source, parameters, name, strictness, parserMode);
-        return parser.parse<ParsedNode>(error);
+        RefPtr<ParsedNode> result = parser.parse<ParsedNode>(error);
+        if (positionBeforeLastNewline)
+            *positionBeforeLastNewline = parser.positionBeforeLastNewline();
+        return result.release();
     }
     Parser<Lexer<UChar>> parser(vm, source, parameters, name, strictness, parserMode);
-    return parser.parse<ParsedNode>(error);
+    RefPtr<ParsedNode> result = parser.parse<ParsedNode>(error);
+    if (positionBeforeLastNewline)
+        *positionBeforeLastNewline = parser.positionBeforeLastNewline();
+    return result.release();
 }
 
 } // namespace
index 0e95db672911fe1b22fcba3333cc547546eb5d6e..3962118610f6aa6a8f4905a90eb2daa4a0085eeb 100644 (file)
@@ -34,7 +34,7 @@
 namespace JSC {
 
 struct SourceProviderCacheItemCreationParameters {
-    unsigned functionStart;
+    unsigned functionNameStart;
     unsigned closeBraceLine;
     unsigned closeBraceOffset;
     unsigned closeBraceLineStartOffset;
@@ -70,7 +70,7 @@ public:
         return token;
     }
 
-    unsigned functionStart : 31;
+    unsigned functionNameStart : 31;
     bool needsFullActivation : 1;
     
     unsigned closeBraceLine : 31;
@@ -107,7 +107,7 @@ inline std::unique_ptr<SourceProviderCacheItem> SourceProviderCacheItem::create(
 }
 
 inline SourceProviderCacheItem::SourceProviderCacheItem(const SourceProviderCacheItemCreationParameters& parameters)
-    : functionStart(parameters.functionStart)
+    : functionNameStart(parameters.functionNameStart)
     , needsFullActivation(parameters.needsFullActivation)
     , closeBraceLine(parameters.closeBraceLine)
     , usesEval(parameters.usesEval)
index 2dab1e2dc954792d12d671a66afe70d8503656d2..254822bd3cc9bcb51ac2d24ffb0fe15bebf11dfe 100644 (file)
@@ -153,8 +153,8 @@ public:
     ExpressionType createConditionalExpr(const JSTokenLocation&, ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; }
     ExpressionType createAssignResolve(const JSTokenLocation&, const Identifier&, ExpressionType, int, int, int) { return AssignmentExpr; }
     ExpressionType createFunctionExpr(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int, int) { return FunctionExpr; }
-    int createFunctionBody(const JSTokenLocation&, const JSTokenLocation&, int, bool) { return 1; }
-    void setFunctionStart(int, int) { }
+    int createFunctionBody(const JSTokenLocation&, const JSTokenLocation&, int, int, bool) { return 1; }
+    void setFunctionNameStart(int, int) { }
     int createArguments() { return 1; }
     int createArguments(int) { return 1; }
     ExpressionType createSpreadExpression(const JSTokenLocation&, ExpressionType, int, int, int) { return 1; }
index 02694244f12753293c076af44c737884fd754c49..510e383fae575aada8176c0441ee725b43a4c732 100644 (file)
@@ -75,17 +75,20 @@ template <> struct CacheTypes<UnlinkedEvalCodeBlock> {
 };
 
 template <class UnlinkedCodeBlockType, class ExecutableType>
-UnlinkedCodeBlockType* CodeCache::getCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+UnlinkedCodeBlockType* CodeCache::getGlobalCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
 {
     SourceCodeKey key = SourceCodeKey(source, String(), CacheTypes<UnlinkedCodeBlockType>::codeType, strictness);
     CodeCacheMap::AddResult addResult = m_sourceCode.add(key, SourceCodeValue());
     bool canCache = debuggerMode == DebuggerOff && profilerMode == ProfilerOff;
     if (!addResult.isNewEntry && canCache) {
-        UnlinkedCodeBlockType* unlinkedCode = jsCast<UnlinkedCodeBlockType*>(addResult.iterator->value.cell.get());
-        unsigned firstLine = source.firstLine() + unlinkedCode->firstLine();
-        unsigned startColumn = source.firstLine() ? source.startColumn() : 0;
-        executable->recordParse(unlinkedCode->codeFeatures(), unlinkedCode->hasCapturedVariables(), firstLine, firstLine + unlinkedCode->lineCount(), startColumn);
-        return unlinkedCode;
+        UnlinkedCodeBlockType* unlinkedCodeBlock = jsCast<UnlinkedCodeBlockType*>(addResult.iterator->value.cell.get());
+        unsigned firstLine = source.firstLine() + unlinkedCodeBlock->firstLine();
+        unsigned lineCount = unlinkedCodeBlock->lineCount();
+        unsigned startColumn = unlinkedCodeBlock->startColumn() + source.startColumn();
+        bool endColumnIsOnStartLine = !lineCount;
+        unsigned endColumn = unlinkedCodeBlock->endColumn() + (endColumnIsOnStartLine ? startColumn : 1);
+        executable->recordParse(unlinkedCodeBlock->codeFeatures(), unlinkedCodeBlock->hasCapturedVariables(), firstLine, firstLine + lineCount, startColumn, endColumn);
+        return unlinkedCodeBlock;
     }
 
     typedef typename CacheTypes<UnlinkedCodeBlockType>::RootNode RootNode;
@@ -94,11 +97,17 @@ UnlinkedCodeBlockType* CodeCache::getCodeBlock(VM& vm, ExecutableType* executabl
         m_sourceCode.remove(addResult.iterator);
         return 0;
     }
-    executable->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo(), rootNode->lastLine(), rootNode->startColumn());
+    unsigned lineCount = rootNode->lastLine() - rootNode->lineNo();
+    unsigned startColumn = rootNode->startColumn() + 1;
+    bool endColumnIsOnStartLine = !lineCount;
+    unsigned unlinkedEndColumn = rootNode->endColumn();
+    unsigned endColumn = unlinkedEndColumn + (endColumnIsOnStartLine ? startColumn : 1);
+    executable->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo(), rootNode->lastLine(), startColumn, endColumn);
 
-    UnlinkedCodeBlockType* unlinkedCode = UnlinkedCodeBlockType::create(&vm, executable->executableInfo());
-    unlinkedCode->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo() - source.firstLine(), rootNode->lastLine() - rootNode->lineNo());
-    OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(vm, rootNode.get(), unlinkedCode, debuggerMode, profilerMode)));
+    UnlinkedCodeBlockType* unlinkedCodeBlock = UnlinkedCodeBlockType::create(&vm, executable->executableInfo());
+    unlinkedCodeBlock->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo() - source.firstLine(), lineCount, unlinkedEndColumn);
+
+    OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(vm, rootNode.get(), unlinkedCodeBlock, debuggerMode, profilerMode)));
     error = generator->generate();
     rootNode->destroyData();
     if (error.m_type != ParserError::ErrorNone) {
@@ -108,21 +117,21 @@ UnlinkedCodeBlockType* CodeCache::getCodeBlock(VM& vm, ExecutableType* executabl
 
     if (!canCache) {
         m_sourceCode.remove(addResult.iterator);
-        return unlinkedCode;
+        return unlinkedCodeBlock;
     }
 
-    addResult.iterator->value = SourceCodeValue(vm, unlinkedCode, m_sourceCode.age());
-    return unlinkedCode;
+    addResult.iterator->value = SourceCodeValue(vm, unlinkedCodeBlock, m_sourceCode.age());
+    return unlinkedCodeBlock;
 }
 
 UnlinkedProgramCodeBlock* CodeCache::getProgramCodeBlock(VM& vm, ProgramExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
 {
-    return getCodeBlock<UnlinkedProgramCodeBlock>(vm, executable, source, strictness, debuggerMode, profilerMode, error);
+    return getGlobalCodeBlock<UnlinkedProgramCodeBlock>(vm, executable, source, strictness, debuggerMode, profilerMode, error);
 }
 
 UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(VM& vm, EvalExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
 {
-    return getCodeBlock<UnlinkedEvalCodeBlock>(vm, executable, source, strictness, debuggerMode, profilerMode, error);
+    return getGlobalCodeBlock<UnlinkedEvalCodeBlock>(vm, executable, source, strictness, debuggerMode, profilerMode, error);
 }
 
 UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(VM& vm, const Identifier& name, const SourceCode& source, ParserError& error)
@@ -132,7 +141,8 @@ UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(VM& v
     if (!addResult.isNewEntry)
         return jsCast<UnlinkedFunctionExecutable*>(addResult.iterator->value.cell.get());
 
-    RefPtr<ProgramNode> program = parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error);
+    JSTextPosition positionBeforeLastNewline;
+    RefPtr<ProgramNode> program = parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error, &positionBeforeLastNewline);
     if (!program) {
         ASSERT(error.m_type != ParserError::ErrorNone);
         m_sourceCode.remove(addResult.iterator);
@@ -147,10 +157,11 @@ UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(VM& v
     ASSERT(funcExpr);
     RELEASE_ASSERT(funcExpr->isFuncExprNode());
     FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
+    body->setEndPosition(positionBeforeLastNewline);
     ASSERT(body);
     ASSERT(body->ident().isNull());
 
-    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, body);
+    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, body, true);
     functionExecutable->m_nameValue.set(vm, functionExecutable, jsString(&vm, name.string()));
 
     addResult.iterator->value = SourceCodeValue(vm, functionExecutable, m_sourceCode.age());
index 6dbcc57e87f8b298eb7b1499fc9d352a182f3345..1628e5e8b20dafcf039bf8f794b80e39a5f52f19 100644 (file)
@@ -253,7 +253,7 @@ private:
     CodeCache();
 
     template <class UnlinkedCodeBlockType, class ExecutableType> 
-    UnlinkedCodeBlockType* getCodeBlock(VM&, ExecutableType*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
+    UnlinkedCodeBlockType* getGlobalCodeBlock(VM&, ExecutableType*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
 
     CodeCacheMap m_sourceCode;
 };
index 003dd43e9512ed3c85947beadb6bc9994527c51d..120d42bab57d26354ca23a6db3a73782175c787a 100644 (file)
@@ -180,7 +180,9 @@ PassRefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
     VM* vm = scope->vm();
 
     ASSERT(vm->heap.isDeferred());
-    
+    ASSERT(startColumn() != UINT_MAX);
+    ASSERT(endColumn() != UINT_MAX);
+
     if (classInfo() == EvalExecutable::info()) {
         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
         RELEASE_ASSERT(kind == CodeForCall);
@@ -209,7 +211,7 @@ PassRefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
     UnlinkedFunctionCodeBlock* unlinkedCodeBlock =
         executable->m_unlinkedExecutable->codeBlockFor(
             *vm, executable->m_source, kind, debuggerMode, profilerMode, error);
-    recordParse(executable->m_unlinkedExecutable->features(), executable->m_unlinkedExecutable->hasCapturedVariables(), lineNo(), lastLine(), startColumn()); 
+    recordParse(executable->m_unlinkedExecutable->features(), executable->m_unlinkedExecutable->hasCapturedVariables(), lineNo(), lastLine(), startColumn(), endColumn()); 
     if (!unlinkedCodeBlock) {
         exception = vm->throwException(
             globalObject->globalExec(),
@@ -362,15 +364,19 @@ void ProgramExecutable::destroy(JSCell* cell)
 
 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
 
-FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
+FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces)
     : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext())
     , m_unlinkedExecutable(vm, this, unlinkedExecutable)
+    , m_bodyIncludesBraces(bodyIncludesBraces)
 {
     RELEASE_ASSERT(!source.isNull());
     ASSERT(source.length());
     m_firstLine = firstLine;
     m_lastLine = lastLine;
+    ASSERT(startColumn != UINT_MAX);
+    ASSERT(endColumn != UINT_MAX);
     m_startColumn = startColumn;
+    m_endColumn = endColumn;
 }
 
 void FunctionExecutable::destroy(JSCell* cell)
@@ -454,16 +460,16 @@ JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callF
     ASSERT(&globalObject->vm() == &vm);
 
     JSObject* exception = 0;
-    UnlinkedProgramCodeBlock* unlinkedCode = globalObject->createProgramCodeBlock(callFrame, this, &exception);
+    UnlinkedProgramCodeBlock* unlinkedCodeBlock = globalObject->createProgramCodeBlock(callFrame, this, &exception);
     if (exception)
         return exception;
 
-    m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCode);
+    m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCodeBlock);
 
     BatchedTransitionOptimizer optimizer(vm, globalObject);
 
-    const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCode->variableDeclarations();
-    const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCode->functionDeclarations();
+    const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCodeBlock->variableDeclarations();
+    const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCodeBlock->functionDeclarations();
 
     for (size_t i = 0; i < functionDeclarations.size(); ++i) {
         UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
@@ -564,15 +570,27 @@ void FunctionExecutable::unlinkCalls()
 
 FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
 {
-    UnlinkedFunctionExecutable* unlinkedFunction = UnlinkedFunctionExecutable::fromGlobalCode(name, exec, debugger, source, exception);
-    if (!unlinkedFunction)
+    UnlinkedFunctionExecutable* unlinkedExecutable = UnlinkedFunctionExecutable::fromGlobalCode(name, exec, debugger, source, exception);
+    if (!unlinkedExecutable)
         return 0;
-    unsigned firstLine = source.firstLine() + unlinkedFunction->firstLineOffset();
-    unsigned startOffset = source.startOffset() + unlinkedFunction->startOffset();
-    unsigned startColumn = source.startColumn();
-    unsigned sourceLength = unlinkedFunction->sourceLength();
-    SourceCode functionSource(source.provider(), startOffset, startOffset + sourceLength, firstLine, startColumn);
-    return FunctionExecutable::create(exec->vm(), functionSource, unlinkedFunction, firstLine, unlinkedFunction->lineCount(), startColumn);
+    unsigned lineCount = unlinkedExecutable->lineCount();
+    unsigned firstLine = source.firstLine() + unlinkedExecutable->firstLineOffset();
+    unsigned startOffset = source.startOffset() + unlinkedExecutable->startOffset();
+
+    // We don't have any owner executable. The source string is effectively like a global
+    // string (like in the handling of eval). Hence, the startColumn is always 1.
+    unsigned startColumn = 1;
+    unsigned sourceLength = unlinkedExecutable->sourceLength();
+    bool endColumnIsOnStartLine = !lineCount;
+    // The unlinkedBodyEndColumn is based-0. Hence, we need to add 1 to it. But if the
+    // endColumn is on the startLine, then we need to subtract back the adjustment for
+    // the open brace resulting in an adjustment of 0.
+    unsigned endColumnExcludingBraces = unlinkedExecutable->unlinkedBodyEndColumn() + (endColumnIsOnStartLine ? 0 : 1);
+    unsigned startOffsetExcludingOpenBrace = startOffset + 1;
+    unsigned endOffsetExcludingCloseBrace = startOffset + sourceLength - 1;
+    SourceCode bodySource(source.provider(), startOffsetExcludingOpenBrace, endOffsetExcludingCloseBrace, firstLine, startColumn);
+
+    return FunctionExecutable::create(exec->vm(), bodySource, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn, endColumnExcludingBraces, false);
 }
 
 String FunctionExecutable::paramString() const
index 49a5e19f8305c3bb2e29818337a4ef25618d7bd3..d2347a289df189577312534d62e3999db82ac7bf 100644 (file)
@@ -93,10 +93,18 @@ public:
         
     CodeBlockHash hashFor(CodeSpecializationKind) const;
 
+    bool isEvalExecutable()
+    {
+        return structure()->typeInfo().type() == EvalExecutableType;
+    }
     bool isFunctionExecutable()
     {
         return structure()->typeInfo().type() == FunctionExecutableType;
     }
+    bool isProgramExecutable()
+    {
+        return structure()->typeInfo().type() == ProgramExecutableType;
+    }
 
     bool isHostFunction() const
     {
@@ -355,6 +363,8 @@ public:
         , m_source(source)
         , m_features(isInStrictContext ? StrictModeFeature : 0)
         , m_neverInline(false)
+        , m_startColumn(UINT_MAX)
+        , m_endColumn(UINT_MAX)
     {
     }
 
@@ -363,6 +373,8 @@ public:
         , m_source(source)
         , m_features(isInStrictContext ? StrictModeFeature : 0)
         , m_neverInline(false)
+        , m_startColumn(UINT_MAX)
+        , m_endColumn(UINT_MAX)
     {
     }
 
@@ -378,6 +390,7 @@ public:
     int lineNo() const { return m_firstLine; }
     int lastLine() const { return m_lastLine; }
     unsigned startColumn() const { return m_startColumn; }
+    unsigned endColumn() const { return m_endColumn; }
 
     bool usesEval() const { return m_features & EvalFeature; }
     bool usesArguments() const { return m_features & ArgumentsFeature; }
@@ -395,13 +408,16 @@ public:
         
     DECLARE_INFO;
 
-    void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn)
+    void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn, unsigned endColumn)
     {
         m_features = features;
         m_hasCapturedVariables = hasCapturedVariables;
         m_firstLine = firstLine;
         m_lastLine = lastLine;
+        ASSERT(startColumn != UINT_MAX);
         m_startColumn = startColumn;
+        ASSERT(endColumn != UINT_MAX);
+        m_endColumn = endColumn;
     }
 
     void installCode(CodeBlock*);
@@ -437,6 +453,7 @@ protected:
     int m_firstLine;
     int m_lastLine;
     unsigned m_startColumn;
+    unsigned m_endColumn;
 };
 
 class EvalExecutable : public ScriptExecutable {
@@ -549,9 +566,9 @@ class FunctionExecutable : public ScriptExecutable {
 public:
     typedef ScriptExecutable Base;
 
-    static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
+    static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces = true)
     {
-        FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn);
+        FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn, bodyIncludesBraces);
         executable->finishCreation(vm);
         return executable;
     }
@@ -638,8 +655,10 @@ public:
 
     void clearCode();
 
+    bool bodyIncludesBraces() const { return m_bodyIncludesBraces; }
+
 private:
-    FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn);
+    FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces);
 
     bool isCompiling()
     {
@@ -658,6 +677,7 @@ private:
     WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
     RefPtr<FunctionCodeBlock> m_codeBlockForCall;
     RefPtr<FunctionCodeBlock> m_codeBlockForConstruct;
+    bool m_bodyIncludesBraces;
 };
 
 inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
index ab8411b9803b407a6f564c9222ed2f77c36311bf..87c3ab6e96087cd6149e66ab7bc4344a6590b9a4 100644 (file)
@@ -93,9 +93,9 @@ JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState* exec, JSGlobalObj
     // We also need \n before the closing } to handle // comments at the end of the last line
     String program;
     if (args.isEmpty())
-        program = ASCIILiteral("(function() { \n})");
+        program = ASCIILiteral("(function() {\n})");
     else if (args.size() == 1)
-        program = makeString("(function() { ", args.at(0).toString(exec)->value(exec), "\n})");
+        program = makeString("(function() {", args.at(0).toString(exec)->value(exec), "\n})");
     else {
         StringBuilder builder;
         builder.appendLiteral("(function(");
@@ -104,7 +104,7 @@ JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState* exec, JSGlobalObj
             builder.append(',');
             builder.append(args.at(i).toString(exec)->value(exec));
         }
-        builder.appendLiteral(") { ");
+        builder.appendLiteral(") {");
         builder.append(args.at(args.size() - 1).toString(exec)->value(exec));
         builder.appendLiteral("\n})");
         program = builder.toString();
index 2eb2a5cc9e4dbf4796a0daefe8d4e27bc4d92189..c1b08af2d818dae57e1b00fda173a816137529b5 100644 (file)
@@ -85,8 +85,11 @@ CallType FunctionPrototype::getCallData(JSCell*, CallData& callData)
 // Functions
 
 // Compatibility hack for the Optimost JavaScript library. (See <rdar://problem/6595040>.)
-static inline void insertSemicolonIfNeeded(String& functionBody)
+static inline void insertSemicolonIfNeeded(String& functionBody, bool bodyIncludesBraces)
 {
+    if (!bodyIncludesBraces)
+        functionBody = makeString("{ ", functionBody, "}");
+
     ASSERT(functionBody[0] == '{');
     ASSERT(functionBody[functionBody.length() - 1] == '}');
 
@@ -109,7 +112,7 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
             return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n    [native code]\n}"));
         FunctionExecutable* executable = function->jsExecutable();
         String sourceString = executable->source().toString();
-        insertSemicolonIfNeeded(sourceString);
+        insertSemicolonIfNeeded(sourceString, executable->bodyIncludesBraces());
         return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "(", executable->paramString(), ") ", sourceString));
     }
 
index 83ff61e5ebc704d6258e9be587f1199d789b9522..2f996d87902a68e0d2c4dd57769b7916b405921d 100644 (file)
@@ -738,7 +738,7 @@ UnlinkedProgramCodeBlock* JSGlobalObject::createProgramCodeBlock(CallFrame* call
     JSParserStrictness strictness = executable->isStrictMode() ? JSParseStrict : JSParseNormal;
     DebuggerMode debuggerMode = hasDebugger() ? DebuggerOn : DebuggerOff;
     ProfilerMode profilerMode = hasProfiler() ? ProfilerOn : ProfilerOff;
-    UnlinkedProgramCodeBlock* unlinkedCode = vm().codeCache()->getProgramCodeBlock(vm(), executable, executable->source(), strictness, debuggerMode, profilerMode, error);
+    UnlinkedProgramCodeBlock* unlinkedCodeBlock = vm().codeCache()->getProgramCodeBlock(vm(), executable, executable->source(), strictness, debuggerMode, profilerMode, error);
 
     if (hasDebugger())
         debugger()->sourceParsed(callFrame, executable->source().provider(), error.m_line, error.m_message);
@@ -748,7 +748,7 @@ UnlinkedProgramCodeBlock* JSGlobalObject::createProgramCodeBlock(CallFrame* call
         return 0;
     }
     
-    return unlinkedCode;
+    return unlinkedCodeBlock;
 }
 
 UnlinkedEvalCodeBlock* JSGlobalObject::createEvalCodeBlock(CallFrame* callFrame, EvalExecutable* executable)
@@ -757,7 +757,7 @@ UnlinkedEvalCodeBlock* JSGlobalObject::createEvalCodeBlock(CallFrame* callFrame,
     JSParserStrictness strictness = executable->isStrictMode() ? JSParseStrict : JSParseNormal;
     DebuggerMode debuggerMode = hasDebugger() ? DebuggerOn : DebuggerOff;
     ProfilerMode profilerMode = hasProfiler() ? ProfilerOn : ProfilerOff;
-    UnlinkedEvalCodeBlock* unlinkedCode = vm().codeCache()->getEvalCodeBlock(vm(), executable, executable->source(), strictness, debuggerMode, profilerMode, error);
+    UnlinkedEvalCodeBlock* unlinkedCodeBlock = vm().codeCache()->getEvalCodeBlock(vm(), executable, executable->source(), strictness, debuggerMode, profilerMode, error);
 
     if (hasDebugger())
         debugger()->sourceParsed(callFrame, executable->source().provider(), error.m_line, error.m_message);
@@ -767,7 +767,7 @@ UnlinkedEvalCodeBlock* JSGlobalObject::createEvalCodeBlock(CallFrame* callFrame,
         return 0;
     }
 
-    return unlinkedCode;
+    return unlinkedCodeBlock;
 }
 
 } // namespace JSC
index cf53eb17f2fd97c8fd0a38bff62cd54a406df4cc..799acb9d9650a01f06564c58ad76955a0691e76b 100644 (file)
@@ -1,3 +1,23 @@
+2013-11-19  Mark Lam  <mark.lam@apple.com>
+
+        Add tracking of endColumn for Executables.
+        https://bugs.webkit.org/show_bug.cgi?id=124245.
+
+        Reviewed by Geoffrey Garen.
+
+        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:
+
 2013-11-15  Jer Noble  <jer.noble@apple.com>
 
         [MSE] Support fastSeek() in MediaSource.
diff --git a/Source/WebCore/ForwardingHeaders/bytecode/CodeBlock.h b/Source/WebCore/ForwardingHeaders/bytecode/CodeBlock.h
new file mode 100644 (file)
index 0000000..4abfc57
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef WebCore_FWD_CodeBlock_h
+#define WebCore_FWD_CodeBlock_h
+#include <JavaScriptCore/CodeBlock.h>
+#endif
index 6fa0beb620a9aac93ad7bde55fa4c38e4a1bddcf..5caa42661b74268f7eb3ef2879eb51b13fbaf160 100644 (file)
@@ -824,6 +824,7 @@ __ZN7WebCore22HTMLPlugInImageElement24restartSnapshottedPlugInEv
 __ZN7WebCore22HTMLPlugInImageElement29setIsPrimarySnapshottedPlugInEb
 __ZN7WebCore22RuntimeEnabledFeatures14sharedFeaturesEv
 __ZN7WebCore22ScriptExecutionContext26canSuspendActiveDOMObjectsEv
+__ZN7WebCore22ScriptExecutionContext2vmEv
 __ZN7WebCore22StorageEventDispatcher34dispatchLocalStorageEventsToFramesERNS_9PageGroupERKN3WTF6VectorINS3_6RefPtrINS_5FrameEEELm0ENS3_15CrashOnOverflowEEERKNS3_6StringESE_SE_SE_PNS_14SecurityOriginE
 __ZN7WebCore22URLWithUserTypedStringEP8NSStringP5NSURL
 __ZN7WebCore22counterValueForElementEPNS_7ElementE
index 40487fc94029a78822b86e82ead5080cc4a74332..855fe517f0ba279bbd4bc700b49ea61b64560276 100644 (file)
@@ -95,6 +95,8 @@
 #include "TypeConversions.h"
 #include "ViewportArguments.h"
 #include "WorkerThread.h"
+#include <bytecode/CodeBlock.h>
+#include <runtime/JSCJSValue.h>
 #include <wtf/text/CString.h>
 #include <wtf/text/StringBuffer.h>
 
 #include "MockMediaPlayerMediaSource.h"
 #endif
 
+using JSC::CodeBlock;
+using JSC::FunctionExecutable;
+using JSC::JSFunction;
+using JSC::JSValue;
+using JSC::ScriptExecutable;
+using JSC::StackVisitor;
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -1252,6 +1261,82 @@ void Internals::emitInspectorDidCancelFrame()
 #endif
 }
 
+class GetCallerCodeBlockFunctor {
+public:
+    GetCallerCodeBlockFunctor()
+        : m_iterations(0)
+        , m_codeBlock(0)
+    {
+    }
+
+    StackVisitor::Status operator()(StackVisitor& visitor)
+    {
+        ++m_iterations;
+        if (m_iterations < 2)
+            return StackVisitor::Continue;
+
+        m_codeBlock = visitor->codeBlock();
+        return StackVisitor::Done;
+    }
+
+    CodeBlock* codeBlock() const { return m_codeBlock; }
+
+private:
+    int m_iterations;
+    CodeBlock* m_codeBlock;
+};
+
+String Internals::parserMetaData(ScriptValue value)
+{
+    JSC::VM* vm = contextDocument()->vm();
+    JSC::ExecState* exec = vm->topCallFrame;
+    JSC::JSValue code = value.jsValue();
+    ScriptExecutable* executable;
+
+    if (!code || code.isNull() || code.isUndefined()) {
+        GetCallerCodeBlockFunctor iter;
+        exec->iterate(iter);
+        CodeBlock* codeBlock = iter.codeBlock();
+        executable = codeBlock->ownerExecutable(); 
+    } else if (code.isFunction()) {
+        JSFunction* funcObj = JSC::jsCast<JSFunction*>(code.toObject(exec));
+        executable = funcObj->jsExecutable();
+    } else
+        return String();
+
+    unsigned startLine = executable->lineNo();
+    unsigned startColumn = executable->startColumn();
+    unsigned endLine = executable->lastLine();
+    unsigned endColumn = executable->endColumn();
+
+    StringBuilder result;
+
+    if (executable->isFunctionExecutable()) {
+        FunctionExecutable* funcExecutable = reinterpret_cast<FunctionExecutable*>(executable);
+        String inferredName = funcExecutable->inferredName().string();
+        result.append("function \"");
+        result.append(inferredName);
+        result.append("\"");
+    } else if (executable->isEvalExecutable())
+        result.append("eval");
+    else {
+        ASSERT(executable->isProgramExecutable());
+        result.append("program");
+    }
+
+    result.append(" { ");
+    result.appendNumber(startLine);
+    result.append(":");
+    result.appendNumber(startColumn);
+    result.append(" - ");
+    result.appendNumber(endLine);
+    result.append(":");
+    result.appendNumber(endColumn);
+    result.append(" }");
+
+    return result.toString();
+}
+
 void Internals::setBatteryStatus(const String& eventType, bool charging, double chargingTime, double dischargingTime, double level, ExceptionCode& ec)
 {
     Document* document = contextDocument();
index b81f5f58bc5ea731411756ffe786f43e2ccad43f..25bcafe0a4dbd3f88ee85bfb6092e67ff456eee5 100644 (file)
@@ -31,6 +31,7 @@
 #include "ContextDestructionObserver.h"
 #include "ExceptionCodePlaceholder.h"
 #include "NodeList.h"
+#include "ScriptValue.h"
 #include <runtime/ArrayBuffer.h>
 #include <runtime/Float32Array.h>
 #include <wtf/PassRefPtr.h>
@@ -180,6 +181,8 @@ public:
     void emitInspectorDidBeginFrame();
     void emitInspectorDidCancelFrame();
 
+    String parserMetaData(ScriptValue = ScriptValue());
+
     bool hasSpellingMarker(int from, int length, ExceptionCode&);
     bool hasGrammarMarker(int from, int length, ExceptionCode&);
     bool hasAutocorrectedMarker(int from, int length, ExceptionCode&);
index f1841d69bcf1d8ce2e73d90f09e5046cdcdb2a55..047a505f685d64f0e0f400d8fb94d770d6b9c496 100644 (file)
     void emitInspectorDidBeginFrame();
     void emitInspectorDidCancelFrame();
 
+    // Calling parserMetaData() with no arguments gets the metadata for the script of the current scope.
+    DOMString parserMetaData(optional any func);
+
     [RaisesException] boolean hasSpellingMarker(long from, long length);
     [RaisesException] boolean hasGrammarMarker(long from, long length);
     [RaisesException] boolean hasAutocorrectedMarker(long from, long length);
index f488c2bf2b89e3ff9df8cc2c6e248fa5d8dfff42..619801b9130363756753e70861a0668c97b8f238 100644 (file)
@@ -1,3 +1,15 @@
+2013-11-19  Mark Lam  <mark.lam@apple.com>
+
+        Add tracking of endColumn for Executables.
+        https://bugs.webkit.org/show_bug.cgi?id=124245.
+
+        Reviewed by Geoffrey Garen.
+
+        * 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.
+
 2013-11-18  Mark Rowe  <mrowe@apple.com>
 
         Use hw.activecpu for determining how many processes to spawn.
index 4d28b87f9e37c0d42f3a118cd9d3b0286d7cd685..187001a827741dffdd39d763b67948ea59c81bd3 100644 (file)
@@ -462,3 +462,4 @@ EXPORTS
         symbolWithPointer(?storeUpdatedQuotaForOrigin@ApplicationCacheStorage@WebCore@@QAE_NPBVSecurityOrigin@2@_J@Z, ?storeUpdatedQuotaForOrigin@ApplicationCacheStorage@WebCore@@QEAA_NPEBVSecurityOrigin@2@_J@Z)
         symbolWithPointer(?cacheStorage@WebCore@@YAAAVApplicationCacheStorage@1@XZ, ?cacheStorage@WebCore@@YAAEAVApplicationCacheStorage@1@XZ)
         symbolWithPointer(?setDefaultOriginQuota@ApplicationCacheStorage@WebCore@@QAEX_J@Z, ?setDefaultOriginQuota@ApplicationCacheStorage@WebCore@@QEAAX_J@Z)
+        symbolWithPointer(?vm@ScriptExecutionContext@WebCore@@QAEPAVVM@JSC@@XZ, ?vm@ScriptExecutionContext@WebCore@@QAEPAVVM@JSC@@XZ)
\ No newline at end of file