isomorfeus-speednode 0.6.3 → 0.7.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b3ece9e49e7a5105aef77b28b04445e4d39e2f22d061bfd1f03e43a79e403eb
4
- data.tar.gz: e3d57e156c9d1efa686a18ae784125cc8c9d553e9946cabfd0c1325f20a959f0
3
+ metadata.gz: 91aa4cb54a3cb13afcf15476f841f711ce8de37c0573dfcdbd535aeda3a5dcbd
4
+ data.tar.gz: 4f1f9ccd06769d21ea4f25171cf128a69d8e4ea942f4417b10413f0df830b944
5
5
  SHA512:
6
- metadata.gz: 67a6b031a66b5b29a9db16924087dc013a4c0ce360edbc8c4db3c076766c6c31d00783472a7b6f4d6bde526c61602ff1a78cc4e343c142016ef183005dcb339c
7
- data.tar.gz: c4600a01abe22631455c4dce5209f656409a7931b5295116a551420c03c78906b3d6733afac90ebc87ce3835c9af2228b35c1e3bdb86296dc5aac2ce93b4ecdd
6
+ metadata.gz: ae92dbfa6c44909c8d9b27392cab6ae86854d25343074441b5b5657c54d36bbc5bf332b19c25fd9694f2a58d75abfdc859982cf79a08a7128916943e40c04ae3
7
+ data.tar.gz: b68a5bd5ebc54b333c67918f6a0a51f8fe871d5607c6b36b987163dd195243b1cb21181e4f52f714528b381ea7a81f43160b5327ddbf4380472cfc58daece9f2
data/README.md CHANGED
@@ -53,6 +53,13 @@ Evaluation in a permissive context:
53
53
  ExecJS.permissive_eval('1+1')
