isomorfeus-speednode 0.3.1 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.