opal 1.2.0 → 1.3.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|