quickjs 0.13.0.pre → 0.13.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: f27d3afc594731cc4df53661889a9787626121923ece35c544b581ef3f52722c
4
- data.tar.gz: d3869683f9134339d1d2e44617845f8ece614e1503926841fb9d4ad6de3dc7ba
3
+ metadata.gz: 5796bac189dd080cf33b19413b16f01aa38a432de8cc70a102d6215e3aa6788a
4
+ data.tar.gz: ff57fa394865f9f2e5881a0e8953662644e51f76aecff2e1cddb16d9f42edc4e
5
5
  SHA512:
6
- metadata.gz: b5cfcad98315e8821644aa233ea86213f855900506767ccce01cb0c1a653326456e3d00c453d0821117e31eee543ec440ed1e4583dd6b420a62e49ffcb53e080
7
- data.tar.gz: 7df6cc20b91fce4c14e2a2b96b31bb447ee50eba03498a99e336c8b35d62164a05874ed7753509a4d0c1958761f96c5c85f4de66c6301b79eecbe208dbcf8212
6
+ metadata.gz: df8c07bb183fdfa7c6440198fcfe24a158cc6cde23fd645dbcaf8bd2c2642c4855e4e09ac459761b4272cbc0332ff7e32856ceb8e5fdb844390b3db37194f7e0
7
+ data.tar.gz: 797fd273ee7888ee2fd6066b2fff620b8b8b13ca33f0f18f0a7b1c24d0a0df980991b22aac1387cf94a08f8dedc0c81ad6a408e9e60ad81f6dc37a59205a2ba2
data/README.md CHANGED
@@ -23,17 +23,9 @@ gem 'quickjs'
23
23
  require 'quickjs'
24
24
 
25
25
  Quickjs.eval_code('const fn = (n, pow) => n ** pow; fn(2,8);') # => 256
26
- Quickjs.eval_code('const fn = (name) => `Hi, ${name}!`; fn("Itadori");') # => "Hi, Itadori!
27
- Quickjs.eval_code("const isOne = (n) => 1 === n; func(1);") #=> true (TrueClass)
28
- Quickjs.eval_code("const isOne = (n) => 1 === n; func(3);") #=> false (FalseClass)
29
-
30
- # When code returns 'object' for `typeof`, the result is converted via JSON.stringify (JS) -> JSON.parse (Ruby)
31
- Quickjs.eval_code("[1,2,3]") #=> [1, 2, 3] (Array)
32
- Quickjs.eval_code("({ a: '1', b: 1 })") #=> { 'a' => '1', 'b' => 1 } (Hash)
33
-
34
- Quickjs.eval_code("null") #=> nil
35
- Quickjs.eval_code('const obj = {}; obj.missingKey;') # => :undefined (Quickjs::Value::Undefined)
36
- Quickjs.eval_code("Number('whatever')") #=> :NaN (Quickjs::Value::NAN)
26
+ Quickjs.eval_code('const fn = (name) => `Hi, ${name}!`; fn("Itadori");') # => "Hi, Itadori!"
27
+ Quickjs.eval_code("[1,2,3]") #=> [1, 2, 3]
28
+ Quickjs.eval_code("({ a: '1', b: 1 })") #=> { 'a' => '1', 'b' => 1 }
37
29
  ```
38
30
 
39
31
  <details>
@@ -42,36 +34,40 @@ Quickjs.eval_code("Number('whatever')") #=> :NaN (Quickjs::Value::NAN)
42
34
  #### Resources
43
35
 
44
36
  ```rb
45
- # 1GB memory limit
46
- Quickjs.eval_code(code, { memory_limit: 1024 ** 3 })
47
-
48
- # 1MB max stack size
49
- Quickjs.eval_code(code, { max_stack_size: 1024 ** 2 })
37
+ Quickjs.eval_code(code,
38
+ memory_limit: 1024 ** 3, # 1GB memory limit
39
+ max_stack_size: 1024 ** 2, # 1MB max stack size
40
+ )
50
41
  ```
51
42
 
52
- #### Toggle features
43
+ #### Timeout
53
44
 
54
45
  ```rb
