execjs 2.7.0 → 2.9.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c281240b821b63764b2972d440a39405d77bca30
4
- data.tar.gz: f661c8d78fb1099bc3787e29c40b91b2e067be2e
2
+ SHA256:
3
+ metadata.gz: 2cff0ab13dcd1bc38d12b1ca38d99773ba123ad75573c8b8f4789232677df308
4
+ data.tar.gz: a84d80b533fa677491bdb26d28bfedd44443deb5ff772d9eeb7db7e9e0d0ab36
5
5
  SHA512:
6
- metadata.gz: d59815bb2b71498baa84e75f9ccdc5210e82a5dc474f22a1c9b749602eeee91a4e0844484e7580c05cee6dcfa94c6672b72e6e2133c23227e9d5011af3110632
7
- data.tar.gz: e38d3bfdfe65de9017d2ba829e40646c98c931d9fae56f8aa39cb345ce5da3e39a4b1c7199fa79dc89609f56d8afae24427d22ef64f67fba092456f60e8f4632
6
+ metadata.gz: fbac63f192c113786e7df0bce663a0e40a241b54534e01f18047d356d7ccb1514e4aeb8a610a336f85271def9b5956404091caccf6f0c984a20a723f67a364ce
7
+ data.tar.gz: 2f6dfe9ff9154500ea26a0c94a829eacb8b63ac84744791eff8f0b8643182f30118b1f1ed42f08486a4cc05c4e61c0cb8d800df53dcbccdbba5dadb786027b7a
data/README.md CHANGED
@@ -7,17 +7,17 @@ returns the result to you as a Ruby object.
7
7
 
8
8
  ExecJS supports these runtimes:
9
9
 
