Skip to content

Commit 9354f97

Browse files
committed
Basic tests and inline source maps when native source maps are enabled
- Added check to not patch `Error.prepareStackTrace` if it has already been patched by another library. - Always attach inline source maps if `--enable-source-map` is set. - Added some basic tests for stack trace.
1 parent bebcec0 commit 9354f97

File tree

11 files changed

+137
-20
lines changed

11 files changed

+137
-20
lines changed

docs/v2/browser-compiler-legacy/coffeescript.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/v2/browser-compiler-modern/coffeescript.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/v2/index.html

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5364,27 +5364,27 @@ <h3>Bound generator functions</h3>
53645364
<h3>Classes are compiled to ES2015 classes</h3>
53655365
<p>ES2015 classes and their methods have some restrictions beyond those on regular functions.</p>
53665366
<p>Class constructors can’t be invoked without <code>new</code>:</p>
5367-
<blockquote class="uneditable-code-block"><pre><code class="language-coffee">(<span class="keyword">class</span>)()
5367+
<blockquote class="uneditable-code-block"><pre><code class="language-coffee">(<span class="class"><span class="keyword">class</span>)()</span>
53685368
<span class="comment"># Throws a TypeError at runtime</span>
53695369
</code></pre>
53705370
</blockquote><p>ES2015 classes don’t allow bound (fat arrow) methods. The CoffeeScript compiler goes through some contortions to preserve support for them, but one thing that can’t be accommodated is calling a bound method before it is bound:</p>
5371-
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="keyword">class</span> <span class="title class_">Base</span>
5371+
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="class"><span class="keyword">class</span> <span class="title">Base</span></span>
53725372
constructor: <span class="function">-&gt;</span>
53735373
@onClick() <span class="comment"># This works</span>
53745374
clickHandler = @onClick
53755375
clickHandler() <span class="comment"># This throws a runtime error</span>
53765376