55
- # Enable `std` module by quickjs: https://bellard.org/quickjs/quickjs.html#std-module
56
- vm = Quickjs.eval_code(features: [::Quickjs::MODULE_STD])
57
-
58
- # Enable `os` module by quickjs: https://bellard.org/quickjs/quickjs.html#os-module
59
- vm = Quickjs.eval_code(features: [::Quickjs::MODULE_OS])
60
-
61
- # Provide `setTimeout` managed by CRuby
62
- vm = Quickjs.eval_code(features: [::Quickjs::FEATURE_TIMEOUT])
46
+ # eval_code will be interrupted after 1 sec (default: 100 msec)
47
+ Quickjs.eval_code(code, timeout_msec: 1_000)
48
+ ```
63
49
 
64
- # Inject the polyfill of Intl
65
- vm = Quickjs.eval_code(features: [::Quickjs::POLYFILL_INTL])
50
+ #### Features
66
51
 
67
- # Inject the polyfill of Blob and File (W3C File API)
68
- vm = Quickjs.eval_code(features: [::Quickjs::POLYFILL_FILE])
52
+ ```rb
53
+ Quickjs.eval_code(code, features: [::Quickjs::MODULE_STD, ::Quickjs::POLYFILL_FILE])
69
54
  ```
70
55
 
56
+ | Constant | Description |
57
+ |---|---|
58
+ | `MODULE_STD` | QuickJS [`std` module](https://bellard.org/quickjs/quickjs.html#std-module) |
59
+ | `MODULE_OS` | QuickJS [`os` module](https://bellard.org/quickjs/quickjs.html#os-module) |
60
+ | `FEATURE_TIMEOUT` | `setTimeout` / `setInterval` managed by CRuby |
61
+ | `POLYFILL_INTL` | Intl API (DateTimeFormat, NumberFormat, PluralRules, Locale) |
62
+ | `POLYFILL_FILE` | W3C File API (Blob and File) |
63
+ | `POLYFILL_ENCODING` | Encoding API (TextEncoder and TextDecoder) |
64
+
71
65
  </details>
72
66
 
73
67
  ### `Quickjs::VM`: Maintain a consistent VM/runtime
74
68
 
69
+ Accepts the same [options](#quickjseval_code-evaluate-javascript-code-instantly) as `Quickjs.eval_code`.
70
+
75
71
  ```rb
76
72
  vm = Quickjs::VM.new
77
73
  vm.eval_code('const a = { b: "c" };')
@@ -80,45 +76,6 @@ vm.eval_code('a.b = "d";')
80
76
  vm.eval_code('a.b;') #=> "d"
81
77
  ```
82
78
 
83
- <details>
84
- <summary>Config VM/runtime</summary>
85
-
86
- #### Resources
87
-
88
- ```rb
89
- vm = Quickjs::VM.new(
90
- memory_limit: 1024 ** 3,
91
- max_stack_size: 1024 ** 2,
92
- )
93
- ```
94
-
95
- #### Toggle features
96
-
97
- ```rb
98
- # Enable `std` module by quickjs: https://bellard.org/quickjs/quickjs.html#std-module
99
- vm = Quickjs::VM.new(features: [::Quickjs::MODULE_STD])
100
-
101
- # Enable `os` module by quickjs: https://bellard.org/quickjs/quickjs.html#os-module
102
- vm = Quickjs::VM.new(features: [::Quickjs::MODULE_OS])
103
-
104
- # Provide `setTimeout` managed by CRuby
105
- vm = Quickjs::VM.new(features: [::Quickjs::FEATURE_TIMEOUT])
106
-
107
- # Inject the polyfill of Intl
108
- vm = Quickjs::VM.new(features: [::Quickjs::POLYFILL_INTL])
109
-
110
- # Inject the polyfill of Blob and File (W3C File API)
111
- vm = Quickjs::VM.new(features: [::Quickjs::POLYFILL_FILE])
112
- ```
113
-
114
- #### VM timeout
115
-
116
- ```rb
117
- # `eval_code` will be interrupted after 1 sec (default: 100 msec)
118
- vm = Quickjs::VM.new(timeout_msec: 1_000)
119
- ```
120
- </details>
121
-
122
79
  #### `Quickjs::VM#import`: 🔌 Import ESM from a source code
123
80
 
124
81
  ```rb
@@ -151,20 +108,58 @@ end
151
108
  vm.eval_code("greetingTo('Rick')") #=> 'Hello! Rick'
152
109
  ```
