opal 1.2.0 → 1.3.0.alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.eslintrc.await.js +6 -0
- data/.eslintrc.js +34 -0
- data/.github/workflows/build.yml +8 -0
- data/.rubocop.yml +9 -0
- data/CHANGELOG.md +4 -0
- data/README.md +1 -1
- data/Rakefile +1 -0
- data/UNRELEASED.md +64 -38
- data/docs/async.md +109 -0
- data/docs/roda-sprockets.md +0 -2
- data/exe/opal +2 -0
- data/exe/opal-repl +2 -2
- data/lib/opal/builder.rb +5 -1
- data/lib/opal/builder_processors.rb +7 -2
- data/lib/opal/cache/file_cache.rb +119 -0
- data/lib/opal/cache.rb +71 -0
- data/lib/opal/cli.rb +35 -1
- data/lib/opal/cli_options.rb +21 -0
- data/lib/opal/cli_runners/chrome.rb +21 -14
- data/lib/opal/cli_runners/chrome_cdp_interface.js +30285 -0
- data/lib/opal/cli_runners/{chrome.js → chrome_cdp_interface.rb} +27 -6
- data/lib/opal/cli_runners/compiler.rb +2 -1
- data/lib/opal/cli_runners/gjs.rb +27 -0
- data/lib/opal/cli_runners/mini_racer.rb +36 -0
- data/lib/opal/cli_runners/source-map-support-browser.js +276 -91
- data/lib/opal/cli_runners/source-map-support-node.js +276 -91
- data/lib/opal/cli_runners/source-map-support.js +60 -18
- data/lib/opal/cli_runners.rb +2 -0
- data/lib/opal/compiler.rb +99 -10
- data/lib/opal/fragment.rb +77 -14
- data/lib/opal/nodes/args/extract_kwrestarg.rb +6 -4
- data/lib/opal/nodes/args/extract_restarg.rb +10 -12
- data/lib/opal/nodes/args.rb +28 -0
- data/lib/opal/nodes/base.rb +29 -5
- data/lib/opal/nodes/call.rb +123 -2
- data/lib/opal/nodes/case.rb +7 -1
- data/lib/opal/nodes/class.rb +12 -2
- data/lib/opal/nodes/def.rb +3 -23
- data/lib/opal/nodes/definitions.rb +21 -4
- data/lib/opal/nodes/helpers.rb +2 -2
- data/lib/opal/nodes/if.rb +39 -9
- data/lib/opal/nodes/iter.rb +15 -3
- data/lib/opal/nodes/lambda.rb +3 -1
- data/lib/opal/nodes/literal.rb +13 -7
- data/lib/opal/nodes/logic.rb +2 -2
- data/lib/opal/nodes/module.rb +12 -2
- data/lib/opal/nodes/rescue.rb +59 -34
- data/lib/opal/nodes/scope.rb +88 -6
- data/lib/opal/nodes/super.rb +52 -25
- data/lib/opal/nodes/top.rb +13 -7
- data/lib/opal/nodes/while.rb +7 -1
- data/lib/opal/parser/patch.rb +2 -1
- data/lib/opal/repl.rb +137 -49
- data/lib/opal/rewriters/binary_operator_assignment.rb +10 -10
- data/lib/opal/rewriters/block_to_iter.rb +3 -3
- data/lib/opal/rewriters/for_rewriter.rb +7 -7
- data/lib/opal/rewriters/js_reserved_words.rb +5 -3
- data/lib/opal/source_map/file.rb +7 -4
- data/lib/opal/source_map/map.rb +17 -3
- data/lib/opal/version.rb +1 -1
- data/opal/corelib/array.rb +2 -2
- data/opal/corelib/binding.rb +46 -0
- data/opal/corelib/boolean.rb +54 -4
- data/opal/corelib/class.rb +2 -0
- data/opal/corelib/constants.rb +2 -2
- data/opal/corelib/error.rb +98 -12
- data/opal/corelib/io.rb +250 -38
- data/opal/corelib/kernel/format.rb +5 -2
- data/opal/corelib/kernel.rb +44 -23
- data/opal/corelib/main.rb +5 -0
- data/opal/corelib/method.rb +1 -0
- data/opal/corelib/module.rb +28 -0
- data/opal/corelib/number.rb +12 -1
- data/opal/corelib/random/seedrandom.js.rb +2 -2
- data/opal/corelib/regexp.rb +47 -3
- data/opal/corelib/runtime.js +152 -12
- data/opal/corelib/string/encoding.rb +17 -17
- data/opal/corelib/string.rb +2 -0
- data/opal/corelib/struct.rb +10 -3
- data/opal/corelib/trace_point.rb +57 -0
- data/opal/opal/full.rb +2 -0
- data/package.json +3 -2
- data/spec/filters/bugs/array.rb +0 -1
- data/spec/filters/bugs/basicobject.rb +0 -1
- data/spec/filters/bugs/binding.rb +27 -0
- data/spec/filters/bugs/enumerator.rb +132 -0
- data/spec/filters/bugs/exception.rb +70 -93
- data/spec/filters/bugs/float.rb +0 -1
- data/spec/filters/bugs/kernel.rb +3 -9
- data/spec/filters/bugs/language.rb +15 -58
- data/spec/filters/bugs/main.rb +16 -0
- data/spec/filters/bugs/matrix.rb +39 -0
- data/spec/filters/bugs/method.rb +0 -2
- data/spec/filters/bugs/module.rb +36 -79
- data/spec/filters/bugs/proc.rb +0 -1
- data/spec/filters/bugs/regexp.rb +0 -16
- data/spec/filters/bugs/trace_point.rb +12 -0
- data/spec/filters/bugs/warnings.rb +0 -4
- data/spec/filters/unsupported/freeze.rb +2 -0
- data/spec/filters/unsupported/privacy.rb +4 -0
- data/spec/lib/compiler_spec.rb +7 -1
- data/spec/lib/repl_spec.rb +4 -2
- data/spec/lib/source_map/file_spec.rb +1 -1
- data/spec/mspec-opal/formatters.rb +18 -4
- data/spec/mspec-opal/runner.rb +2 -2
- data/spec/opal/core/boolean_spec.rb +44 -0
- data/spec/opal/core/hash_spec.rb +8 -0
- data/spec/opal/core/number/to_s_spec.rb +11 -0
- data/spec/opal/stdlib/json/ext_spec.rb +3 -3
- data/spec/opal/stdlib/logger/logger_spec.rb +10 -1
- data/spec/ruby_specs +18 -0
- data/stdlib/await.rb +83 -0
- data/stdlib/base64.rb +4 -4
- data/stdlib/bigdecimal/bignumber.js.rb +4 -2
- data/stdlib/bigdecimal.rb +1 -0
- data/stdlib/gjs/io.rb +33 -0
- data/stdlib/gjs/kernel.rb +5 -0
- data/stdlib/gjs.rb +2 -0
- data/stdlib/js.rb +4 -0
- data/stdlib/json.rb +3 -3
- data/stdlib/logger.rb +1 -1
- data/stdlib/nashorn/file.rb +2 -0
- data/stdlib/nodejs/env.rb +7 -0
- data/stdlib/nodejs/file.rb +6 -41
- data/stdlib/nodejs/io.rb +21 -5
- data/stdlib/nodejs/js-yaml-3-6-1.js +2 -2
- data/stdlib/opal/miniracer.rb +6 -0
- data/stdlib/opal/platform.rb +4 -0
- data/stdlib/opal/repl_js.rb +5 -0
- data/stdlib/opal/replutils.rb +271 -0
- data/stdlib/opal-parser.rb +24 -11
- data/stdlib/opal-platform.rb +8 -0
- data/stdlib/promise/v2.rb +16 -4
- data/stdlib/promise.rb +14 -0
- data/stdlib/stringio.rb +13 -110
- data/stdlib/thread.rb +29 -0
- data/tasks/building.rake +10 -4
- data/tasks/linting-parse-eslint-results.js +39 -0
- data/tasks/linting.rake +38 -28
- data/tasks/performance/asciidoctor_test.rb.erb +6 -0
- data/tasks/performance/optimization_status.rb +77 -0
- data/tasks/performance.rake +149 -0
- data/tasks/testing.rake +9 -1
- data/test/nodejs/test_await.rb +169 -0
- data/test/opal/promisev2/test_error.rb +9 -3
- data/test/opal/unsupported_and_bugs.rb +5 -0
- data/vendored-minitest/minitest/benchmark.rb +9 -7
- data/vendored-minitest/minitest/test.rb +14 -12
- data/vendored-minitest/minitest.rb +19 -16
- data/yarn.lock +686 -117
- metadata +60 -23
- data/.jshintrc +0 -41
- data/spec/filters/unsupported/refinements.rb +0 -8
- data/vendored-minitest/minitest/hell.rb +0 -11
- data/vendored-minitest/minitest/parallel.rb +0 -65
- data/vendored-minitest/minitest/pride.rb +0 -4
- data/vendored-minitest/minitest/pride_plugin.rb +0 -142
- data/vendored-minitest/minitest/unit.rb +0 -45
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// to do so, `run bin/build-browser-source-map-support`
|
|
4
4
|
|
|
5
5
|
// The following is taken and adapted from the work of Evan Wallace
|
|
6
|
-
// https://github.com/evanw/node-source-map-support v0.5.
|
|
6
|
+
// https://github.com/evanw/node-source-map-support v0.5.19
|
|
7
7
|
|
|
8
8
|
// The MIT License (MIT)
|
|
9
9
|
//
|
|
@@ -43,6 +43,16 @@ try {
|
|
|
43
43
|
|
|
44
44
|
var bufferFrom = require('buffer-from');
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Requires a module which is protected against bundler minification.
|
|
48
|
+
*
|
|
49
|
+
* @param {NodeModule} mod
|
|
50
|
+
* @param {string} request
|
|
51
|
+
*/
|
|
52
|
+
function dynamicRequire(mod, request) {
|
|
53
|
+
return mod.require(request);
|
|
54
|
+
}
|
|
55
|
+
|
|
46
56
|
// Only install once if called multiple times
|
|
47
57
|
var errorFormatterInstalled = false;
|
|
48
58
|
var uncaughtShimInstalled = false;
|
|
@@ -169,7 +179,7 @@ function retrieveSourceMapURL(source) {
|
|
|
169
179
|
|
|
170
180
|
// Get the URL of the source map
|
|
171
181
|
fileData = retrieveFile(source);
|
|
172
|
-
var re = /(?:\/\/[@#][
|
|
182
|
+
var re = /(?:\/\/[@#][\s]*sourceMappingURL=([^\s'"]+)[\s]*$)|(?:\/\*[@#][\s]*sourceMappingURL=([^\s*'"]+)[\s]*(?:\*\/)[\s]*$)/mg;
|
|
173
183
|
// Keep executing the search to find the *last* sourceMappingURL to avoid
|
|
174
184
|
// picking up sourceMappingURLs from comments, strings, etc.
|
|
175
185
|
var lastMatch, match;
|
|
@@ -380,8 +390,13 @@ function cloneCallSite(frame) {
|
|
|
380
390
|
return object;
|
|
381
391
|
}
|
|
382
392
|
|
|
383
|
-
function wrapCallSite(frame) {
|
|
393
|
+
function wrapCallSite(frame, state) {
|
|
394
|
+
// provides interface backward compatibility
|
|
395
|
+
if (state === undefined) {
|
|
396
|
+
state = { nextPosition: null, curPosition: null }
|
|
397
|
+
}
|
|
384
398
|
if(frame.isNative()) {
|
|
399
|
+
state.curPosition = null;
|
|
385
400
|
return frame;
|
|
386
401
|
}
|
|
387
402
|
|
|
@@ -395,7 +410,11 @@ function wrapCallSite(frame) {
|
|
|
395
410
|
|
|
396
411
|
// Fix position in Node where some (internal) code is prepended.
|
|
397
412
|
// See https://github.com/evanw/node-source-map-support/issues/36
|
|
398
|
-
|
|
413
|
+
// Header removed in node at ^10.16 || >=11.11.0
|
|
414
|
+
// v11 is not an LTS candidate, we can just test the one version with it.
|
|
415
|
+
// Test node versions for: 10.16-19, 10.20+, 12-19, 20-99, 100+, or 11.11
|
|
416
|
+
var noHeader = /^v(10\.1[6-9]|10\.[2-9][0-9]|10\.[0-9]{3,}|1[2-9]\d*|[2-9]\d|\d{3,}|11\.11)/;
|
|
417
|
+
var headerLength = noHeader.test(process.version) ? 0 : 62;
|
|
399
418
|
if (line === 1 && column > headerLength && !isInBrowser() && !frame.isEval()) {
|
|
400
419
|
column -= headerLength;
|
|
401
420
|
}
|
|
@@ -405,9 +424,15 @@ function wrapCallSite(frame) {
|
|
|
405
424
|
line: line,
|
|
406
425
|
column: column
|
|
407
426
|
});
|
|
427
|
+
state.curPosition = position;
|
|
408
428
|
frame = cloneCallSite(frame);
|
|
409
429
|
var originalFunctionName = frame.getFunctionName;
|
|
410
|
-
frame.getFunctionName = function() {
|
|
430
|
+
frame.getFunctionName = function() {
|
|
431
|
+
if (state.nextPosition == null) {
|
|
432
|
+
return originalFunctionName();
|
|
433
|
+
}
|
|
434
|
+
return state.nextPosition.name || originalFunctionName();
|
|
435
|
+
};
|
|
411
436
|
frame.getFileName = function() { return position.source; };
|
|
412
437
|
frame.getLineNumber = function() { return position.line; };
|
|
413
438
|
frame.getColumnNumber = function() { return position.column + 1; };
|
|
@@ -440,9 +465,14 @@ function prepareStackTrace(error, stack) {
|
|
|
440
465
|
var message = error.message || '';
|
|
441
466
|
var errorString = name + ": " + message;
|
|
442
467
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
468
|
+
var state = { nextPosition: null, curPosition: null };
|
|
469
|
+
var processedStack = [];
|
|
470
|
+
for (var i = stack.length - 1; i >= 0; i--) {
|
|
471
|
+
processedStack.push('\n from ' + wrapCallSite(stack[i], state));
|
|
472
|
+
state.nextPosition = state.curPosition;
|
|
473
|
+
}
|
|
474
|
+
state.curPosition = state.nextPosition = null;
|
|
475
|
+
return errorString + processedStack.reverse().join('');
|
|
446
476
|
}
|
|
447
477
|
|
|
448
478
|
// Generate position and snippet of original source with pointer
|
|
@@ -485,12 +515,17 @@ function printErrorAndExit (error) {
|
|
|
485
515
|
process.stderr._handle.setBlocking(true);
|
|
486
516
|
}
|
|
487
517
|
|
|
488
|
-
if (
|
|
489
|
-
console.error();
|
|
490
|
-
console.error(source);
|
|
518
|
+
if (typeof error.$full_message === 'function') {
|
|
519
|
+
console.error(error.$full_message().$chomp());
|
|
491
520
|
}
|
|
521
|
+
else {
|
|
522
|
+
if (source) {
|
|
523
|
+
console.error();
|
|
524
|
+
console.error(source);
|
|
525
|
+
}
|
|
492
526
|
|
|
493
|
-
|
|
527
|
+
console.error(error.stack);
|
|
528
|
+
}
|
|
494
529
|
process.exit(1);
|
|
495
530
|
}
|
|
496
531
|
|
|
@@ -551,12 +586,8 @@ exports.install = function(options) {
|
|
|
551
586
|
|
|
552
587
|
// Support runtime transpilers that include inline source maps
|
|
553
588
|
if (options.hookRequire && !isInBrowser()) {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
Module = require('module');
|
|
557
|
-
} catch (err) {
|
|
558
|
-
// NOP: Loading in catch block to convert webpack error to warning.
|
|
559
|
-
}
|
|
589
|
+
// Use dynamicRequire to avoid including in browser bundles
|
|
590
|
+
var Module = dynamicRequire(module, 'module');
|
|
560
591
|
var $compile = Module.prototype._compile;
|
|
561
592
|
|
|
562
593
|
if (!$compile.__sourceMapSupport) {
|
|
@@ -586,6 +617,17 @@ exports.install = function(options) {
|
|
|
586
617
|
var installHandler = 'handleUncaughtExceptions' in options ?
|
|
587
618
|
options.handleUncaughtExceptions : true;
|
|
588
619
|
|
|
620
|
+
// Do not override 'uncaughtException' with our own handler in Node.js
|
|
621
|
+
// Worker threads. Workers pass the error to the main thread as an event,
|
|
622
|
+
// rather than printing something to stderr and exiting.
|
|
623
|
+
try {
|
|
624
|
+
// We need to use `dynamicRequire` because `require` on it's own will be optimized by WebPack/Browserify.
|
|
625
|
+
var worker_threads = dynamicRequire(module, 'worker_threads');
|
|
626
|
+
if (worker_threads.isMainThread === false) {
|
|
627
|
+
installHandler = false;
|
|
628
|
+
}
|
|
629
|
+
} catch(e) {}
|
|
630
|
+
|
|
589
631
|
// Provide the option to not install the uncaught exception handler. This is
|
|
590
632
|
// to support other uncaught exception handlers (in test frameworks, for
|
|
591
633
|
// example). If this handler is not installed and there are no other uncaught
|
data/lib/opal/cli_runners.rb
CHANGED
|
@@ -65,6 +65,8 @@ module Opal
|
|
|
65
65
|
register_runner :compiler, :Compiler, 'opal/cli_runners/compiler'
|
|
66
66
|
register_runner :nashorn, :Nashorn, 'opal/cli_runners/nashorn'
|
|
67
67
|
register_runner :nodejs, :Nodejs, 'opal/cli_runners/nodejs'
|
|
68
|
+
register_runner :gjs, :Gjs, 'opal/cli_runners/gjs'
|
|
69
|
+
register_runner :miniracer, :MiniRacer, 'opal/cli_runners/mini_racer'
|
|
68
70
|
register_runner :server, :Server, 'opal/cli_runners/server'
|
|
69
71
|
|
|
70
72
|
alias_runner :osascript, :applescript
|
data/lib/opal/compiler.rb
CHANGED
|
@@ -137,6 +137,11 @@ module Opal
|
|
|
137
137
|
# Prepare the code for future requires
|
|
138
138
|
compiler_option :requirable, default: false, as: :requirable?
|
|
139
139
|
|
|
140
|
+
# @!method esm?
|
|
141
|
+
#
|
|
142
|
+
# Wrap compiler result as self contained ES6 module
|
|
143
|
+
compiler_option :esm, default: false, as: :esm?
|
|
144
|
+
|
|
140
145
|
# @!method inline_operators?
|
|
141
146
|
#
|
|
142
147
|
# are operators compiled inline
|
|
@@ -159,6 +164,38 @@ module Opal
|
|
|
159
164
|
# Adds comments for every method definition
|
|
160
165
|
compiler_option :parse_comments, default: false, as: :parse_comments?
|
|
161
166
|
|
|
167
|
+
compiler_option :scope_variables, default: []
|
|
168
|
+
|
|
169
|
+
# @!method async_await
|
|
170
|
+
#
|
|
171
|
+
# Enable async/await support and optionally enable auto-await.
|
|
172
|
+
#
|
|
173
|
+
# Use either true, false, an Array of Symbols, a String containing names
|
|
174
|
+
# to auto-await separated by a comma or a Regexp.
|
|
175
|
+
#
|
|
176
|
+
# Auto-await awaits provided methods by default as if .__await__ was added to
|
|
177
|
+
# them automatically.
|
|
178
|
+
#
|
|
179
|
+
# By default, the support is disabled (set to false).
|
|
180
|
+
#
|
|
181
|
+
# If the config value is not set to false, any calls to #__await__ will be
|
|
182
|
+
# translated to ES8 await keyword which makes the scope return a Promise
|
|
183
|
+
# and a containing scope will be async (instead of a value, it will return
|
|
184
|
+
# a Promise).
|
|
185
|
+
#
|
|
186
|
+
# If the config value is an array, or a String separated by a comma,
|
|
187
|
+
# auto-await is also enabled.
|
|
188
|
+
#
|
|
189
|
+
# A member of this collection can contain a wildcard character * in which
|
|
190
|
+
# case all methods containing a given substring will be awaited.
|
|
191
|
+
#
|
|
192
|
+
# It can be used as a magic comment, examples:
|
|
193
|
+
# ```
|
|
194
|
+
# # await: true
|
|
195
|
+
# # await: *await*
|
|
196
|
+
# # await: *await*, sleep, gets
|
|
197
|
+
compiler_option :await, default: false, as: :async_await, magic_comment: true
|
|
198
|
+
|
|
162
199
|
# @return [String] The compiled ruby code
|
|
163
200
|
attr_reader :result
|
|
164
201
|
|
|
@@ -211,7 +248,16 @@ module Opal
|
|
|
211
248
|
|
|
212
249
|
sexp, comments, tokens = re_raise_with_location { @parser.tokenize(@buffer) }
|
|
213
250
|
|
|
214
|
-
|
|
251
|
+
kind = case
|
|
252
|
+
when requirable?
|
|
253
|
+
:require
|
|
254
|
+
when eval?
|
|
255
|
+
:eval
|
|
256
|
+
else
|
|
257
|
+
:main
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
@sexp = s(:top, sexp || s(:nil)).tap { |i| i.meta[:kind] = kind }
|
|
215
261
|
@comments = ::Parser::Source::Comment.associate_locations(sexp, comments)
|
|
216
262
|
@magic_comments = MagicComments.parse(sexp, comments)
|
|
217
263
|
@eof_content = EofContent.new(tokens, @source).eof
|
|
@@ -223,7 +269,8 @@ module Opal
|
|
|
223
269
|
# @param source_file [String] optional source_file to reference ruby source
|
|
224
270
|
# @return [Opal::SourceMap]
|
|
225
271
|
def source_map
|
|
226
|
-
|
|
272
|
+
# We only use @source_map if compiler is cached.
|
|
273
|
+
@source_map || ::Opal::SourceMap::File.new(@fragments, file, @source, @result)
|
|
227
274
|
end
|
|
228
275
|
|
|
229
276
|
# Any helpers required by this file. Used by {Opal::Nodes::Top} to reference
|
|
@@ -247,6 +294,32 @@ module Opal
|
|
|
247
294
|
@method_calls ||= Set.new
|
|
248
295
|
end
|
|
249
296
|
|
|
297
|
+
alias async_await_before_typecasting async_await
|
|
298
|
+
def async_await
|
|
299
|
+
if defined? @async_await
|
|
300
|
+
@async_await
|
|
301
|
+
else
|
|
302
|
+
original = async_await_before_typecasting
|
|
303
|
+
@async_await = case original
|
|
304
|
+
when String
|
|
305
|
+
async_await_set_to_regexp(original.split(',').map { |h| h.strip.to_sym })
|
|
306
|
+
when Array, Set
|
|
307
|
+
async_await_set_to_regexp(original.to_a.map(&:to_sym))
|
|
308
|
+
when Regexp, true, false
|
|
309
|
+
original
|
|
310
|
+
else
|
|
311
|
+
raise 'A value of await compiler option can be either ' \
|
|
312
|
+
'a Set, an Array, a String or a Boolean.'
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def async_await_set_to_regexp(set)
|
|
318
|
+
set = set.map { |name| Regexp.escape(name.to_s).gsub('\*', '.*?') }
|
|
319
|
+
set = set.join('|')
|
|
320
|
+
/^(#{set})$/
|
|
321
|
+
end
|
|
322
|
+
|
|
250
323
|
# This is called when a parsing/processing error occurs. This
|
|
251
324
|
# method simply appends the filename and curent line number onto
|
|
252
325
|
# the message and raises it.
|
|
@@ -421,8 +494,8 @@ module Opal
|
|
|
421
494
|
case sexp.type
|
|
422
495
|
when :undef
|
|
423
496
|
# undef :method_name always returns nil
|
|
424
|
-
returns
|
|
425
|
-
when :break, :next, :redo
|
|
497
|
+
returns sexp.updated(:begin, [sexp, s(:nil)])
|
|
498
|
+
when :break, :next, :redo, :retry
|
|
426
499
|
sexp
|
|
427
500
|
when :yield
|
|
428
501
|
sexp.updated(:returnable_yield, nil)
|
|
@@ -453,7 +526,7 @@ module Opal
|
|
|
453
526
|
when :ensure
|
|
454
527
|
rescue_sexp, ensure_body = *sexp
|
|
455
528
|
sexp = sexp.updated(nil, [returns(rescue_sexp), ensure_body])
|
|
456
|
-
|
|
529
|
+
sexp.updated(:js_return, [sexp])
|
|
457
530
|
when :begin, :kwbegin
|
|
458
531
|
# Wrapping last expression with s(:js_return, ...)
|
|
459
532
|
*rest, last = *sexp
|
|
@@ -474,11 +547,14 @@ module Opal
|
|
|
474
547
|
]
|
|
475
548
|
)
|
|
476
549
|
else
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
550
|
+
if sexp.type == :send && sexp.children[1] == :debugger
|
|
551
|
+
# debugger is a statement, so it doesn't return a value
|
|
552
|
+
# and returning it is invalid. Therefore we update it
|
|
553
|
+
# to do `debugger; return nil`.
|
|
554
|
+
sexp.updated(:begin, [sexp, s(:js_return, s(:nil))])
|
|
555
|
+
else
|
|
556
|
+
sexp.updated(:js_return, [sexp])
|
|
557
|
+
end
|
|
482
558
|
end
|
|
483
559
|
end
|
|
484
560
|
|
|
@@ -492,5 +568,18 @@ module Opal
|
|
|
492
568
|
fragment('false', scope, sexp)
|
|
493
569
|
end
|
|
494
570
|
end
|
|
571
|
+
|
|
572
|
+
# Marshalling for cache shortpath
|
|
573
|
+
def marshal_dump
|
|
574
|
+
[@options, @option_values, @source_map ||= source_map.cache,
|
|
575
|
+
@magic_comments, @result,
|
|
576
|
+
@required_trees, @requires]
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
def marshal_load(src)
|
|
580
|
+
@options, @option_values, @source_map,
|
|
581
|
+
@magic_comments, @result,
|
|
582
|
+
@required_trees, @requires = src
|
|
583
|
+
end
|
|
495
584
|
end
|
|
496
585
|
end
|
data/lib/opal/fragment.rb
CHANGED
|
@@ -28,41 +28,104 @@ module Opal
|
|
|
28
28
|
"f(#{@code.inspect})"
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
def
|
|
32
|
-
case
|
|
33
|
-
when :top
|
|
34
|
-
|
|
31
|
+
def source_map_name_for(sexp)
|
|
32
|
+
case sexp.type
|
|
33
|
+
when :top
|
|
34
|
+
case sexp.meta[:kind]
|
|
35
|
+
when :require
|
|
36
|
+
'<top (required)>'
|
|
37
|
+
when :eval
|
|
38
|
+
'(eval)'
|
|
39
|
+
when :main
|
|
40
|
+
'<main>'
|
|
41
|
+
end
|
|
42
|
+
when :begin, :newline, :js_return
|
|
43
|
+
source_map_name_for(@scope.sexp) if @scope
|
|
44
|
+
when :iter
|
|
45
|
+
scope = @scope
|
|
46
|
+
iters = 1
|
|
47
|
+
while scope
|
|
48
|
+
if scope.class == Nodes::IterNode
|
|
49
|
+
iters += 1
|
|
50
|
+
scope = scope.parent
|
|
51
|
+
else
|
|
52
|
+
break
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
level = " (#{iters} levels)" if iters > 1
|
|
56
|
+
"block#{level} in #{source_map_name_for(scope.sexp)}"
|
|
35
57
|
when :self
|
|
36
58
|
'self'
|
|
37
59
|
when :module
|
|
38
|
-
|
|
60
|
+
const, = *sexp
|
|
61
|
+
"<module:#{source_map_name_for(const)}>"
|
|
39
62
|
when :class
|
|
40
|
-
|
|
63
|
+
const, = *sexp
|
|
64
|
+
"<class:#{source_map_name_for(const)}>"
|
|
65
|
+
when :const
|
|
66
|
+
scope, name = *sexp
|
|
67
|
+
if !scope || scope.type == :cbase
|
|
68
|
+
name.to_s
|
|
69
|
+
else
|
|
70
|
+
"#{source_map_name_for(scope)}::#{name}"
|
|
71
|
+
end
|
|
41
72
|
when :int
|
|
42
|
-
|
|
73
|
+
sexp.children.first
|
|
43
74
|
when :def
|
|
44
|
-
|
|
75
|
+
sexp.children.first
|
|
45
76
|
when :defs
|
|
46
|
-
|
|
77
|
+
sexp.children[1]
|
|
47
78
|
when :send
|
|
48
|
-
|
|
49
|
-
when :lvar, :lvasgn, :lvdeclare, :ivar, :ivasgn, :gvar, :cvar, :cvasgn, :gvars, :gvasgn
|
|
50
|
-
|
|
79
|
+
sexp.children[1]
|
|
80
|
+
when :lvar, :lvasgn, :lvdeclare, :ivar, :ivasgn, :gvar, :cvar, :cvasgn, :gvars, :gvasgn, :arg
|
|
81
|
+
sexp.children.first
|
|
82
|
+
when :str, :xstr # Inside xstr - JS calls
|
|
83
|
+
source_map_name_for(@scope.sexp)
|
|
51
84
|
else
|
|
52
85
|
# nil
|
|
53
86
|
end
|
|
54
87
|
end
|
|
55
88
|
|
|
89
|
+
def source_map_name
|
|
90
|
+
return nil unless @sexp
|
|
91
|
+
|
|
92
|
+
source_map_name_for(@sexp)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def location
|
|
96
|
+
case
|
|
97
|
+
when !@sexp
|
|
98
|
+
nil
|
|
99
|
+
when @sexp.type == :send
|
|
100
|
+
loc = @sexp.loc
|
|
101
|
+
if loc.respond_to? :dot # a>.b || a>+b / >a / a>[b]
|
|
102
|
+
loc.dot || loc.selector
|
|
103
|
+
elsif loc.respond_to? :operator # a >|= b
|
|
104
|
+
loc.operator
|
|
105
|
+
else
|
|
106
|
+
@sexp
|
|
107
|
+
end
|
|
108
|
+
when @sexp.type == :iter
|
|
109
|
+
@sexp.loc.begin # [1,2].each >{ }
|
|
110
|
+
else
|
|
111
|
+
@sexp
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
56
115
|
# Original line this fragment was created from
|
|
57
116
|
# @return [Integer, nil]
|
|
58
117
|
def line
|
|
59
|
-
|
|
118
|
+
location&.line
|
|
60
119
|
end
|
|
61
120
|
|
|
62
121
|
# Original column this fragment was created from
|
|
63
122
|
# @return [Integer, nil]
|
|
64
123
|
def column
|
|
65
|
-
|
|
124
|
+
location&.column
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def skip_source_map?
|
|
128
|
+
@sexp == false
|
|
66
129
|
end
|
|
67
130
|
end
|
|
68
131
|
end
|
|
@@ -16,10 +16,12 @@ module Opal
|
|
|
16
16
|
children :name
|
|
17
17
|
|
|
18
18
|
def compile
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
# def m(**)
|
|
20
|
+
# arguments are assigned to `$kw_rest_arg` for super call
|
|
21
|
+
name = self.name || '$kw_rest_arg'
|
|
22
|
+
|
|
23
|
+
add_temp name
|
|
24
|
+
line "#{name} = Opal.kwrestargs($kwargs, #{used_kwargs});"
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
def used_kwargs
|
|
@@ -19,19 +19,17 @@ module Opal
|
|
|
19
19
|
children :name, :args_to_keep
|
|
20
20
|
|
|
21
21
|
def compile
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
# def m(*)
|
|
23
|
+
# arguments are assigned to `$rest_arg` for super call
|
|
24
|
+
name = self.name || '$rest_arg'
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
# def m(*, a)
|
|
33
|
-
# We still have to "cut" our splat
|
|
34
|
-
line "$post_args.splice(0, $post_args.length - #{args_to_keep});"
|
|
26
|
+
add_temp name
|
|
27
|
+
|
|
28
|
+
if args_to_keep == 0
|
|
29
|
+
# no post-args, we are free to grab everything
|
|
30
|
+
line "#{name} = $post_args;"
|
|
31
|
+
else
|
|
32
|
+
line "#{name} = $post_args.splice(0, $post_args.length - #{args_to_keep});"
|
|
35
33
|
end
|
|
36
34
|
end
|
|
37
35
|
end
|
data/lib/opal/nodes/args.rb
CHANGED
|
@@ -25,12 +25,40 @@ module Opal
|
|
|
25
25
|
class ArgsNode < Base
|
|
26
26
|
handle :args
|
|
27
27
|
|
|
28
|
+
# ruby allows for args with the same name, if the arg starts with a '_', like:
|
|
29
|
+
# def funny_method_name(_, _)
|
|
30
|
+
# puts _
|
|
31
|
+
# end
|
|
32
|
+
# but javascript in strict mode does not allow for args with the same name
|
|
33
|
+
# ruby assigns the value of the first arg given
|
|
34
|
+
# funny_method_name(1, 2) => 1
|
|
35
|
+
# 1. check for args starting with '_' and check if they appear multiple times
|
|
36
|
+
# 2. leave the first appearance as it is and rename the other ones
|
|
37
|
+
# compiler result:
|
|
38
|
+
# function $$funny_method_name(_, __$2)
|
|
39
|
+
|
|
28
40
|
def compile
|
|
41
|
+
same_arg_counter = {}
|
|
29
42
|
children.each_with_index do |arg, idx|
|
|
43
|
+
if multiple_underscore?(arg)
|
|
44
|
+
same_arg_counter[arg] ||= 0
|
|
45
|
+
same_arg_counter[arg] += 1
|
|
46
|
+
if same_arg_counter[arg] > 1
|
|
47
|
+
arg = s(arg.type, :"#{arg.children[0]}_$#{same_arg_counter[arg]}")
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
30
51
|
push ', ' if idx != 0
|
|
31
52
|
push process(arg)
|
|
32
53
|
end
|
|
33
54
|
end
|
|
55
|
+
|
|
56
|
+
def multiple_underscore?(arg)
|
|
57
|
+
arg.type == :arg &&
|
|
58
|
+
arg.children.count == 1 &&
|
|
59
|
+
arg.children.first.to_s.start_with?('_') &&
|
|
60
|
+
children.count(arg) > 1
|
|
61
|
+
end
|
|
34
62
|
end
|
|
35
63
|
end
|
|
36
64
|
end
|
data/lib/opal/nodes/base.rb
CHANGED
|
@@ -29,7 +29,7 @@ module Opal
|
|
|
29
29
|
false
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
attr_reader :compiler, :type
|
|
32
|
+
attr_reader :compiler, :type, :sexp
|
|
33
33
|
|
|
34
34
|
def initialize(sexp, level, compiler)
|
|
35
35
|
@sexp = sexp
|
|
@@ -73,8 +73,8 @@ module Opal
|
|
|
73
73
|
push post
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
def fragment(str)
|
|
77
|
-
Opal::Fragment.new str, scope, @sexp
|
|
76
|
+
def fragment(str, loc: true)
|
|
77
|
+
Opal::Fragment.new str, scope, loc && @sexp
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
def error(msg)
|
|
@@ -85,8 +85,12 @@ module Opal
|
|
|
85
85
|
@compiler.scope
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
-
def
|
|
89
|
-
|
|
88
|
+
def top_scope
|
|
89
|
+
scope.top_scope
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def s(type, *children)
|
|
93
|
+
::Opal::AST::Node.new(type, children, location: @sexp.loc)
|
|
90
94
|
end
|
|
91
95
|
|
|
92
96
|
def expr?
|
|
@@ -165,6 +169,18 @@ module Opal
|
|
|
165
169
|
scope.in_ensure?
|
|
166
170
|
end
|
|
167
171
|
|
|
172
|
+
def in_resbody(&block)
|
|
173
|
+
scope.in_resbody(&block)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def in_resbody?
|
|
177
|
+
scope.in_resbody?
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def in_rescue(node, &block)
|
|
181
|
+
scope.in_rescue(node, &block)
|
|
182
|
+
end
|
|
183
|
+
|
|
168
184
|
def class_variable_owner_nesting_level
|
|
169
185
|
cvar_scope = scope
|
|
170
186
|
nesting_level = 0
|
|
@@ -192,6 +208,14 @@ module Opal
|
|
|
192
208
|
def comments
|
|
193
209
|
compiler.comments[@sexp.loc]
|
|
194
210
|
end
|
|
211
|
+
|
|
212
|
+
def source_location
|
|
213
|
+
file = @sexp.loc.expression.source_buffer.name
|
|
214
|
+
file = "<internal:#{file}>" if file.start_with?("corelib/")
|
|
215
|
+
file = "<js:#{file}>" if file.end_with?(".js")
|
|
216
|
+
line = @sexp.loc.line
|
|
217
|
+
"['#{file}', #{line}]"
|
|
218
|
+
end
|
|
195
219
|
end
|
|
196
220
|
end
|
|
197
221
|
end
|