Module: Quickjs
- Defined in:
- lib/quickjs.rb,
lib/quickjs/version.rb,
lib/quickjs/function.rb,
lib/quickjs/runnable.rb,
lib/quickjs/polyfills.rb,
lib/quickjs/crypto_key.rb,
lib/quickjs/subtle_crypto.rb,
ext/quickjsrb/quickjsrb.c
Defined Under Namespace
Modules: PolyfillLoader, SubtleCrypto
Classes: Blob, CryptoKey, File, Function, Runnable, VM
Constant Summary
collapse
- VERSION =
"0.19.0.pre1"
Class Method Summary
collapse
Class Method Details
._apply_registered_polyfills(vm, features) ⇒ Object
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
# File 'lib/quickjs/polyfills.rb', line 30
def self._apply_registered_polyfills(vm, features)
features.each do |feature|
next unless (entry = @_polyfills[feature])
entry[:bytecode] ||= _precompile_polyfill(entry, feature)
vm.send(:_load_polyfill_bytecode, entry[:bytecode])
end
end
|
._build_import(imported) ⇒ Object
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
# File 'lib/quickjs.rb', line 73
def _build_import(imported)
code_define_global = ->(name) { "globalThis['#{name}'] = #{name};" }
case imported
in String if matched = imported.match(/\* as (.+)/)
[imported, code_define_global.call(matched[1])]
in String
[imported, code_define_global.call(imported)]
in [*all] if all.all? {|e| e.is_a? String }
[
imported.join(', ').yield_self{|s| '{ %s }' % s },
imported.map(&code_define_global).join("\n")
]
in { ** }
imports, aliases = imported.to_a.map do |imp|
["#{imp[0]} as #{imp[1]}", imp[1].to_s]
end.transpose
[
imports.join(', ').yield_self{|s| '{ %s }' % s },
aliases.map(&code_define_global).join("\n")
]
else
raise 'Unsupported importing style'
end
end
|
._polyfill_for(name) ⇒ Object
21
22
23
|
# File 'lib/quickjs/polyfills.rb', line 21
def self._polyfill_for(name)
@_polyfills[name]
end
|
._precompile_polyfill(entry, feature) ⇒ Object
Compiled once per process per polyfill on a disposable VM whose generous timeout covers parsing multi-MB bundles (FormatJS Intl is ~2 MB). The user’s per-VM ‘timeout_msec` is for their own JS — it would otherwise interrupt our infrastructure on tight defaults. `features: []` skips applying any registered polyfills to the temp VM (no recursion / no wasted polyfill loads).
51
52
53
54
55
56
|
# File 'lib/quickjs/polyfills.rb', line 51
def self._precompile_polyfill(entry, feature)
source = entry[:source]
source = source.call if source.is_a?(Proc)
combined = entry[:init] ? "#{entry[:init]}\n#{source}" : source
Quickjs.compile(combined, filename: feature.to_s, timeout_msec: 60_000, features: []).to_s
end
|
._unregister_polyfill(name) ⇒ Object
25
26
27
28
|
# File 'lib/quickjs/polyfills.rb', line 25
def self._unregister_polyfill(name)
@_polyfills.delete(name)
nil
end
|
._with_timeout(msec, proc, args) ⇒ Object
46
47
48
49
50
51
52
|
# File 'lib/quickjs.rb', line 46
def _with_timeout(msec, proc, args)
Timeout.timeout(msec / 1_000.0) { proc.call(*args) }
rescue Timeout::Error
raise Quickjs::InterruptedError.new('Ruby runtime got timeout', nil)
rescue
raise
end
|
._with_vm(on) ⇒ Object
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
# File 'lib/quickjs.rb', line 55
def _with_vm(on)
case on
when Quickjs::VM
yield on
when nil
vm = Quickjs::VM.new
yield vm
when Hash
vm = Quickjs::VM.new(**on)
yield vm
else
raise ArgumentError, 'on: must be a Quickjs::VM, a Hash of VM options, or nil'
end
ensure
vm&.dispose!
end
|
.compile(source, **opts) ⇒ Object
36
37
38
39
40
41
42
43
|
# File 'lib/quickjs.rb', line 36
def compile(source, **opts)
compile_opts = {}
compile_opts[:filename] = opts.delete(:filename) if opts.key?(:filename)
vm = Quickjs::VM.new(**opts)
vm.compile(source, **compile_opts)
ensure
vm&.dispose!
end
|
.eval_code(code, overwrite_opts = {}) ⇒ Object
25
26
27
28
29
30
31
32
33
|
# File 'lib/quickjs.rb', line 25
def eval_code(code, overwrite_opts = {})
eval_opts = {}
eval_opts[:filename] = overwrite_opts.delete(:filename) if overwrite_opts.key?(:filename)
eval_opts[:async] = overwrite_opts.delete(:async) if overwrite_opts.key?(:async)
vm = Quickjs::VM.new(**overwrite_opts)
vm.eval_code(code, **eval_opts)
ensure
vm&.dispose!
end
|
.register_polyfill(name, source:, init: nil) ⇒ Object
‘source:` accepts either a `String` (eager) or a `Proc` returning one (lazy). The lazy form lets a companion gem call `register_polyfill` at require time without paying the file-read cost unless a VM actually opts into the feature.
12
13
14
15
16
17
18
19
|
# File 'lib/quickjs/polyfills.rb', line 12
def self.register_polyfill(name, source:, init: nil)
raise ::TypeError, "name must be a Symbol, got #{name.class}" unless name.is_a?(Symbol)
raise ::TypeError, "source: must be a String or Proc, got #{source.class}" unless source.is_a?(String) || source.is_a?(Proc)
raise ::TypeError, "init: must be a String or nil, got #{init.class}" unless init.nil? || init.is_a?(String)
@_polyfills[name] = {source: source, init: init&.freeze, bytecode: nil}
nil
end
|