isomorfeus-speednode 0.3.1 → 0.4.3

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.
@@ -1,288 +1,45 @@
1
- require 'securerandom'
2
- if Gem.win_platform?
3
- require 'win32/pipe'
4
-
5
- module Win32
6
- class Pipe
7
- def write(data)
8
- bytes = FFI::MemoryPointer.new(:ulong)
9
-
10
- raise Error, "no pipe created" unless @pipe
11
-
12
- if @asynchronous
13
- bool = WriteFile(@pipe, data, data.bytesize, bytes, @overlapped)
14
- bytes_written = bytes.read_ulong
15
-
16
- if bool && bytes_written > 0
17
- @pending_io = false
18
- return true
19
- end
20
-
21
- error = GetLastError()
22
- if !bool && error == ERROR_IO_PENDING
23
- @pending_io = true
24
- return true
25
- end
26
-
27
- return false
28
- else
29
- unless WriteFile(@pipe, data, data.bytesize, bytes, nil)
30
- raise SystemCallError.new("WriteFile", FFI.errno)
31
- end
32
-
33
- return true
34
- end
35
- end
36
- end
37
- end
38
- end
39
-
40
- module Isomorfeus
41
- module Speednode
42
- class Runtime < ExecJS::Runtime
43
- class VMCommand
44
- def initialize(socket, cmd, arguments)
45
- @socket = socket
46
- @cmd = cmd
47
- @arguments = arguments
48
- end
49
-
50
- def execute
51
- result = ''
52
- message = ::Oj.dump({ 'cmd' => @cmd, 'args' => @arguments }, mode: :strict)
53
- message = message + "\x04"
54
- bytes_to_send = message.bytesize
55
- sent_bytes = 0
56
-
57
- if ExecJS.windows?
58
- @socket.write(message)
59
- begin
60
- result << @socket.read
61
- end until result.end_with?("\x04")
62
- else
63
- sent_bytes = @socket.sendmsg(message)
64
- if sent_bytes < bytes_to_send
65
- while sent_bytes < bytes_to_send
66
- sent_bytes += @socket.sendmsg(message.byteslice((sent_bytes)..-1))
67
- end
68
- end
69
-
70
- begin
71
- result << @socket.recvmsg()[0]
72
- end until result.end_with?("\x04")
73
- end
74
- ::Oj.load(result.chop!, create_additions: false)
75
- end
76
- end
77
-
78
- class VM
79
- def initialize(options)
80
- @mutex = Mutex.new
81
- @socket_path = nil
82
- @options = options
83
- @started = false
84
- @socket = nil
85
- end
86
-
87
- def started?
88
- @started
89
- end
90
-
91
- def self.finalize(socket, socket_dir, socket_path, pid)
92
- proc { exit_node(socket, socket_dir, socket_path, pid) }
93
- end
94
-
95
- def self.exit_node(socket, socket_dir, socket_path, pid)
96
- VMCommand.new(socket, "exit", [0]).execute
97
- socket.close
98
- File.unlink(socket_path)
99
- Dir.rmdir(socket_dir)
100
- Process.kill('KILL', pid)
101
- end
102
-
103
- def exec(context, source)
104
- command("exec", {'context' => context, 'source' => source})
105
- end
106
-
107
- def execp(context, source)
108
- command("execp", {'context' => context, 'source' => source})
109
- end
110
-
111
- def delete_context(context)
112
- command("deleteContext", context)
113
- end
114
-
115
- def start
116
- @mutex.synchronize do
117
- start_without_synchronization
118
- end
119
- end
120
-
121
- private
122
-
123
- def start_without_synchronization
124
- return if @started
125
- if ExecJS.windows?
126
- @socket_dir = nil
127
- @socket_path = SecureRandom.uuid
128
- else
129
- @socket_dir = Dir.mktmpdir("isomorfeus-speednode-")
130
- @socket_path = File.join(@socket_dir, "socket")
131
- end
132
- @pid = Process.spawn({"SOCKET_PATH" => @socket_path}, @options[:binary], @options[:runner_path])
133
-
134
- retries = 20
135
-
136
- if ExecJS.windows?
137
- timeout_or_connected = false
138
- begin
139
- retries -= 1
140
- begin
141
- @socket = Win32::Pipe::Client.new(@socket_path, Win32::Pipe::ACCESS_DUPLEX)
142
- rescue
143
- sleep 0.1
144
- raise "Unable to start nodejs process in time" if retries == 0
145
- next
146
- end
147
- timeout_or_connected = true
148
- end until timeout_or_connected
149
- else
150
- while !File.exist?(@socket_path)
151
- sleep 0.1
152
- retries -= 1
153
- raise "Unable to start nodejs process in time" if retries == 0
154
- end
155
-
156
- @socket = UNIXSocket.new(@socket_path)
157
- end
158
-
159
- @started = true
160
-
161
- at_exit do
162
- begin
163
- self.class.exit_node(@socket, @socket_dir, @socket_path, @pid) unless @socket.closed?
164
- rescue
165
- # do nothing
166
- end
167
- end
168
-
169
- ObjectSpace.define_finalizer(self, self.class.finalize(@socket, @socket_dir, @socket_path, @pid))
170
- end
171
-
172
- def command(cmd, *arguments)
173
- @mutex.synchronize do
174
- start_without_synchronization
175
- VMCommand.new(@socket, cmd, arguments).execute
176
- end
177
- end
178
- end
179
-
180
- class Context < ::ExecJS::Runtime::Context
181
- def initialize(runtime, source = "", options = {})
182
- @runtime = runtime
183
- @uuid = SecureRandom.uuid
184
- @permissive = !!options[:permissive]
185
-
186
- ObjectSpace.define_finalizer(self, self.class.finalize(@runtime, @uuid))
187
-
188
- begin
189
- source = encode(source)
190
- rescue
191
- source = source.force_encoding('UTF-8')
192
- end
193
-
194
- @permissive ? raw_execp(source) : raw_exec(source)
195
- end
196
-
197
- def self.finalize(runtime, uuid)
198
- proc { runtime.vm.delete_context(uuid) }
199
- end
200
-
201
- def call(identifier, *args)
202
- eval "#{identifier}.apply(this, #{::Oj.dump(args, mode: :strict)})"
203
- end
204
-
205
- def eval(source, options = {})
206
- raw_exec("(#{source})") if /\S/ =~ source
207
- end
208
-
209
- def exec(source, options = {})
210
- raw_exec("(function(){#{source}})()")
211
- end
212
-
213
- def permissive?
214
- @permissive
215
- end
216
-
217
- def permissive_eval(source, options = {})
218
- raw_execp("(#{source})") if /\S/ =~ source
219
- end
220
-
221
- def permissive_exec(source, options = {})
222
- raw_execp("(function(){#{source}})()")
223
- end
224
-
225
- def raw_exec(source)
226
- source = encode(source)
227
-
228
- result = @runtime.vm.exec(@uuid, source)
229
- extract_result(result)
230
- end
231
-
232
- def raw_execp(source)
233
- source = encode(source)
234
-
235
- result = @runtime.vm.execp(@uuid, source)
236
- extract_result(result)
237
- end
238
-
239
- protected
240
-
241
- def extract_result(output)
242
- status, value, stack = output
243
- if status == "ok"
244
- value
245
- else
246
- stack ||= ""
247
- stack = stack.split("\n").map do |line|
248
- line.sub(" at ", "").strip
249
- end
250
- stack.reject! { |line| ["eval code", "eval@[native code]"].include?(line) }
251
- stack.shift unless stack[0].to_s.include?("(execjs)")
252
- error_class = value =~ /SyntaxError:/ ? ExecJS::RuntimeError : ExecJS::ProgramError
253
- error = error_class.new(value)
254
- error.set_backtrace(stack + caller)
255
- raise error
256
- end
257
- end
258
- end
259
-
260
- attr_reader :name, :vm
261
-
262
- def initialize(options)
263
- @name = options[:name]
264
- @binary = Isomorfeus::Speednode::NodeCommand.cached(options[:command])
265
- @runner_path = options[:runner_path]
266
- @encoding = options[:encoding]
267
- @deprecated = !!options[:deprecated]
268
-
269
- @vm = VM.new(
270
- binary: @binary,
271
- runner_path: @runner_path
272
- )
273
-
274
- @popen_options = {}
275
- @popen_options[:external_encoding] = @encoding if @encoding
276
- @popen_options[:internal_encoding] = ::Encoding.default_internal || 'UTF-8'
277
- end
278
-
279
- def available?
280
- @binary ? true : false
281
- end
282
-
283
- def deprecated?
284
- @deprecated
285
- end
286
- end
287
- end
288
- end
1
+ module Isomorfeus
2
+ module Speednode
3
+ class Runtime < ExecJS::Runtime
4
+ def self.attach_proc(context_id, func, run_block)
5
+ attached_procs[context_id] = { func => run_block }
6
+ end
7
+
8
+ def self.attached_procs
9
+ @attached_procs ||= {}
10
+ end
11
+
12
+ def self.responders
13
+ @responders ||= {}
14
+ end
15
+
16
+ attr_reader :name, :vm
17
+
18
+ def initialize(options)
19
+ @name = options[:name]
20
+ @binary = Isomorfeus::Speednode::NodeCommand.cached(options[:command])
21
+ @runner_path = options[:runner_path]
22
+ @encoding = options[:encoding]
23
+ @deprecated = !!options[:deprecated]
24
+
25
+ @vm = VM.new(
26
+ binary: @binary,
27
+ source_maps: '--enable-source-maps',
28
+ runner_path: @runner_path
29
+ )
30
+
31
+ @popen_options = {}
32
+ @popen_options[:external_encoding] = @encoding if @encoding
33
+ @popen_options[:internal_encoding] = ::Encoding.default_internal || 'UTF-8'
34
+ end
35
+
36
+ def available?
37
+ @binary ? true : false
38
+ end
39
+
40
+ def deprecated?
41
+ @deprecated
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,5 +1,5 @@
1
1
  module Isomorfeus