54
54
  ```
55
55
 
56
+ #### Stopping Contexts
57
+ Contexts can be stopped programmatically. If all contexts of a VM are stopped, the VM itself will be shut down with Node exiting, freeing memory and resources.
58
+ ```ruby
59
+ context = ExecJS.compile('Test = "test"') # will start a node process
60
+ ExecJS::Runtimes::Speednode.stop_context(context) # will kill the node process
61
+ ```
62
+
56
63
  ### Precompiling and Storing scripts for repeated execution
57
64
 
58
65
  Scripts can be precompiled and stored for repeated execution, which leads to a significant performance improvement, especially for larger scripts:
@@ -309,7 +309,7 @@ let commands = {
309
309
  deleteContext: function(uuid) {
310
310
  delete contexts[uuid];
311
311
  delete scripts[uuid]
312
- return [1];
312
+ return ['ok', Object.keys(contexts).length];
313
313
  },
314
314
  exit: function(code) {
315
315
  process_exit = code;
@@ -4,22 +4,20 @@ module Isomorfeus
4
4
  class Context < ::ExecJS::Runtime::Context
5
5
  def self.finalize(runtime, uuid)
6
6
  proc do
7
- runtime.vm.delete_context(uuid) rescue nil # if delete_context fails, the vm exited before probably
7
+ runtime.unregister_context(uuid)
8
8
  end
9
9
  end
10
10
 
11
11
  def initialize(runtime, source = "", options = {})
12
12
  @runtime = runtime
13
13
  @uuid = SecureRandom.uuid
14
+ @runtime.register_context(@uuid, self)
14
15
  @permissive = !!options.delete(:permissive)
15
16
  @debug = @permissive ? !!options.delete(:debug) { false } : false
16
17
  @debug = false unless ENV['NODE_OPTIONS']&.include?('--inspect')
17
18
  @vm = @runtime.vm
18
- @context = nil
19
19
  @timeout = options[:timeout] ? options[:timeout]/1000 : 600
20
-
21
- ObjectSpace.define_finalizer(self, self.class.finalize(@runtime, @uuid))
22
-
20
+
23
21
  filename = options.delete(:filename)
24
22
  source = File.read(filename) if filename
25
23
 
@@ -28,6 +26,9 @@ module Isomorfeus
28
26
  rescue
29
27
  source = source.force_encoding('UTF-8')
30
28
  end
29
+
30
+ ObjectSpace.define_finalizer(self, self.class.finalize(@runtime, @uuid))
31
+
31
32
  if @debug && @permissive
32
33
  raw_created(source, options)
33
34
  elsif @permissive
@@ -35,7 +36,8 @@ module Isomorfeus
35
36
  else
36
37
  raw_create(source, options)
37
38
  end
38
- self.add_script(key: :_internal_exec_fin, source: '!global.__LastExecutionFinished')
39
+
40
+ add_script(key: :_internal_exec_fin, source: '!global.__LastExecutionFinished')
39
41
  end
40
42
 
41
43
  # def options
@@ -104,6 +106,10 @@ module Isomorfeus
104
106
  raw_exec("(function(){#{source}})()")
105
107
  end
106
108
 
109
+ def stop
110
+ @runtime.unregister_context(@uuid)
111
+ end
112
+
107
113
  protected
108
114
 
109
115
  def raw_bench(source)
@@ -119,26 +125,20 @@ module Isomorfeus
119
125
  end
120
126
 
121
127
  def raw_create(source, options)
122
- return if @context
123
128
  source = encode(source)
124
129
  result = @vm.create(@uuid, source, options)
125
- @context = true
126
130
  extract_result(result)
127
131
  end
128
132
 
129
133
  def raw_created(source, options)
130
- return if @context
131
134
  source = encode(source)
132
135
  result = @vm.created(@uuid, source, options)
133
- @context = true
134
136
  extract_result(result)
135
137
  end
136
138
 
137
139
  def raw_createp(source, options)
138
- return if @context
139
140
  source = encode(source)
140
141
  result = @vm.createp(@uuid, source, options)
141
- @context = true
142
142
  extract_result(result)
143
143
  end
144
144
 
@@ -41,20 +41,6 @@ module Isomorfeus
41
41
  module Speednode
42
42
  class Runtime < ExecJS::Runtime
43
43
  class VM
44
- attr_reader :responder
45
-
46
- def initialize(options)
47
- @mutex = ::Thread::Mutex.new
48
- @socket_path = nil
49
- @options = options
50
- @started = false
51
- @socket = nil
52
- end
53
-
54
- def started?
55
- @started
56
- end
57
-
58
44
  def self.finalize(socket, socket_dir, socket_path, pid)
59
45
  proc do
60
46
  Isomorfeus::Speednode::Runtime.responders[socket_path].kill if Isomorfeus::Speednode::Runtime.responders[socket_path]
@@ -79,6 +65,20 @@ module Isomorfeus
79
65
  nil
80
66
  end
81
67
 
68
+ attr_reader :responder
69
+
70
+ def initialize(options)
71
+ @mutex = ::Thread::Mutex.new
72
+ @socket_path = nil
73
+ @options = options
74
+ @started = false
75
+ @socket = nil
76
+ end
77
+
78
+ def started?
79
+ @started
80
+ end
81
+
82
82
  def evsc(context, key)
83
83
  command('evsc', { 'context' => context, 'key' => key })
84
84
  end
@@ -134,6 +134,16 @@ module Isomorfeus
134
134
  end
135
135
  end
136
136
 
137
+ def stop
138
+ return unless @started
139
+ @mutex.synchronize do
140
+ self.class.exit_node(@socket, @socket_dir, @socket_path, @pid)
141
+ @socket_path = nil
142
+ @started = false
143
+ @socket = nil
144
+ end
145
+ end
146
+
137
147
  private
138
148
 
139
149
  def start_without_synchronization
@@ -19,14 +19,30 @@ module Isomorfeus
19
19
  @name = options[:name]
20
20
  @binary = Isomorfeus::Speednode::NodeCommand.cached(options[:command])
21
21
  @runner_path = options[:runner_path]
22
+ @vm = VM.new(binary: @binary, source_maps: '--enable-source-maps', runner_path: @runner_path)
22
23
  @encoding = options[:encoding]
23
24
  @deprecated = !!options[:deprecated]
24
-
25
- @vm = VM.new(binary: @binary, source_maps: '--enable-source-maps', runner_path: @runner_path)
26
-
27
25
  @popen_options = {}
28
26
  @popen_options[:external_encoding] = @encoding if @encoding
29
27
  @popen_options[:internal_encoding] = ::Encoding.default_internal || 'UTF-8'
28
+ @contexts = {}
29
+ end
30
+
31
+ def register_context(uuid, context)
32
+ @contexts[uuid] = context
33
+ end
34
+
35
+ def unregister_context(uuid)
36
+ context = @contexts.delete(uuid)
37
+ if context && @vm
38
+ ObjectSpace.undefine_finalizer(context)
39
+ _ok, cc = @vm.delete_context(uuid) rescue nil # if delete_context fails, the vm exited before probably
40
+ end
41
+ @vm.stop if @contexts.size == 0 && @vm.started?
42
+ end
43
+
44
+ def stop_context(context)
45
+ unregister_context(context.instance_variable_get(:@uuid))
30
46
  end
31
47
 
32
48
  def available?
@@ -1,5 +1,5 @@
1
1
  module Isomorfeus
2
2
  module Speednode
3
- VERSION = '0.6.3'
3
+ VERSION = '0.7.0'
4
4
  end
5
5
  end
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.6.3
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Biedermann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-04 00:00:00.000000000 Z
11
+ date: 2023-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: execjs