jscall 1.0.1 → 1.2.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 +4 -4
- data/README.md +225 -29
- data/examples/pdf-js.rb +56 -0
- data/lib/jscall/browser.mjs +36 -11
- data/lib/jscall/browser.rb +29 -7
- data/lib/jscall/main.mjs +218 -62
- data/lib/jscall/synch.mjs +185 -0
- data/lib/jscall/version.rb +1 -1
- data/lib/jscall.rb +246 -75
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dad6ca4017b93ba7f1675b3d1e3727a143d5e413f86d9f000966f7eae9306d06
|
4
|
+
data.tar.gz: e50ef13d47441f195194e4a36886b506266f87339f9d7bbf7f5b9d79dc500814
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16a7885d6e0e5ef993a9f8ea43a6dc2bcfe78624f20cd10517642c00f59525b1edab1a91ab99367f962d3f63ba5a5c6705bf7cad915673613fb9ee805358baeb
|
7
|
+
data.tar.gz: 1f7d95224652882839fd9bce1d4fd539021980018ecc1cca73aed56e598a2c034b8800cdfb88cc6ffd4b09f6488867e33335e8180f7e5e81aa29663ebdc6a5d4
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Jscall
|
2
2
|
|
3
|
+
[](https://github.com/csg-tokyo/jscall/actions/workflows/ruby.yml)
|
4
|
+
|
3
5
|
Jscall allows executing a program in JavaScript on node.js or a web browser.
|
4
6
|
By default, node.js is used for the execution.
|
5
7
|
To choose a web browser, call `Jscall.config`.
|
@@ -16,13 +18,17 @@ Jscall.exec '1 + 1'
|
|
16
18
|
```
|
17
19
|
|
18
20
|
This returns `2`. The argument passed to `Jscall.exec` can be
|
19
|
-
|
21
|
+
multiple lines. It is executed as source code written in JavaScript.
|
20
22
|
|
21
23
|
`Jscall.exec` returns a resulting value. Numbers, character strings (and symbols), boolean values, and `nil` (and `null`)
|
22
|
-
are copied when passing between Ruby and JavaScript. An array is
|
24
|
+
are copied when passing between Ruby and JavaScript. An array is shallow-copied.
|
23
25
|
Other objects are not copied. When they are passed, a remote reference is created at the destination.
|
26
|
+
When a `Map` object is returned from JavaScript to Ruby, it is also
|
27
|
+
shallow-copied but into a `Hash` object in Ruby.
|
24
28
|
|
25
|
-
A remote reference is a
|
29
|
+
A remote reference is a local reference to a proxy object.
|
30
|
+
A method call on a remote reference invokes a method on the corresponding
|
31
|
+
object on the remote site. For example,
|
26
32
|
|
27
33
|
```
|
28
34
|
js_obj = Jscall.exec '({ foo: (x) => x + 1, bar: 7 })'
|
@@ -35,11 +41,30 @@ js_obj.baz # 9
|
|
35
41
|
The `foo` method is executed in JavaScript.
|
36
42
|
Since `bar` is not a function, its value is returned to Ruby as it is.
|
37
43
|
|
38
|
-
Setting
|
44
|
+
Setting an object property to a given value is also
|
39
45
|
allowed. The expression `js_obj.baz = 9` above sets
|
40
46
|
the object property `baz` to 9.
|
41
47
|
|
42
|
-
|
48
|
+
An argument to a JavaScript method is copied from Ruby to
|
49
|
+
JavaScript unless it is an object. When an argument is a Ruby object,
|
50
|
+
a proxy object is created in JavaScript. The rule is the same as the
|
51
|
+
rule for returning a value from JavaScript to Ruby. A primitive
|
52
|
+
value is copied but an object is not. An array is shallow-copied.
|
53
|
+
|
54
|
+
A `Hash` object in Ruby is also shallow-copied into JavaScript but a normal
|
55
|
+
object is created in JavaScript. Recall that a JavaScript object is
|
56
|
+
regarded as an associative array, or a hash table as in Ruby.
|
57
|
+
For example, in Ruby,
|
58
|
+
|
59
|
+
```
|
60
|
+
obj = { a: 2, b: 3 }
|
61
|
+
```
|
62
|
+
|
63
|
+
when this ruby object is passed to JavaScript as an argument,
|
64
|
+
a normal object `{ a: 2, b: 3 }` is created as its copy in JavaScript
|
65
|
+
and passed to a JavaScript method.
|
66
|
+
|
67
|
+
To call a JavaScript function from Ruby, call a method on `Jscall`.
|
43
68
|
For example,
|
44
69
|
|
45
70
|
```
|
@@ -54,9 +79,22 @@ Jscall.foo(7) # 8
|
|
54
79
|
`Jscall.foo(7)` invokes the JavaScript function with the name following `Jscall.`
|
55
80
|
with the given argument. In this case,
|
56
81
|
the `foo` function is executed with the argument `7`.
|
82
|
+
Arguments and a return value are passed to/from a function
|
83
|
+
as they are passed to/from a method.
|
84
|
+
|
85
|
+
`Jscall` can be used for obtaining a remote reference to access a global variable
|
86
|
+
in JavaScript. For example,
|
87
|
+
|
88
|
+
```
|
89
|
+
Jscall.console.log('Hello')
|
90
|
+
```
|
91
|
+
|
92
|
+
This prints `Hello` on a JavaScript console. `Jscall.console` returns a remote
|
93
|
+
reference to the value of `console` in JavaScript. Then, `.log('Hello')`
|
94
|
+
calls the `log` method on `console` in JavaScript.
|
57
95
|
|
58
96
|
When a Ruby object is passed to a JavaScript function/method,
|
59
|
-
|
97
|
+
you can call a method on the passed Ruby object.
|
60
98
|
|
61
99
|
```
|
62
100
|
Jscall.exec <<CODE
|
@@ -72,7 +110,7 @@ created in Ruby.
|
|
72
110
|
Note that you must `await` every call to Ruby object since it is
|
73
111
|
asynchronous call.
|
74
112
|
|
75
|
-
In JavaScript, `Ruby.exec` is
|
113
|
+
In JavaScript, `Ruby.exec` is available to run a program in Ruby.
|
76
114
|
For example,
|
77
115
|
|
78
116
|
```
|
@@ -84,10 +122,19 @@ CODE
|
|
84
122
|
Jscall.foo()
|
85
123
|
```
|
86
124
|
|
87
|
-
`Jscall.foo()` returns the result of evaluating
|
88
|
-
in Ruby.
|
125
|
+
`Jscall.foo()` returns the result of evaluating given Ruby code
|
126
|
+
`RUBY_VERSION` in Ruby.
|
89
127
|
Don't forget to `await` a call to `Ruby.exec`.
|
90
128
|
|
129
|
+
### Remote references
|
130
|
+
|
131
|
+
A remote reference is implemented by a local reference to a proxy
|
132
|
+
object representing the remote object that the remote reference refers to.
|
133
|
+
When a proxy object is passed as an argument or a return value
|
134
|
+
from Ruby to JavaScript (or vice versa), the corresponding JavaScript
|
135
|
+
(or Ruby) object is passed to the destination. In other words,
|
136
|
+
a remote reference passed is converted back to a local reference.
|
137
|
+
|
91
138
|
Remote references will be automatically reclaimed when they are no
|
92
139
|
longer used. To reclaim them immediately, call:
|
93
140
|
|
@@ -95,6 +142,25 @@ longer used. To reclaim them immediately, call:
|
|
95
142
|
Jscall.scavenge_references
|
96
143
|
```
|
97
144
|
|
145
|
+
As mentioned above, a remote reference is a local reference
|
146
|
+
to a proxy object. In Ruby,
|
147
|
+
even a proxy object provides a number of methods inherited from `Object` class,
|
148
|
+
such as `clone`, `to_s`, and `inspect`. A call to such a method is not
|
149
|
+
delegated to the corresponding JavaScript object. To invoke such a method
|
150
|
+
on a JavaScript object, call `send` on its proxy object.
|
151
|
+
For example,
|
152
|
+
|
153
|
+
```
|
154
|
+
js_obj = Jscall.exec '({ to_s: (x, y) => x + y })'
|
155
|
+
puts js_obj.to_s(3, 4) # error
|
156
|
+
puts js_obj.send('to_s', 3, 4) # 7
|
157
|
+
```
|
158
|
+
|
159
|
+
The `send` method invokes the JavaScript method with the name specified
|
160
|
+
by the first argument. The remaining arguments passed to `send` are passed
|
161
|
+
to that JavaScript method.
|
162
|
+
|
163
|
+
|
98
164
|
## DOM manipulation
|
99
165
|
|
100
166
|
When JavaScript code is run on a browser, some utility methods
|
@@ -109,7 +175,16 @@ links `mystyle.css` in the current directory.
|
|
109
175
|
- `Jscall.dom.print(msg)`
|
110
176
|
|
111
177
|
This adds a `p` element to the DOM tree.
|
178
|
+
Its inner text is the character string passed as `msg`.
|
112
179
|
|
180
|
+
- `Jscall.dom.append_to_body(html_source)`
|
181
|
+
|
182
|
+
This inserts the given `html_source` at the end of the `body` element.
|
183
|
+
It is a shorthand for
|
184
|
+
|
185
|
+
```
|
186
|
+
Jscall.document.body.insertAdjacentHTML('beforeend', html_source)
|
187
|
+
```
|
113
188
|
|
114
189
|
## Variable scope
|
115
190
|
|
@@ -142,16 +217,33 @@ for loading a CommonJS module. For example,
|
|
142
217
|
Jscall.exec "mime = require('./mime.js')"
|
143
218
|
```
|
144
219
|
|
145
|
-
The file `./mime.js` is loaded and the module is bound to a global variable `mime
|
220
|
+
The file `./mime.js` is loaded and the module is bound to a global variable `mime` in JavaScript.
|
146
221
|
|
147
|
-
You
|
222
|
+
You can directly call `require` on `Jscall` in Ruby.
|
223
|
+
|
224
|
+
```
|
225
|
+
parser = Jscall.require("@babel/parser")
|
226
|
+
ast = parser.parse('const i = 3')
|
227
|
+
Jscall.console.log(ast)
|
228
|
+
```
|
229
|
+
|
230
|
+
`require` will search `./node_modules/` for `@babel/parser`.
|
231
|
+
This is equivalent to the following JavaScript code.
|
232
|
+
|
233
|
+
```
|
234
|
+
parser = require("@babel/parser")
|
235
|
+
ast = parser.parse('const i = 3')
|
236
|
+
console.log(ast)
|
237
|
+
```
|
238
|
+
|
239
|
+
Dynamic importing is also available. Call `Jscall.dyn_import` in Ruby.
|
148
240
|
|
149
241
|
```
|
150
242
|
fs = Jscall.dyn_import('fs')
|
151
243
|
```
|
152
244
|
|
153
245
|
This executes dynamic importing in JavaScript.
|
154
|
-
For node.js, the file name of the imported module should be a full path name. For a web browser, the root directory is
|
246
|
+
For node.js, the file name of the imported module should be a full path name. For a web browser, the root directory is the current working directory. So `Jscall.dyn_import('/mine.mjs')` loads the file `./mine.mjs`.
|
155
247
|
|
156
248
|
`Jscall.dyn_import` takes the second argument. If it is given,
|
157
249
|
a global variable in JavaScript is bound to the loaded module.
|
@@ -166,49 +258,147 @@ This is quite equivalent to the following JavaScript code:
|
|
166
258
|
fs_module = await load('fs')
|
167
259
|
```
|
168
260
|
|
261
|
+
## Promise
|
262
|
+
|
263
|
+
If a program attempts to pass a `Promise` object from JavaScript to Ruby,
|
264
|
+
it waits until the promise is fulfilled. Then Jscall passes
|
265
|
+
the value of that promise from JavaScript to Ruby instead of that
|
266
|
+
promise itself (or a remote reference to that promise). When that promise
|
267
|
+
is rejected, an error object is passed to Ruby
|
268
|
+
so that the error will be raised in Ruby.
|
269
|
+
This design reflects the fact that an `async` function in JavaScript
|
270
|
+
also returns a `Promise` object but this object must not be returned
|
271
|
+
to Ruby as is when that `async` function is called from Ruby.
|
272
|
+
Jscall cannot determine whether a promise should be passed as is to Ruby
|
273
|
+
or its value must be passed to Ruby after the promise is fulfilled.
|
274
|
+
|
275
|
+
When enforcing Jscall to pass a `Promise` object from JavaScript to Ruby,
|
276
|
+
`.async` must be inserted between a receiver and a method name.
|
277
|
+
|
278
|
+
```
|
279
|
+
Jscall.exec(<<CODE)
|
280
|
+
function make_promise() {
|
281
|
+
return { a: Promise.resolve(7) }
|
282
|
+
}
|
283
|
+
CODE
|
284
|
+
|
285
|
+
obj = Jscall.make_promise
|
286
|
+
result = obj.a # 7
|
287
|
+
prom = obj.async.a # promise
|
288
|
+
prom.then(->(r) { puts r }) # 7
|
289
|
+
```
|
290
|
+
|
291
|
+
## Synchronous calls
|
292
|
+
|
293
|
+
You might want to avoid writing `await` when you call a method on a Ruby
|
294
|
+
object or you execute Ruby code by `Ruby.exec` from JavaScript.
|
295
|
+
For example, that call is included in library code and you might not
|
296
|
+
be able to modify the library code so that `await` will be inserted.
|
297
|
+
|
298
|
+
Jscall supports synchronous calls from JavaScript to Ruby only when
|
299
|
+
the underlying JavaScript engine is node.js on Linux.
|
300
|
+
In the mode of synchronous calls, you do not have to `await` a method call
|
301
|
+
on a Ruby object or a call to `Ruby.exec`.
|
302
|
+
It blocks until the return value comes back from Ruby.
|
303
|
+
While it blocks, all calls from Ruby to JavaScript are
|
304
|
+
synchronously processed.
|
305
|
+
|
306
|
+
To change to the mode of synchronous calls,
|
307
|
+
call `Jscall.config`:
|
308
|
+
|
309
|
+
```
|
310
|
+
Jscall.config(sync: true)
|
311
|
+
```
|
169
312
|
|
170
313
|
## Configuration
|
171
314
|
|
172
|
-
|
315
|
+
Jscall supports several configuration options.
|
316
|
+
Call `Jscall.config` with necessary options.
|
317
|
+
|
318
|
+
### module_names:
|
319
|
+
|
320
|
+
To import JavaScript modules when node.js or a web browser starts,
|
173
321
|
|
174
322
|
```
|
175
|
-
Jscall.config(module_names: [["Foo", "./foo.mjs"], ["Bar", "./bar.mjs"]]
|
323
|
+
Jscall.config(module_names: [["Foo", "./js", "/lib/foo.mjs"], ["Bar", "./js", "/lib/bar.mjs"]])
|
176
324
|
```
|
177
325
|
|
178
|
-
This specifies that `./foo.mjs` and `./bar.mjs` are
|
326
|
+
This specifies that `./js/lib/foo.mjs` and `./js/lib/bar.mjs` are imported
|
327
|
+
at the beginning.
|
179
328
|
This is equivalent to the following import declarations:
|
180
329
|
|
181
330
|
```
|
182
|
-
import * as "Foo" from "./foo.mjs"
|
183
|
-
import * as "Bar" from "./bar.mjs"
|
331
|
+
import * as "Foo" from "./js/lib/foo.mjs"
|
332
|
+
import * as "Bar" from "./js/lib/bar.mjs"
|
184
333
|
```
|
185
334
|
|
186
|
-
|
335
|
+
Note that each array element given to `module_names:` is
|
187
336
|
|
188
|
-
|
337
|
+
```
|
338
|
+
[<module_name> <root> <path>]
|
339
|
+
```
|
189
340
|
|
190
|
-
|
341
|
+
`<path>` must start with `/`. It is used as a part of the URL when a browser
|
342
|
+
accesses a module.
|
343
|
+
When importing a module for node.js, `<root>` and `<path>` are concatenated
|
344
|
+
to form a full path name.
|
345
|
+
|
346
|
+
`<path>` must not start with `/jscall` or `/cmd`. They are reserved for
|
347
|
+
internal use.
|
348
|
+
|
349
|
+
### options:
|
350
|
+
|
351
|
+
To specify a command line argument passed to node.js,
|
191
352
|
|
192
353
|
```
|
193
|
-
Jscall
|
354
|
+
Jscall.config(options: '--use-strict')
|
194
355
|
```
|
195
356
|
|
196
|
-
|
357
|
+
This call specifies that
|
358
|
+
`--use-strict` is passed as a command line argument.
|
359
|
+
|
360
|
+
### browser: and port:
|
197
361
|
|
198
362
|
When running JavaScript code on a web browser,
|
199
363
|
|
200
364
|
```
|
201
|
-
Jscall.config(browser: true,
|
365
|
+
Jscall.config(browser: true, port: 10082)
|
202
366
|
```
|
203
367
|
|
204
|
-
`
|
368
|
+
Passing `true` for `browser:` switches the execution engine to a web browser.
|
369
|
+
The default engine is node.js.
|
370
|
+
To switch the engine back to node.js, pass `false` for `browser:`.
|
371
|
+
Call `Jscall.close` to detach the current execution engine.
|
372
|
+
A new engine with a new configuration will be created.
|
373
|
+
|
374
|
+
`port:` specifies the port number of an http server. It is optional.
|
205
375
|
The example above specifies that Ruby receives http requests
|
206
376
|
sent to http://localhost:10082 from JavaScript on a web browser.
|
207
377
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
378
|
+
|
379
|
+
### Misc.
|
380
|
+
|
381
|
+
To change to the mode of synchronous calls,
|
382
|
+
|
383
|
+
```
|
384
|
+
Jscall.config(sync: true)
|
385
|
+
```
|
386
|
+
|
387
|
+
To set all the configurations to the default ones,
|
388
|
+
|
389
|
+
```
|
390
|
+
Jscall.config()
|
391
|
+
```
|
392
|
+
|
393
|
+
### Other configurations
|
394
|
+
|
395
|
+
To change the name of the node command,
|
396
|
+
|
397
|
+
```
|
398
|
+
Jscall::PipeToJs.node_command = "node.exe"
|
399
|
+
```
|
400
|
+
|
401
|
+
The default command name is `"node"`.
|
212
402
|
|
213
403
|
To change the command for launching a web browser,
|
214
404
|
|
@@ -224,6 +414,12 @@ Jscall launches a web browser by the command like the following:
|
|
224
414
|
open http://localhost:10082/jscall/jscall.html
|
225
415
|
```
|
226
416
|
|
417
|
+
Jscall generates a verbose error message if its debug level is more than 0.
|
418
|
+
|
419
|
+
```
|
420
|
+
Jscall.debug = 1
|
421
|
+
```
|
422
|
+
|
227
423
|
## Installation
|
228
424
|
|
229
425
|
Add this line to your application's Gemfile:
|
@@ -254,7 +450,7 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/csg-to
|
|
254
450
|
|
255
451
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
256
452
|
|
257
|
-
##
|
453
|
+
## Acknowledgment
|
258
454
|
|
259
455
|
The icon image for jscall was created by partly using the Ruby logo, which was obtained
|
260
456
|
from https://www.ruby-lang.org/en/about/logo/ under CC BY-SA 2.5.
|
data/examples/pdf-js.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# Display a pdf file by using pdf.js
|
2
|
+
|
3
|
+
require 'jscall'
|
4
|
+
|
5
|
+
# Run a JavaScript program on a browser
|
6
|
+
Jscall.config browser: true
|
7
|
+
|
8
|
+
# Write HTML code on a blank web page.
|
9
|
+
Jscall.dom.append_to_body(<<CODE)
|
10
|
+
<h1>PDF.js 'Hello, world!' example</h1>
|
11
|
+
<canvas id="the-canvas"></canvas>
|
12
|
+
CODE
|
13
|
+
|
14
|
+
# import pdf.js
|
15
|
+
pdfjs = Jscall.dyn_import('https://mozilla.github.io/pdf.js/build/pdf.js')
|
16
|
+
|
17
|
+
# A pdf file
|
18
|
+
url = "https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.pdf"
|
19
|
+
|
20
|
+
pdf = Jscall.exec 'window["pdfjs-dist/build/pdf"]'
|
21
|
+
|
22
|
+
pdf.GlobalWorkerOptions.workerSrc = "https://mozilla.github.io/pdf.js/build/pdf.worker.js"
|
23
|
+
|
24
|
+
loadingTask = pdf.getDocument(url)
|
25
|
+
loadingTask.async.promise.then(-> (pdf) {
|
26
|
+
puts "PDF loaded"
|
27
|
+
|
28
|
+
# Fetch the first page
|
29
|
+
pageNumber = 1;
|
30
|
+
pdf.async.getPage(pageNumber).then(-> (page) {
|
31
|
+
puts "Page loaded"
|
32
|
+
|
33
|
+
scale = 1.5;
|
34
|
+
viewport = page.getViewport({ scale: scale })
|
35
|
+
|
36
|
+
canvas = Jscall.document.getElementById("the-canvas")
|
37
|
+
context = canvas.getContext("2d")
|
38
|
+
canvas.height = viewport.height
|
39
|
+
canvas.width = viewport.width
|
40
|
+
|
41
|
+
# Render the pdf page
|
42
|
+
renderContext = {
|
43
|
+
canvasContext: context,
|
44
|
+
viewport: viewport,
|
45
|
+
}
|
46
|
+
renderTask = page.render(renderContext)
|
47
|
+
renderTask.async.promise.then(-> (r) {
|
48
|
+
# Print a message when the rendering succeeds.
|
49
|
+
puts "Page rendered #{r}"
|
50
|
+
})
|
51
|
+
})
|
52
|
+
},
|
53
|
+
-> (reason) {
|
54
|
+
# an error occurs.
|
55
|
+
puts reason
|
56
|
+
})
|
data/lib/jscall/browser.mjs
CHANGED
@@ -2,24 +2,27 @@
|
|
2
2
|
|
3
3
|
export class HttpStream {
|
4
4
|
constructor() {
|
5
|
-
this.
|
5
|
+
this.recv_buffer = []
|
6
6
|
this.send_callback = null
|
7
|
+
this.fetching = null
|
8
|
+
this.call_queue = []
|
9
|
+
this.puts('start')
|
7
10
|
}
|
8
11
|
|
9
12
|
[Symbol.asyncIterator]() {
|
10
13
|
const http_stream = this
|
11
14
|
return {
|
12
15
|
next() {
|
13
|
-
let
|
14
|
-
if (
|
16
|
+
let next_data = http_stream.recv_buffer.shift()
|
17
|
+
if (next_data === undefined)
|
15
18
|
return new Promise((resolve, reject) => {
|
16
19
|
if (http_stream.send_callback === null)
|
17
20
|
http_stream.send_callback = resolve
|
18
21
|
else
|
19
22
|
throw new Error('(fatal) send_callback is not null!')
|
20
|
-
})
|
23
|
+
})
|
21
24
|
else
|
22
|
-
return
|
25
|
+
return next_data
|
23
26
|
}
|
24
27
|
}
|
25
28
|
}
|
@@ -40,12 +43,30 @@ export class HttpStream {
|
|
40
43
|
}
|
41
44
|
|
42
45
|
puts(msg) {
|
43
|
-
this.
|
44
|
-
|
45
|
-
|
46
|
-
this.
|
47
|
-
|
48
|
-
|
46
|
+
if (this.fetching === null)
|
47
|
+
this.fetching = this.puts0(msg)
|
48
|
+
else
|
49
|
+
this.call_queue.push(msg)
|
50
|
+
}
|
51
|
+
|
52
|
+
puts0(msg) {
|
53
|
+
return this.do_fetch(msg)
|
54
|
+
.then((data) => {
|
55
|
+
if (this.send_callback === null)
|
56
|
+
this.recv_buffer.push(data)
|
57
|
+
else {
|
58
|
+
const callback = this.send_callback
|
59
|
+
this.send_callback = null
|
60
|
+
callback(data)
|
61
|
+
}
|
62
|
+
|
63
|
+
if (this.call_queue.length > 0) {
|
64
|
+
const msg2 = this.call_queue.shift()
|
65
|
+
this.fetching = this.puts0(msg2)
|
66
|
+
}
|
67
|
+
else
|
68
|
+
this.fetching = null
|
69
|
+
})
|
49
70
|
}
|
50
71
|
|
51
72
|
setEncoding(encoding) {}
|
@@ -64,4 +85,8 @@ export const Jscall = new class {
|
|
64
85
|
link.href = file_name
|
65
86
|
document.head.append(link)
|
66
87
|
}
|
88
|
+
|
89
|
+
append_to_body(html_source) {
|
90
|
+
document.body.insertAdjacentHTML('beforeend', html_source)
|
91
|
+
}
|
67
92
|
}
|
data/lib/jscall/browser.rb
CHANGED
@@ -8,6 +8,7 @@ module Jscall
|
|
8
8
|
WEBrick::HTTPUtils::DefaultMimeTypes['mjs'] ||= "application/javascript"
|
9
9
|
|
10
10
|
class Dom
|
11
|
+
# see Jscall class in browser.mjs
|
11
12
|
def method_missing(name, *args)
|
12
13
|
Jscall.__getpipe__.funcall(nil, "Jscall.#{name}", args)
|
13
14
|
end
|
@@ -23,13 +24,27 @@ module Jscall
|
|
23
24
|
end
|
24
25
|
|
25
26
|
class PipeToBrowser < PipeToJs
|
26
|
-
def startJS(module_names,
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
def startJS(module_names, config)
|
28
|
+
urls = {}
|
29
|
+
module_names.each_index do |i|
|
30
|
+
mod = module_names[i]
|
31
|
+
urls[mod[2]] = mod
|
32
|
+
end
|
33
|
+
port = config[:port] || 10081
|
34
|
+
@pipe = FetchServer.new(port, urls)
|
30
35
|
@pipe.open
|
31
36
|
end
|
32
37
|
|
38
|
+
def setup(config)
|
39
|
+
if config[:browser]
|
40
|
+
module_names = config[:module_names] || []
|
41
|
+
module_names.each_index do |i|
|
42
|
+
mod = module_names[i]
|
43
|
+
Jscall.dyn_import(mod[2], mod[0])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
33
48
|
def close
|
34
49
|
@pipe.shutdown
|
35
50
|
sleep(0.5)
|
@@ -58,7 +73,8 @@ module Jscall
|
|
58
73
|
@@run_cmd = name
|
59
74
|
end
|
60
75
|
|
61
|
-
def initialize(port)
|
76
|
+
def initialize(port, urls)
|
77
|
+
@url_map = urls
|
62
78
|
@send_buffer = Thread::Queue.new
|
63
79
|
@receive_buffer = Thread::Queue.new
|
64
80
|
@server_running = false
|
@@ -96,10 +112,16 @@ module Jscall
|
|
96
112
|
end
|
97
113
|
|
98
114
|
def read_file(req, res)
|
99
|
-
|
115
|
+
path = req.path
|
116
|
+
if path.start_with?('/jscall/')
|
100
117
|
root = "#{__dir__}/../"
|
101
118
|
else
|
102
|
-
|
119
|
+
value = @url_map[path]
|
120
|
+
if value.nil?
|
121
|
+
root = @server.config[:DocumentRoot]
|
122
|
+
else
|
123
|
+
root = value[1]
|
124
|
+
end
|
103
125
|
end
|
104
126
|
WEBrick::HTTPServlet::FileHandler.new(@server, root).service(req, res)
|
105
127
|
end
|