153
110
 
154
- #### `Quickjs::VM#logs`: 💾 Capture console logs
111
+ A Ruby exception raised inside the block is catchable in JS as an `Error`, and propagates back to Ruby as the original exception type if uncaught in JS.
112
+
113
+ ```rb
114
+ vm.define_function("fail") { raise IOError, "something went wrong" }
115
+
116
+ vm.eval_code('try { fail() } catch (e) { e.message }') #=> "something went wrong"
117
+ vm.eval_code("fail()") #=> raise IOError transparently
118
+ ```
119
+
120
+ With `POLYFILL_FILE` enabled, a Ruby `::File` returned from the block becomes a JS `File`-compatible proxy. Passing it back to Ruby from JS returns the original `::File` object.
155
121
 
156
- All logs by `console.(log|info|debug|warn|error)` on VM are recorded and inspectable.
122
+ ```rb
123
+ vm = Quickjs::VM.new(features: [::Quickjs::POLYFILL_FILE])
124
+ vm.define_function(:get_file) { File.open('report.pdf') }
125
+
126
+ vm.eval_code("get_file().name") #=> "report.pdf"
127
+ vm.eval_code("get_file().size") #=> Integer (byte size)
128
+ vm.eval_code("await get_file().text()") #=> file content as String
129
+ ```
130
+
131
+ #### `Quickjs::VM#on_log`: 📡 Handle console logs in real time
132
+
133
+ Register a block to be called for each `console.(log|info|debug|warn|error)` call.
157
134
 
158
135
  ```rb
159
136
  vm = Quickjs::VM.new
160
- vm.eval_code('console.log("log me", null)')
137
+ vm.on_log { |log| puts "#{log.severity}: #{log.to_s}" }
161
138
 
162
- vm.logs #=> Array of Quickjs::VM::Log
163
- vm.logs.last.severity #=> :info
164
- vm.logs.last.to_s #=> 'log me null'
165
- vm.logs.last.raw #=> ['log me', nil]
139
+ vm.eval_code('console.log("hello", 42)')
140
+ # => prints: info: hello 42
141
+
142
+ # log.severity #=> :info / :verbose / :warning / :error
143
+ # log.to_s #=> space-joined string of all arguments
144
+ # log.raw #=> Array of raw Ruby values
166
145
  ```
167
146
 
147
+ ### Value Conversion
148
+
149
+ | JavaScript | | Ruby | Note |
150
+ |---|:---:|---|---|
151
+ | `number` (integer / float) | ↔ | `Integer` / `Float` | |
152
+ | `string` | ↔ | `String` | |
153
+ | `true` / `false` | ↔ | `true` / `false` | |
154
+ | `null` | ↔ | `nil` | |
155
+ | `Array` | ↔ | `Array` | via JSON |
156
+ | `Object` | ↔ | `Hash` | via JSON |
157
+ | `undefined` | → | `Quickjs::Value::UNDEFINED` | |
158
+ | `NaN` | → | `Quickjs::Value::NAN` | |
159
+ | `Blob` | → | `Quickjs::Blob` — `.size`, `.type`, `.content` | requires `POLYFILL_FILE` |
160
+ | `File` | → | `Quickjs::File` — `.name`, `.last_modified` + Blob attrs | requires `POLYFILL_FILE` |
161
+ | `File` proxy | ← | `::File` | requires `POLYFILL_FILE`; applies to `define_function` return values |
162
+
168
163
  ## License
169
164
 
170
165
  - `ext/quickjsrb/quickjs`
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quickjs
4
- VERSION = "0.13.0.pre"
4
+ VERSION = "0.13.0"
5
5
  end
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "quickjs-rb-polyfills",
3
- "version": "0.13.0.pre",
3
+ "version": "0.13.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "quickjs-rb-polyfills",
9
- "version": "0.13.0.pre",
9
+ "version": "0.13.0",
10
10
  "dependencies": {
11
11
  "@formatjs/intl-datetimeformat": "^7.2.1",
12
12
  "@formatjs/intl-getcanonicallocales": "^3.2.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quickjs-rb-polyfills",
3
- "version": "0.13.0.pre",
3
+ "version": "0.13.0",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "build": "rolldown -c rolldown.config.mjs"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quickjs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0.pre
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - hmsk