Skip to content

Commit f6d6377

Browse files
ES module version of compiler for use in browsers; dynamic import() docs; revised Stage 3 policy (#5177)
* Build both a legacy and modern browser compiler * Dynamic import example and documentation * Update the docs to use the modern browser compiler if the browser supports it * Update policy regarding Stage 3 features * This never made sense, and assigning a string to index 0 *of a string* throws in Module mode (and silently does nothing in Script mode) so remove this unneeded code that throws when compiling `fn for i from from iterable` in Module mode * Have browser-based tests use the ES module version if supported * Simplify building logic * Update output * For the ES module version of the browser compiler, don't automatically attach the runScripts event handler * Consistent comments * Fix comment
1 parent 41b31c7 commit f6d6377

File tree

23 files changed

+11660
-211
lines changed

23 files changed

+11660
-211
lines changed

Cakefile

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,18 @@ build = (callback) ->
6666
buildParser()
6767
buildExceptParser callback
6868

69-
transpile = (code) ->
69+
transpile = (code, options = {}) ->
70+
options.minify = process.env.MINIFY isnt 'false'
71+
options.transform = process.env.TRANSFORM isnt 'false'
7072
babel = require '@babel/core'
7173
presets = []
7274
# Exclude the `modules` plugin in order to not break the `}(this));`
7375
# at the end of the `build:browser` code block.
74-
presets.push ['@babel/env', {modules: no}] unless process.env.TRANSFORM is 'false'
75-
presets.push ['minify', {mangle: no, evaluate: no, removeUndefined: no}] unless process.env.MINIFY is 'false'
76+
presets.push ['@babel/env', {modules: no}] if options.transform
77+
presets.push ['minify', {mangle: no, evaluate: no, removeUndefined: no}] if options.minify
7678
babelOptions =
77-
compact: process.env.MINIFY isnt 'false'
79+
compact: not options.minify
80+
comments: not options.minify
7881
presets: presets
7982
sourceType: 'script'
8083
{ code } = babel.transform code, babelOptions unless presets.length is 0
@@ -140,13 +143,18 @@ task 'build:browser', 'merge the built scripts into a single file for use in a b
140143
return module.exports;
141144
})();
142145
"""
146+
# From here, we generate two outputs: a legacy script output for all browsers
147+
# and a module output for browsers that support `<script type="module">`.
143148
code = """
149+
var CoffeeScript = function() {
150+
function require(path){ return require[path]; }
151+
#{code}
152+
return require['./browser'];
153+
}();
154+
"""
155+
scriptCode = transpile """
144156
(function(root) {
145-
var CoffeeScript = function() {
146-
function require(path){ return require[path]; }
147-
#{code}
148-
return require['./browser'];
149-
}();
157+
#{code}
150158
151159
if (typeof define === 'function' && define.amd) {
152160
define(function() { return CoffeeScript; });
@@ -155,10 +163,20 @@ task 'build:browser', 'merge the built scripts into a single file for use in a b
155163
}
156164
}(this));
157165
"""
158-
code = transpile code
159-
outputFolder = "docs/v#{majorVersion}/browser-compiler"
160-
fs.mkdirSync outputFolder unless fs.existsSync outputFolder
161-
fs.writeFileSync "#{outputFolder}/coffeescript.js", header + '\n' + code
166+
moduleCode = """
167+
#{code}
168+
169+
export default CoffeeScript;
170+
const { VERSION, compile, eval: evaluate, load, run, runScripts } = CoffeeScript;
171+
export { VERSION, compile, evaluate as eval, load, run, runScripts };
172+
"""
173+
for folder in ['browser-compiler', 'browser-compiler-modern']
174+
outputFolder = "docs/v#{majorVersion}/#{folder}"
175+
fs.mkdirSync outputFolder unless fs.existsSync outputFolder
176+
fs.writeFileSync "#{outputFolder}/coffeescript.js", """
177+
#{header}
178+
#{if folder is 'browser-compiler' then scriptCode else moduleCode}
179+
"""
162180

163181
task 'build:browser:full', 'merge the built scripts into a single file for use in a browser, and test it', ->
164182
invoke 'build:browser'

docs/browser-compiler-modern

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v2/browser-compiler-modern

docs/v2/annotated-source/browser.html

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ <h1>browser.coffee</h1>
262262

263263
</div>
264264

265-
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">runScripts</span> = -&gt;</span>
265+
<div class="content"><div class='highlight'><pre>CoffeeScript.runScripts = <span class="hljs-function">-&gt;</span>
266266
scripts = <span class="hljs-built_in">window</span>.<span class="hljs-built_in">document</span>.getElementsByTagName <span class="hljs-string">'script'</span>
267267
coffeetypes = [<span class="hljs-string">'text/coffeescript'</span>, <span class="hljs-string">'text/literate-coffeescript'</span>]
268268
coffees = (s <span class="hljs-keyword">for</span> s <span class="hljs-keyword">in</span> scripts <span class="hljs-keyword">when</span> s.type <span class="hljs-keyword">in</span> coffeetypes)
@@ -321,14 +321,19 @@ <h1>browser.coffee</h1>
321321
<div class="pilwrap ">
322322
<a class="pilcrow" href="#section-10">&#182;</a>
323323
</div>
324-
<p>Listen for window load, both in decent browsers and in IE.</p>
324+
<p>Listen for window load, both in decent browsers and in IE.
325+
Only attach this event handler on startup for the
326+
non-ES module version of the browser compiler, to preserve
327+
backward compatibility while letting the ES module version
328+
be importable without side effects.</p>
325329

326330
</div>
327331

328-
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> <span class="hljs-built_in">window</span>.addEventListener
329-
<span class="hljs-built_in">window</span>.addEventListener <span class="hljs-string">'DOMContentLoaded'</span>, runScripts, <span class="hljs-literal">no</span>
330-
<span class="hljs-keyword">else</span>
331-
<span class="hljs-built_in">window</span>.attachEvent <span class="hljs-string">'onload'</span>, runScripts</pre></div></div>
332+
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> <span class="hljs-keyword">this</span> <span class="hljs-keyword">is</span> <span class="hljs-built_in">window</span>
333+
<span class="hljs-keyword">if</span> <span class="hljs-built_in">window</span>.addEventListener
334+
<span class="hljs-built_in">window</span>.addEventListener <span class="hljs-string">'DOMContentLoaded'</span>, CoffeeScript.runScripts, <span class="hljs-literal">no</span>
335+
<span class="hljs-keyword">else</span>
336+
<span class="hljs-built_in">window</span>.attachEvent <span class="hljs-string">'onload'</span>, CoffeeScript.runScripts</pre></div></div>
332337

333338
</li>
334339

0 commit comments

Comments
 (0)