10
- * [therubyracer](https://github.com/cowboyd/therubyracer) - Google V8
11
- embedded within Ruby
12
10
  * [therubyrhino](https://github.com/cowboyd/therubyrhino) - Mozilla
13
11
  Rhino embedded within JRuby
14
12
  * [Duktape.rb](https://github.com/judofyr/duktape.rb) - Duktape JavaScript interpreter
15
13
  * [Node.js](http://nodejs.org/)
14
+ * [Bun.sh](https://bun.sh) - JavaScript runtime & toolkit designed for speed
16
15
  * Apple JavaScriptCore - Included with Mac OS X
17
16
  * [Microsoft Windows Script Host](http://msdn.microsoft.com/en-us/library/9bbdkx3k.aspx) (JScript)
18
17
  * [Google V8](http://code.google.com/p/v8/)
19
- * [mini_racer](https://github.com/discourse/mini_racer) - Google V8
18
+ * [mini_racer](https://github.com/rubyjs/mini_racer) - Google V8
20
19
  embedded within Ruby
20
+ * [GraalVM JavaScript](https://www.graalvm.org/javascript/) - used on TruffleRuby
21
21
 
22
22
  A short example:
23
23
 
@@ -39,6 +39,22 @@ context.call("CoffeeScript.compile", "square = (x) -> x * x", bare: true)
39
39
  # => "var square;\nsquare = function(x) {\n return x * x;\n};"
40
40
  ```
41
41
 
42
+ # Forcing a specific runtime
43
+
44
+ If you'd like to use a specific runtime rather than the autodected one, you can assign `ExecJS.runtime`:
45
+
46
+ ```ruby
47
+ ExecJS.runtime = ExecJS::Runtimes::Node
48
+ ```
49
+
50
+ Alternatively, you can define it via the `EXECJS_RUNTIME` environment variable:
51
+
52
+ ```bash
53
+ EXECJS_RUNTIME=Node ruby ...
54
+ ```
55
+
56
+ You can find the list of possible runtimes in [`lib/execjs/runtimes.rb`](https://github.com/rails/execjs/blob/master/lib/execjs/runtimes.rb).
57
+
42
58
  # Installation
43
59
 
44
60
  ```
@@ -76,7 +92,7 @@ You shouldn't use `ExecJS.eval` on any inputs you wouldn't feel comfortable Ruby
76
92
 
77
93
  ## Contributing to ExecJS
78
94
 
79
- ExecJS is work of hundreds of contributors. You're encouraged to submit pull requests, propose
95
+ ExecJS is work of dozens of contributors. You're encouraged to submit pull requests, propose
80
96
  features and discuss issues.
81
97
 
82
98
  See [CONTRIBUTING](CONTRIBUTING.md).
@@ -6,27 +6,28 @@ module ExecJS
6
6
  class Context < Runtime::Context
7
7
  def initialize(runtime, source = "", options = {})
8
8
  @ctx = Duktape::Context.new(complex_object: nil)
9
- @ctx.exec_string(encode(source), '(execjs)')
9
+ @ctx.exec_string(source.encode(Encoding::UTF_8), '(execjs)')
10
10
  rescue Exception => e
11
11
  raise wrap_error(e)
12
12
  end
13
13
 
14
14
  def exec(source, options = {})
15
15
  return unless /\S/ =~ source
16
- @ctx.eval_string("(function(){#{encode(source)}})()", '(execjs)')
16
+ @ctx.eval_string("(function(){#{source.encode(Encoding::UTF_8)}})()", '(execjs)')
17
17
  rescue Exception => e
18
18
  raise wrap_error(e)
19
19
  end
20
20
 
21
21
  def eval(source, options = {})
22
22
  return unless /\S/ =~ source
23
- @ctx.eval_string("(#{encode(source)})", '(execjs)')
23
+ @ctx.eval_string("(#{source.encode(Encoding::UTF_8)})", '(execjs)')
24
24
  rescue Exception => e
25
25
  raise wrap_error(e)
26
26
  end
27
27
 
28
28
  def call(identifier, *args)
29
- @ctx.call_prop(identifier.split("."), *args)
29
+ @ctx.exec_string("__execjs_duktape_call = #{identifier}", '(execjs)')
30
+ @ctx.call_prop("__execjs_duktape_call", *args)
30
31
  rescue Exception => e
31
32
  raise wrap_error(e)
32
33
  end
@@ -1,11 +1,12 @@
1
- require "tmpdir"
2
1
  require "execjs/runtime"
2
+ require "tmpdir"
3
+ require "json"
3
4
 
4
5
  module ExecJS
5
6
  class ExternalRuntime < Runtime
6
7
  class Context < Runtime::Context
7
8
  def initialize(runtime, source = "", options = {})
8
- source = encode(source)
9
+ source = source.encode(Encoding::UTF_8)
9
10
 
10
11
  @runtime = runtime
11
12
  @source = source
@@ -15,7 +16,7 @@ module ExecJS
15
16
  end
16
17
 
17
18
  def eval(source, options = {})
18
- source = encode(source)
19
+ source = source.encode(Encoding::UTF_8)
19
20
 
20
21
  if /\S/ =~ source
21
22
  exec("return eval(#{::JSON.generate("(#{source})", quirks_mode: true)})")
@@ -23,7 +24,7 @@ module ExecJS
23
24
  end
24
25
 
25
26
  def exec(source, options = {})
26
- source = encode(source)
27
+ source = source.encode(Encoding::UTF_8)
27
28
  source = "#{@source}\n#{source}" if @source != ""
28
29
  source = @runtime.compile_source(source)
29
30
 
@@ -77,7 +78,7 @@ module ExecJS
77
78
  .sub(filename, "(execjs)")
78
79
  .strip
79
80
  end
80
- stack.reject! { |line| ["eval code", "eval@[native code]"].include?(line) }
81
+ stack.reject! { |line| ["eval code", "eval code@", "eval@[native code]"].include?(line) }
81
82
  stack.shift unless stack[0].to_s.include?("(execjs)")
82
83
  error_class = value =~ /SyntaxError:/ ? RuntimeError : ProgramError
83
84
  error = error_class.new(value)
@@ -102,7 +103,13 @@ module ExecJS
102
103
  @popen_options[:internal_encoding] = ::Encoding.default_internal || 'UTF-8'
103
104
 
104
105
  if @runner_path
105
- instance_eval generate_compile_method(@runner_path)
106
+ instance_eval <<~RUBY, __FILE__, __LINE__
107
+ def compile_source(source)
108
+ <<-RUNNER
109
+ #{IO.read(@runner_path)}
110
+ RUNNER
111
+ end
112
+ RUBY
106
113
  end
107
114
  end
108
115
 
@@ -142,15 +149,6 @@ module ExecJS
142
149
  end
143
150
 
144
151
  protected
145
- def generate_compile_method(path)
146
- <<-RUBY
147
- def compile_source(source)
148
- <<-RUNNER
149
- #{IO.read(path)}
150
- RUNNER
151
- end
152
- RUBY
153
- end
154
152
 
155
153
  def json2_source
156
154
  @json2_source ||= IO.read(ExecJS.root + "/support/json2.js")
@@ -173,7 +171,7 @@ module ExecJS
173
171
  begin
174
172
  command = binary.split(" ") << filename
175
173
  `#{shell_escape(*command)} 2>&1 > #{path}`
176
- output = File.open(path, 'rb', @popen_options) { |f| f.read }
174
+ output = File.open(path, 'rb', **@popen_options) { |f| f.read }
177
175
  ensure
178
176
  File.unlink(path) if path
179
177
  end
@@ -196,8 +194,8 @@ module ExecJS
196
194
  require 'shellwords'
197
195
 
198
196
  def exec_runtime(filename)
199
- command = "#{Shellwords.join(binary.split(' ') << filename)} 2>&1"
200
- io = IO.popen(command, @popen_options)
197
+ command = "#{Shellwords.join(binary.split(' ') << filename)}"
198
+ io = IO.popen(command, **@popen_options)
201
199
  output = io.read
202
200
  io.close
203
201
 
@@ -209,7 +207,7 @@ module ExecJS
209
207
  end
210
208
  else
211
209
  def exec_runtime(filename)
212
- io = IO.popen(binary.split(' ') << filename, @popen_options.merge({err: [:child, :out]}))
210
+ io = IO.popen(binary.split(' ') << filename, **@popen_options)
213
211
  output = io.read
214
212
  io.close
215
213
 
@@ -0,0 +1,147 @@
1
+ require "execjs/runtime"
2
+
3
+ module ExecJS
4
+ class GraalJSRuntime < Runtime
5
+ class Context < Runtime::Context
6
+ def initialize(runtime, source = "", options = {})
7
+ @context = Polyglot::InnerContext.new
8
+ @context.eval('js', 'delete this.console')
9
+ @js_object = @context.eval('js', 'Object')
10
+
11
+ source = source.encode(Encoding::UTF_8)
12
+ unless source.empty?
13
+ translate do
14
+ eval_in_context(source)
15
+ end
16
+ end
17
+ end
18
+
19
+ def exec(source, options = {})
20
+ source = source.encode(Encoding::UTF_8)
21
+ source = "(function(){#{source}})()" if /\S/.match?(source)
22
+
23
+ translate do
24
+ eval_in_context(source)
25
+ end
26
+ end
27
+
28
+ def eval(source, options = {})
29
+ source = source.encode(Encoding::UTF_8)
30
+ source = "(#{source})" if /\S/.match?(source)
31
+
32
+ translate do
33
+ eval_in_context(source)
34
+ end
35
+ end
36
+
37
+ def call(source, *args)
38
+ source = source.encode(Encoding::UTF_8)
39
+ source = "(#{source})" if /\S/.match?(source)
40
+
41
+ translate do
42
+ function = eval_in_context(source)
43
+ function.call(*convert_ruby_to_js(args))
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ ForeignException = defined?(Polyglot::ForeignException) ? Polyglot::ForeignException : ::RuntimeError
50
+
51
+ def translate
52
+ convert_js_to_ruby yield
53
+ rescue ForeignException => e
54
+ if e.message && e.message.start_with?('SyntaxError:')
55
+ error_class = ExecJS::RuntimeError
56
+ else
57
+ error_class = ExecJS::ProgramError
58
+ end
59
+
60
+ backtrace = (e.backtrace || []).map { |line| line.sub('(eval)', '(execjs)') }
61
+ raise error_class, e.message, backtrace
62
+ end
63
+
64
+ def convert_js_to_ruby(value)
65
+ case value
66
+ when true, false, Integer, Float
67
+ value
68
+ else
69
+ if value.nil?
70
+ nil
71
+ elsif value.respond_to?(:call)
72
+ nil
73
+ elsif value.respond_to?(:to_str)
74
+ value.to_str
75
+ elsif value.respond_to?(:to_ary)
76
+ value.to_ary.map do |e|
77
+ if e.respond_to?(:call)
78
+ nil
79
+ else
80
+ convert_js_to_ruby(e)
81
+ end
82
+ end
83
+ else
84
+ object = value
85
+ h = {}
86
+ object.instance_variables.each do |member|
87
+ v = object[member]
88
+ unless v.respond_to?(:call)
89
+ h[member.to_s] = convert_js_to_ruby(v)
90
+ end
91
+ end
92
+ h
93
+ end
94
+ end
95
+ end
96
+
97
+ def convert_ruby_to_js(value)
98
+ case value
99
+ when nil, true, false, Integer, Float
100
+ value
101
+ when String, Symbol
102
+ Truffle::Interop.as_truffle_string value
103
+ when Array
104
+ value.map { |e| convert_ruby_to_js(e) }
105
+ when Hash
106
+ h = @js_object.new
107
+ value.each_pair do |k,v|
108
+ h[convert_ruby_to_js(k)] = convert_ruby_to_js(v)
109
+ end
110
+ h
111
+ else
112
+ raise TypeError, "Unknown how to convert to JS: #{value.inspect}"
113
+ end
114
+ end
115
+
116
+ class_eval <<-'RUBY', "(execjs)", 1
117
+ def eval_in_context(code); @context.eval('js', code); end
118
+ RUBY
119
+ end
120
+
121
+ def name
122
+ "GraalVM (Graal.js)"
123
+ end
124
+
125
+ def available?
126
+ return @available if defined?(@available)
127
+
128
+ unless RUBY_ENGINE == "truffleruby"
129
+ return @available = false
130
+ end
131
+
132
+ unless defined?(Polyglot::InnerContext)
133
+ warn "TruffleRuby #{RUBY_ENGINE_VERSION} does not have support for inner contexts, use a more recent version", uplevel: 0 if $VERBOSE
134
+ return @available = false
135
+ end
136
+
137
+ unless Polyglot.languages.include? "js"
138
+ warn "The language 'js' is not available, you likely need to `export TRUFFLERUBYOPT='--jvm --polyglot'`", uplevel: 0 if $VERBOSE
139
+ warn "You also need to install the 'js' component with 'gu install js' on GraalVM 22.2+", uplevel: 0 if $VERBOSE
140
+ warn "Note that you need TruffleRuby+GraalVM and not just the TruffleRuby standalone to use #{self.class}", uplevel: 0 if $VERBOSE
141
+ return @available = false
142
+ end
143
+
144
+ @available = true
145
+ end
146
+ end
147
+ end
@@ -4,15 +4,16 @@ module ExecJS
4
4
  class MiniRacerRuntime < Runtime
5
5
  class Context < Runtime::Context
6
6
  def initialize(runtime, source = "", options={})
7
- source = encode(source)
7
+ source = source.encode(Encoding::UTF_8)
8
8
  @context = ::MiniRacer::Context.new
9
+ @context.eval("delete this.console");
9
10
  translate do
10
11
  @context.eval(source)
11
12
  end
12
13
  end
13
14
 
14
15
  def exec(source, options = {})
15
- source = encode(source)
16
+ source = source.encode(Encoding::UTF_8)
16
17
 
17
18
  if /\S/ =~ source
18
19
  eval "(function(){#{source}})()"
@@ -20,7 +21,7 @@ module ExecJS
20
21
  end
21
22
 
22
23
  def eval(source, options = {})
23
- source = encode(source)
24
+ source = source.encode(Encoding::UTF_8)
24
25
 
25
26
  if /\S/ =~ source
26
27
  translate do
@@ -1,10 +1,11 @@
1
1
  require "execjs/runtime"
2
+ require "json"
2
3
 
3
4
  module ExecJS
4
5
  class RubyRhinoRuntime < Runtime
5
6
  class Context < Runtime::Context
6
7
  def initialize(runtime, source = "", options = {})
7
- source = encode(source)
8
+ source = source.encode(Encoding::UTF_8)
8
9
 
9
10
  @rhino_context = ::Rhino::Context.new
10
11
  fix_memory_limit! @rhino_context
@@ -14,7 +15,7 @@ module ExecJS
14
15
  end
15
16
 
16
17
  def exec(source, options = {})
17
- source = encode(source)
18
+ source = source.encode(Encoding::UTF_8)
18
19
 
19
20
  if /\S/ =~ source
20
21
  eval "(function(){#{source}})()", options
@@ -22,7 +23,7 @@ module ExecJS
22
23
  end
23
24
 
24
25
  def eval(source, options = {})
25
- source = encode(source)
26
+ source = source.encode(Encoding::UTF_8)
26
27
 
27
28
  if /\S/ =~ source
28
29
  unbox @rhino_context.eval("(#{source})")
@@ -32,7 +33,11 @@ module ExecJS
32
33
  end
33
34
 
34
35
  def call(properties, *args)
35
- unbox @rhino_context.eval(properties).call(*args)
36
+ # Might no longer be necessary if therubyrhino handles Symbols directly:
37
+ # https://github.com/rubyjs/therubyrhino/issues/43
38
+ converted_args = JSON.parse(JSON.generate(args), create_additions: false)
39
+
40
+ unbox @rhino_context.eval(properties).call(*converted_args)
36
41
  rescue Exception => e
37
42
  raise wrap_error(e)
38
43
  end
@@ -1,23 +1,34 @@
1
- require "execjs/encoding"
2
-
3
1
  module ExecJS
4
2
  # Abstract base class for runtimes
5
3
  class Runtime
6
4
  class Context
7
- include Encoding
8
-
9
5
  def initialize(runtime, source = "", options = {})
10
6
  end
11
7
 
8
+ # Evaluates the +source+ in the context of a function body and returns the
9
+ # returned value.
10
+ #
11
+ # context.exec("return 1") # => 1
12
+ # context.exec("1") # => nil (nothing was returned)
12
13
  def exec(source, options = {})
13
14
  raise NotImplementedError
14
15
  end
15
16
 
17
+ # Evaluates the +source+ as an expression and returns the result.
18
+ #
19
+ # context.eval("1") # => 1
20
+ # context.eval("return 1") # => Raises SyntaxError
16
21
  def eval(source, options = {})
17
22
  raise NotImplementedError
18
23
  end
19
24
 
20
- def call(properties, *args)
25
+ # Evaluates +source+ as an expression (which should be of type
26
+ # +function+), and calls the function with the given arguments.
27
+ # The function will be evaluated with the global object as +this+.
28
+ #
29
+ # context.call("function(a, b) { return a + b }", 1, 1) # => 2
30
+ # context.call("CoffeeScript.compile", "1 + 1")
31
+ def call(source, *args)
21
32
  raise NotImplementedError
22
33
  end
23
34
  end
@@ -2,9 +2,9 @@ require "execjs/module"
2
2
  require "execjs/disabled_runtime"
3
3
  require "execjs/duktape_runtime"
4
4
  require "execjs/external_runtime"
5
- require "execjs/ruby_racer_runtime"
6
5
  require "execjs/ruby_rhino_runtime"
7
6
  require "execjs/mini_racer_runtime"
7
+ require "execjs/graaljs_runtime"
8
8
 
9
9
  module ExecJS
10
10
  module Runtimes
@@ -12,22 +12,32 @@ module ExecJS
12
12
 
13
13
  Duktape = DuktapeRuntime.new
14
14
 
15
- RubyRacer = RubyRacerRuntime.new
16
-
17
15
  RubyRhino = RubyRhinoRuntime.new
18
16
 
17
+ GraalJS = GraalJSRuntime.new
18
+
19
19
  MiniRacer = MiniRacerRuntime.new
20
20
 
21
21
  Node = ExternalRuntime.new(
22
22
  name: "Node.js (V8)",
23
- command: ["nodejs", "node"],
23
+ command: ["node", "nodejs"],
24
24
  runner_path: ExecJS.root + "/support/node_runner.js",
25
25
  encoding: 'UTF-8'
26
26
  )
27
27
 
28
+ Bun = ExternalRuntime.new(
29
+ name: "Bun.sh",
30
+ command: ["bun"],
31
+ runner_path: ExecJS.root + "/support/bun_runner.js",
32
+ encoding: 'UTF-8'
33
+ )
34
+
28
35
  JavaScriptCore = ExternalRuntime.new(
29
36
  name: "JavaScriptCore",
30
- command: "/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc",
37
+ command: [
38
+ "/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc",
39
+ "/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc",
40
+ ],
31
41
  runner_path: ExecJS.root + "/support/jsc_runner.js"
32
42
  )
33
43
 
@@ -64,7 +74,9 @@ module ExecJS
64
74
  end
65
75
 
66
76
  def self.from_environment
67
- if name = ENV["EXECJS_RUNTIME"]
77
+ env = ENV["EXECJS_RUNTIME"]
78
+ if env && !env.empty?
79
+ name = env
68
80
  raise RuntimeUnavailable, "#{name} runtime is not defined" unless const_defined?(name)
69
81
  runtime = const_get(name)
70
82
 
@@ -79,10 +91,11 @@ module ExecJS
79
91
 
80
92
  def self.runtimes
81
93
  @runtimes ||= [
82
- RubyRacer,
83
94
  RubyRhino,
95
+ GraalJS,
84
96
  Duktape,
85
97
  MiniRacer,
98
+ Bun,
86
99
  Node,
87
100
  JavaScriptCore,
88
101
  SpiderMonkey,
@@ -0,0 +1,29 @@
1
+ (function(program, execJS) { (function() {execJS(program) }).call({}); })(function(self, global, process, module, exports, require, console, setTimeout, setInterval, clearTimeout, clearInterval, setImmediate, clearImmediate) { #{source}
2
+ }, function(program) {
3
+ // Force BunJS to use sloppy mode see https://github.com/oven-sh/bun/issues/4527#issuecomment-1709520894
4
+ exports.abc = function(){}
5
+ var __process__ = process;
6
+ var printFinal = function(string) {
7
+ process.stdout.write('' + string, function() {
8
+ __process__.exit(0);
9
+ });
10
+ };
11
+ try {
12
+ delete this.process;
13
+ delete this.console;
14
+ result = program();
15
+ process = __process__;
16
+ if (typeof result == 'undefined' && result !== null) {
17
+ printFinal('["ok"]');
18
+ } else {
19
+ try {
20
+ printFinal(JSON.stringify(['ok', result]));
21
+ } catch (err) {
22
+ printFinal(JSON.stringify(['err', '' + err, err.stack]));
23
+ }
24
+ }
25
+ } catch (err) {
26
+ process = __process__;
27
+ printFinal(JSON.stringify(['err', '' + err, err.stack]));
28
+ }
29
+ });
@@ -2,6 +2,14 @@
2
2
  }, function(program) {
3
3
  var output;
4
4
  try {
5
+ delete this.console;
6
+ delete this.setTimeout;
7
+ delete this.setInterval;
8
+ delete this.clearTimeout;
9
+ delete this.clearInterval;
10
+ delete this.setImmediate;
11
+ delete this.clearImmediate;
12
+
5
13
  result = program();
6
14
  if (typeof result == 'undefined' && result !== null) {
7
15
  print('["ok"]');
@@ -1,20 +1,34 @@
1
- (function(program, execJS) { execJS(program) })(function(global, module, exports, require, console, setTimeout, setInterval, clearTimeout, clearInterval, setImmediate, clearImmediate) { #{source}
1
+ (function(program, execJS) { execJS(program) })(function(global, process, module, exports, require, console, setTimeout, setInterval, clearTimeout, clearInterval, setImmediate, clearImmediate) { #{source}
2
2
  }, function(program) {
3
- var output, print = function(string) {
4
- process.stdout.write('' + string);
3
+ var __process__ = process;
4
+
5
+ var printFinal = function(string) {
6
+ process.stdout.write('' + string, function() {
7
+ __process__.exit(0);
8
+ });
5
9
  };
6
10
  try {
11
+ delete this.process;
12
+ delete this.console;
13
+ delete this.setTimeout;
14
+ delete this.setInterval;
15
+ delete this.clearTimeout;
16
+ delete this.clearInterval;
17
+ delete this.setImmediate;
18
+ delete this.clearImmediate;
7
19
  result = program();
20
+ this.process = __process__;
8
21
  if (typeof result == 'undefined' && result !== null) {
9
- print('["ok"]');
22
+ printFinal('["ok"]');
10
23
  } else {
11
24
  try {
12
- print(JSON.stringify(['ok', result]));
25
+ printFinal(JSON.stringify(['ok', result]));
13
26
  } catch (err) {
14
- print(JSON.stringify(['err', '' + err, err.stack]));
27
+ printFinal(JSON.stringify(['err', '' + err, err.stack]));
15
28
  }
16
29
  }
17
30
  } catch (err) {
18
- print(JSON.stringify(['err', '' + err, err.stack]));
31
+ this.process = __process__;
32
+ printFinal(JSON.stringify(['err', '' + err, err.stack]));
19
33
  }
20
34
  });
@@ -1,7 +1,14 @@
1
- (function(program, execJS) { execJS(program) })(function() { #{source}
1
+ (function(program, execJS) { execJS(program) })(function(console, setTimeout, setInterval, clearTimeout, clearInterval, setImmediate, clearImmediate) { #{source}
2
2
  }, function(program) {
3
3
  var output;
4
4
  try {
5
+ delete this.console;
6
+ delete this.setTimeout;
7
+ delete this.setInterval;
8
+ delete this.clearTimeout;
9
+ delete this.clearInterval;
10
+ delete this.setImmediate;
11
+ delete this.clearImmediate;
5
12
  result = program();
6
13
  if (typeof result == 'undefined' && result !== null) {
7
14
  print('["ok"]');
@@ -1,3 +1,3 @@
1
1
  module ExecJS
2
- VERSION = "2.7.0"
2
+ VERSION = "2.9.1"
3
3
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: execjs
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.0
4
+ version: 2.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Stephenson
8
8
  - Josh Peek
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-05-20 00:00:00.000000000 Z
12
+ date: 2023-09-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -38,14 +38,14 @@ files:
38
38
  - lib/execjs.rb
39
39
  - lib/execjs/disabled_runtime.rb
40
40
  - lib/execjs/duktape_runtime.rb
41
- - lib/execjs/encoding.rb
42
41
  - lib/execjs/external_runtime.rb
42
+ - lib/execjs/graaljs_runtime.rb
43
43
  - lib/execjs/mini_racer_runtime.rb
44
44
  - lib/execjs/module.rb
45
- - lib/execjs/ruby_racer_runtime.rb
46
45
  - lib/execjs/ruby_rhino_runtime.rb
47
46
  - lib/execjs/runtime.rb
48
47
  - lib/execjs/runtimes.rb
48
+ - lib/execjs/support/bun_runner.js
49
49
  - lib/execjs/support/jsc_runner.js
50
50
  - lib/execjs/support/jscript_runner.js
51
51
  - lib/execjs/support/json2.js
@@ -57,7 +57,7 @@ homepage: https://github.com/rails/execjs
57
57
  licenses:
58
58
  - MIT
59
59
  metadata: {}
60
- post_install_message:
60
+ post_install_message:
61
61
  rdoc_options: []
62
62
  require_paths:
63
63
  - lib
@@ -65,16 +65,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: 1.9.3
68
+ version: 2.5.0
69
69
  required_rubygems_version: !ruby/object:Gem::Requirement
70
70
  requirements:
71
71
  - - ">="
72
72
  - !ruby/object:Gem::Version
73
73
  version: '0'
74
74
  requirements: []
75
- rubyforge_project:
76
- rubygems_version: 2.5.1
77
- signing_key:
75
+ rubygems_version: 3.3.7
76
+ signing_key:
78
77
  specification_version: 4
79
78
  summary: Run JavaScript code from Ruby
80
79
  test_files: []
@@ -1,26 +0,0 @@
1
- module ExecJS
2
- # Encodes strings as UTF-8
3
- module Encoding
4
- if RUBY_ENGINE == 'jruby' || RUBY_ENGINE == 'rbx'
5
- # workaround for jruby bug http://jira.codehaus.org/browse/JRUBY-6588
6
- # workaround for rbx bug https://github.com/rubinius/rubinius/issues/1729
7
- def encode(string)
8
- if string.encoding.name == 'ASCII-8BIT'
9
- data = string.dup
10
- data.force_encoding('UTF-8')
11
-
12
- unless data.valid_encoding?
13
- raise ::Encoding::UndefinedConversionError, "Could not encode ASCII-8BIT data #{string.dump} as UTF-8"
14
- end
15
- else
16
- data = string.encode('UTF-8')
17
- end
18
- data
19
- end
20
- else
21
- def encode(string)
22
- string.encode('UTF-8')
23
- end
24
- end
25
- end
26
- end
@@ -1,114 +0,0 @@
1
- require "execjs/runtime"
2
-
3
- module ExecJS
4
- class RubyRacerRuntime < Runtime
5
- class Context < Runtime::Context
6
- def initialize(runtime, source = "", options = {})
7
- source = encode(source)
8
-
9
- lock do
10
- @v8_context = ::V8::Context.new
11
-
12
- begin
13
- @v8_context.eval(source)
14
- rescue ::V8::JSError => e
15
- raise wrap_error(e)
16
- end
17
- end
18
- end
19
-
20
- def exec(source, options = {})
21
- source = encode(source)
22
-
23
- if /\S/ =~ source
24
- eval "(function(){#{source}})()", options
25
- end
26
- end
27
-
28
- def eval(source, options = {})
29
- source = encode(source)
30
-
31
- if /\S/ =~ source
32
- lock do
33
- begin
34
- unbox @v8_context.eval("(#{source})")
35
- rescue ::V8::JSError => e
36
- raise wrap_error(e)
37
- end
38
- end
39
- end
40
- end
41
-
42
- def call(properties, *args)
43
- lock do
44
- begin
45
- unbox @v8_context.eval(properties).call(*args)
46
- rescue ::V8::JSError => e
47
- raise wrap_error(e)
48
- end
49
- end
50
- end
51
-
52
- def unbox(value)
53
- case value
54
- when ::V8::Function
55
- nil
56
- when ::V8::Array
57
- value.map { |v| unbox(v) }
58
- when ::V8::Object
59
- value.inject({}) do |vs, (k, v)|
60
- vs[k] = unbox(v) unless v.is_a?(::V8::Function)
61
- vs
62
- end
63
- when String
64
- value.force_encoding('UTF-8')
65
- else
66
- value
67
- end
68
- end
69
-
70
- private
71
- def lock
72
- result, exception = nil, nil
73
- V8::C::Locker() do
74
- begin
75
- result = yield
76
- rescue Exception => e
77
- exception = e
78
- end
79
- end
80
-
81
- if exception
82
- raise exception
83
- else
84
- result
85
- end
86
- end
87
-
88
- def wrap_error(e)
89
- error_class = e.value["name"] == "SyntaxError" ? RuntimeError : ProgramError
90
-
91
- stack = e.value["stack"] || ""
92
- stack = stack.split("\n")
93
- stack.shift
94
- stack = [e.message[/<eval>:\d+:\d+/, 0]].compact if stack.empty?
95
- stack = stack.map { |line| line.sub(" at ", "").sub("<eval>", "(execjs)").strip }
96
-
97
- error = error_class.new(e.value.to_s)
98
- error.set_backtrace(stack + caller)
99
- error
100
- end
101
- end
102
-
103
- def name
104
- "therubyracer (V8)"
105
- end
106
-
107
- def available?
108
- require "v8"
109
- true
110
- rescue LoadError
111
- false
112
- end
113
- end
114
- end