2
2
  module Speednode
3
- VERSION = '0.3.1'
3
+ VERSION = '0.4.3'
4
4
  end
5
5
  end
@@ -1,12 +1,21 @@
1
- require 'securerandom'
2
- require 'socket'
3
- require 'oj'
4
- require 'execjs/module'
5
- require 'isomorfeus/speednode/node_command'
6
- require 'execjs/runtime'
7
- require 'isomorfeus/speednode/runtime'
8
- require "execjs/runtimes"
9
- require 'isomorfeus/execjs_runtime'
10
- require 'isomorfeus/execjs_module'
11
- require 'isomorfeus/execjs_runtimes'
12
- require 'execjs'
1
+ require 'securerandom'
2
+ require 'socket'
3
+ require 'oj'
4
+ require 'execjs/module'
5
+ require 'isomorfeus/speednode/config'
6
+ require 'isomorfeus/speednode/node_command'
7
+ require 'execjs/runtime'
8
+ if Gem.win_platform?
9
+ require 'isomorfeus/speednode/attach_pipe'
10
+ else
11
+ require 'isomorfeus/speednode/attach_socket'
12
+ end
13
+ require 'isomorfeus/speednode/runtime/vm'
14
+ require 'isomorfeus/speednode/runtime/vm_command'
15
+ require 'isomorfeus/speednode/runtime/context'
16
+ require 'isomorfeus/speednode/runtime'
17
+ require "execjs/runtimes"
18
+ require 'isomorfeus/execjs_runtime'
19
+ require 'isomorfeus/execjs_module'
20
+ require 'isomorfeus/execjs_runtimes'
21
+ require 'execjs'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: isomorfeus-speednode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Biedermann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-14 00:00:00.000000000 Z
11
+ date: 2021-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: execjs
@@ -16,40 +16,40 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.8.0
19
+ version: 2.8.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 2.8.0
26
+ version: 2.8.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: oj
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 3.11.0
33
+ version: 3.13.9
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 3.11.0
40
+ version: 3.13.9
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: win32-pipe
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: 0.4.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.4.0
55
55
  - !ruby/object:Gem::Dependency
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: uglifier
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  description: A fast ExecJS runtime based on nodejs, tuned for Isomorfeus.
98
112
  email: jan@kursator.de