5377-
<span class="keyword">class</span> <span class="title class_">Component</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Base</span>
5377+
<span class="class"><span class="keyword">class</span> <span class="title">Component</span> <span class="keyword">extends</span> <span class="title">Base</span></span>
53785378
onClick: <span class="function">=&gt;</span>
53795379
console.log <span class="string">&#x27;Clicked!&#x27;</span>, @
53805380
</code></pre>
53815381
</blockquote><p>Class methods can’t be used with <code>new</code> (uncommon):</p>
5382-
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="keyword">class</span> <span class="title class_">Namespace</span>
5382+
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="class"><span class="keyword">class</span> <span class="title">Namespace</span></span>
53835383
@Klass = <span class="function">-&gt;</span>
53845384
<span class="keyword">new</span> Namespace.Klass <span class="comment"># Throws a TypeError at runtime</span>
53855385
</code></pre>
53865386
</blockquote><p>Due to the hoisting required to compile to ES2015 classes, dynamic keys in class methods can’t use values from the executable class body unless the methods are assigned in prototype style.</p>
5387-
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="keyword">class</span> <span class="title class_">A</span>
5387+
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span>
53885388
name = <span class="string">&#x27;method&#x27;</span>
53895389
<span class="string">&quot;<span class="subst">#{name}</span>&quot;</span>: <span class="function">-&gt;</span> <span class="comment"># This method will be named &#x27;undefined&#x27;</span>
53905390
@::[name] = <span class="function">-&gt;</span> <span class="comment"># This will work; assigns to `A.prototype.method`</span>
@@ -5394,11 +5394,11 @@ <h3>Classes are compiled to ES2015 classes</h3>
53945394
<section id="breaking-changes-super-this">
53955395
<h3><code>super</code> and <code>this</code></h3>
53965396
<p>In the constructor of a derived class (a class that <code>extends</code> another class), <code>this</code> cannot be used before calling <code>super</code>:</p>
5397-
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="keyword">class</span> <span class="title class_">B</span> <span class="keyword">extends</span> <span class="title class_ inherited__">A</span>
5397+
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span></span>
53985398
constructor: <span class="function">-&gt;</span> this <span class="comment"># Throws a compiler error</span>
53995399
</code></pre>
54005400
</blockquote><p>This also means you cannot pass a reference to <code>this</code> as an argument to <code>super</code> in the constructor of a derived class:</p>
5401-
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="keyword">class</span> <span class="title class_">B</span> <span class="keyword">extends</span> <span class="title class_ inherited__">A</span>
5401+
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span></span>
54025402
constructor: <span class="function"><span class="params">(@arg)</span> -&gt;</span>
54035403
super @arg <span class="comment"># Throws a compiler error</span>
54045404
</code></pre>
@@ -5447,7 +5447,7 @@ <h3><code>super</code> and <code>this</code></h3>
54475447
<section id="breaking-changes-super-extends">
54485448
<h3><code>super</code> and <code>extends</code></h3>
54495449
<p>Due to a syntax clash with <code>super</code> with accessors, “bare” <code>super</code> (the keyword <code>super</code> without parentheses) no longer compiles to a super call forwarding all arguments.</p>
5450-
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="keyword">class</span> <span class="title class_">B</span> <span class="keyword">extends</span> <span class="title class_ inherited__">A</span>
5450+
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span></span>
54515451
foo: <span class="function">-&gt;</span> super
54525452
<span class="comment"># Throws a compiler error</span>
54535453
</code></pre>
@@ -5704,7 +5704,7 @@ <h3>Argument parsing and shebang (<code>#!</code>) lines</h3>
57045704
console.log x
57055705
</code></pre>
57065706
</blockquote><p>If this were saved as <code>executable.coffee</code>, it could be made executable and run:</p>
5707-
<blockquote class="uneditable-code-block"><pre><code class="language-bash"><span class="built_in">chmod</span> +x ./executable.coffee
5707+
<blockquote class="uneditable-code-block"><pre><code class="language-bash">▶ chmod +x ./executable.coffee
57085708
▶ ./executable.coffee
57095709
4
57105710
</code></pre>

docs/v2/test.html

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32712,6 +32712,7 @@ <h2>Another heading</h2>
3271232712
<script type="text/x-coffeescript" class="test" id="sourcemap">
3271332713
return if global.testingBrowser
3271432714

32715+
{spawn} = require('child_process')
3271532716
SourceMap = require '../src/sourcemap'
3271632717

3271732718
vlqEncodedValues = [
@@ -32776,6 +32777,52 @@ <h2>Another heading</h2>
3277632777
arrayEq v3SourceMap.sources, ['tempus_fugit.coffee']
3277732778
eq v3SourceMap.sourceRoot, './www_root/coffee/'
3277832779

32780+
test "native source maps", ->
32781+
new Promise (resolve, reject) ->
32782+
proc = spawn "node", [
32783+
"--enable-source-maps"
32784+
"-r", "./register.js"
32785+
"-r", "./test/integration/error.coffee"
32786+
]
32787+
32788+
# proc.stdout.setEncoding('utf8')
32789+
# proc.stdout.on 'data', (s) -> console.log(s)
32790+
err = ""
32791+
proc.stderr.setEncoding('utf8')
32792+
proc.stderr.on 'data', (s) -> err += s
32793+
proc.on 'exit', (status) ->
32794+
try
32795+
equal status, 1
32796+
32797+
[_, line] = err.match /error\.coffee:(\d+)/
32798+
equal line, 3 # Mapped source line
32799+
resolve()
32800+
catch e
32801+
reject(e)
32802+
32803+
test "don't change stack traces if another library has patched `Error.prepareStackTrace`", ->
32804+
new Promise (resolve, reject) ->
32805+
proc = spawn "node", [
32806+
"-r", "./test/integration/prepare_stack_trace.js",
32807+
"-r", "./register.js",
32808+
"-r", "./test/integration/error.coffee",
32809+
]
32810+
32811+
# proc.stdout.setEncoding('utf8')
32812+
# proc.stdout.on 'data', (s) -> console.log(s)
32813+
err = ""
32814+
proc.stderr.setEncoding('utf8')
32815+
proc.stderr.on 'data', (s) -> err += s
32816+
proc.on 'exit', (status) ->
32817+
try
32818+
equal status, 1
32819+
32820+
[_, line] = err.match /error\.coffee:(\d+)/
32821+
equal line, 4 # Unmapped source line
32822+
resolve()
32823+
catch e
32824+
reject(e)
32825+
3277932826
</script>
3278032827
<script type="text/x-coffeescript" class="test" id="strict">
3278132828
# Strict Early Errors

lib/coffeescript-browser-compiler-legacy/coffeescript.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/coffeescript-browser-compiler-modern/coffeescript.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/coffeescript/coffeescript.js

Lines changed: 9 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/coffeescript.coffee

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ exports.compile = compile = withPrettyErrors (code, options = {}) ->
5959
# Always generate a source map if no filename is passed in, since without a
6060
# a filename we have no way to retrieve this source later in the event that
6161
# we need to recompile it to get a source map for `prepareStackTrace`.
62-
generateSourceMap = options.sourceMap or options.inlineMap or not options.filename?
62+
generateSourceMap = options.sourceMap or
63+
options.inlineMap or
64+
nativeSourceMaps or
65+
not options.filename?
6366
filename = options.filename or '<anonymous>'
6467

6568
checkShebangLine filename, code
@@ -158,7 +161,7 @@ exports.compile = compile = withPrettyErrors (code, options = {}) ->
158161
if v3SourceMap and transpilerOutput.map
159162
v3SourceMap = transpilerOutput.map
160163

161-
if options.inlineMap
164+
if options.inlineMap or nativeSourceMaps
162165
encoded = base64encode JSON.stringify v3SourceMap
163166
sourceMapDataURI = "//# sourceMappingURL=data:application/json;base64,#{encoded}"
164167
sourceURL = "//# sourceURL=#{options.filename ? 'coffeescript'}"
@@ -246,7 +249,11 @@ parser.yy.parseError = (message, {token}) ->
246249
# from the lexer.
247250
helpers.throwSyntaxError "unexpected #{errorText}", errorLoc
248251

249-
if process.execArgv.includes('--enable-source-maps') or process.env.NODE_OPTIONS?.includes('--enable-source-maps')
252+
# Use native source maps rather than monkey patching `Error.prepareStackTrace`
253+
# if native source maps are enabled. Do not patch `Error.prepareStackTrace`
254+
# if another library has patched it since that would break them.
255+
nativeSourceMaps = process.execArgv.includes('--enable-source-maps') or process.env.NODE_OPTIONS?.includes('--enable-source-maps')
256+
if nativeSourceMaps or Error.prepareStackTrace
250257
registerCompiled = ->
251258
else
252259
# For each compiled file, save its source in memory in case we need to

test/integration/error.coffee

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# This file throws an error on line 3. It is used for testing error stack traces with sourcemaps.
2+
module.exports =
3+
throw new Error "I am error"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// This simulates a library hooking into `Error.prepareStackTrace` such as Babel
2+
// via `source-map-support`. This file is used in `../sourcemap.coffee` to test
3+
// that we won't break a previously installed handler.
4+
Error.prepareStackTrace = function (err, frames) {
5+
return frames.map(function (f) {
6+
return `^_^ ${f.getFileName()}:${f.getLineNumber()}:${f.getColumnNumber()}\n`;
7+
}).join("");
8+
};

0 commit comments

Comments
 (0)