99
113
  executables: []
@@ -106,9 +120,15 @@ files:
106
120
  - lib/isomorfeus/execjs_module.rb
107
121
  - lib/isomorfeus/execjs_runtime.rb
108
122
  - lib/isomorfeus/execjs_runtimes.rb
123
+ - lib/isomorfeus/speednode/attach_pipe.rb
124
+ - lib/isomorfeus/speednode/attach_socket.rb
125
+ - lib/isomorfeus/speednode/config.rb
109
126
  - lib/isomorfeus/speednode/node_command.rb
110
127
  - lib/isomorfeus/speednode/runner.js
111
128
  - lib/isomorfeus/speednode/runtime.rb
129
+ - lib/isomorfeus/speednode/runtime/context.rb
130
+ - lib/isomorfeus/speednode/runtime/vm.rb
131
+ - lib/isomorfeus/speednode/runtime/vm_command.rb
112
132
  - lib/isomorfeus/speednode/version.rb
113
133
  homepage: http://isomorfeus.com
114
134
  licenses:
@@ -130,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
150
  - !ruby/object:Gem::Version
131
151
  version: '0'
132
152
  requirements: []
133
- rubygems_version: 3.2.15
153
+ rubygems_version: 3.2.22
134
154
  signing_key:
135
155
  specification_version: 4
136
156
  summary: A fast ExecJS runtime based on nodejs, tuned for Isomorfeus.