Skip to content

Commit 56b00f1

Browse files
Merge pull request #525 from ruby/katei/npm-jco
Add `RubyVM.instantiateComponent` and `RubyVM.instantiateModule`
2 parents 3912725 + 2e6882b commit 56b00f1

File tree

26 files changed

+452
-499
lines changed

26 files changed

+452
-499
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
- run: ./bin/setup
3737
- run: bundle exec rake check:type
3838
- run: sudo apt-get install clang-format
39-
- run: ./tools/clang-format-diff.sh
39+
- run: ./bin/clang-format-diff.sh
4040
- run: bundle exec rake check:bindgen
4141
- run: git diff --exit-code
4242

File renamed without changes.

tools/exe/rbminify renamed to bin/rbminify

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env ruby
22

3-
$LOAD_PATH << File.join(File.dirname(__FILE__), "../lib")
3+
$LOAD_PATH << File.join(File.dirname(__FILE__), "lib")
44

55
require "syntax_tree"
66
require "syntax_tree/cli"

bin/repl.mjs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import * as preview2Shim from "@bytecodealliance/preview2-shim"
2+
import * as nodeWasi from "wasi";
3+
import fs from "fs/promises";
4+
import path from "path";
5+
import { RubyVM } from "@ruby/wasm-wasi";
6+
import * as readline from 'node:readline/promises';
7+
import { stdin as input, stdout as output } from 'node:process';
8+
import { parseArgs } from "node:util"
9+
10+
async function instantiateComponent(pkgPath) {
11+
const componentJsPath = path.resolve(pkgPath, "dist/component/ruby.component.js");
12+
const { instantiate } = await import(componentJsPath);
13+
const getCoreModule = async (relativePath) => {
14+
const coreModulePath = path.resolve(pkgPath, "dist/component", relativePath);
15+
const buffer = await fs.readFile(coreModulePath);
16+
return WebAssembly.compile(buffer);
17+
}
18+
const { cli, filesystem } = preview2Shim;
19+
cli._setArgs(["ruby.wasm"].concat(process.argv.slice(2)));
20+
cli._setCwd("/")
21+
filesystem._setPreopens({})
22+
23+
const { vm } = await RubyVM.instantiateComponent({
24+
instantiate, getCoreModule, wasip2: preview2Shim,
25+
});
26+
return vm;
27+
}
28+
29+
async function instantiateModule(pkgPath) {
30+
const binaryPath = path.resolve(pkgPath, "dist/ruby.debug+stdlib.wasm");
31+
const binary = await fs.readFile(binaryPath);
32+
const rubyModule = await WebAssembly.compile(binary);
33+
const wasi = new nodeWasi.WASI({
34+
stdio: "inherit",
35+
args: ["ruby.wasm"].concat(process.argv.slice(2)),
36+
env: process.env,
37+
version: "preview1",
38+
});
39+
40+
const { vm } = await RubyVM.instantiateModule({
41+
module: rubyModule, wasip1: wasi
42+
})
43+
return vm;
44+
};
45+
46+
function parseOptions(args) {
47+
/** @type {import("util").ParseArgsConfig["options"]} */
48+
const options = {
49+
pkg: {
50+
type: "string",
51+
short: "p",
52+
default: (() => {
53+
const dirname = path.dirname(new URL(import.meta.url).pathname);
54+
return path.resolve(dirname, "../packages/npm-packages/ruby-head-wasm-wasi");
55+
})()
56+
},
57+
type: {
58+
type: "string",
59+
short: "t",
60+
default: "component",
61+
},
62+
help: {
63+
type: "boolean",
64+
short: "h",
65+
},
66+
}
67+
const { values } = parseArgs({ args, options });
68+
return values;
69+
}
70+
71+
function printUsage() {
72+
console.log("Usage: repl.mjs [--pkg <npm-package-path>] [--type <component|module>]");
73+
}
74+
75+
async function main() {
76+
const args = parseOptions(process.argv.slice(2));
77+
if (args["help"]) {
78+
printUsage();
79+
return;
80+
}
81+
const pkgPath = args["pkg"];
82+
const vm = await (async () => {
83+
switch (args["type"]) {
84+
case "component": {
85+
console.log(`Loading component from ${pkgPath}`);
86+
return await instantiateComponent(pkgPath);
87+
}
88+
case "module": {
89+
console.log(`Loading core module from ${pkgPath}`);
90+
return await instantiateModule(pkgPath);
91+
}
92+
default:
93+
throw new Error(`Unknown type: ${args["type"]}`);
94+
}
95+
})();
96+
const rl = readline.createInterface({ input, output });
97+
98+
vm.eval(`puts RUBY_DESCRIPTION`);
99+
100+
const printer = vm.eval(`
101+
class ReplPrinter
102+
def puts(*args)
103+
args.each do |arg|
104+
Kernel.puts(arg)
105+
end
106+
end
107+
end
108+
ReplPrinter.new
109+
`);
110+
while (true) {
111+
const line = await rl.question(`>> `);
112+
try {
113+
const result = vm.eval(line);
114+
printer.call("puts", result);
115+
} catch (e) {
116+
console.error(e);
117+
}
118+
}
119+
}
120+
121+
main().catch(console.error);

packages/gems/js/ext/js/bindgen/ext.c

Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,6 @@ extern void __wasm_import_ruby_js_js_runtime_throw_prohibit_rewind_exception(uin
7878

7979

8080

81-
82-
83-
8481
__attribute__((__weak__, __export_name__("cabi_post_ruby:js/ruby-runtime#rstring-ptr")))
8582
void __wasm_export_exports_ruby_js_ruby_runtime_rstring_ptr_post_return(uint8_t * arg0) {
8683
if ((*((size_t*) (arg0 + 4))) > 0) {
@@ -150,32 +147,6 @@ void ruby_js_js_runtime_list_borrow_js_abi_value_free(ruby_js_js_runtime_list_bo
150147
}
151148
}
152149

153-
__attribute__((__import_module__("[export]ruby:js/ruby-runtime"), __import_name__("[resource-drop]rb-iseq")))
154-
extern void __wasm_import_exports_ruby_js_ruby_runtime_rb_iseq_drop(int32_t handle);
155-
156-
void exports_ruby_js_ruby_runtime_rb_iseq_drop_own(exports_ruby_js_ruby_runtime_own_rb_iseq_t handle) {
157-
__wasm_import_exports_ruby_js_ruby_runtime_rb_iseq_drop(handle.__handle);
158-
}
159-
160-
__attribute__(( __import_module__("[export]ruby:js/ruby-runtime"), __import_name__("[resource-new]rb-iseq")))
161-
extern int32_t __wasm_import_exports_ruby_js_ruby_runtime_rb_iseq_new(int32_t);
162-
163-
__attribute__((__import_module__("[export]ruby:js/ruby-runtime"), __import_name__("[resource-rep]rb-iseq")))
164-
extern int32_t __wasm_import_exports_ruby_js_ruby_runtime_rb_iseq_rep(int32_t);
165-
166-
exports_ruby_js_ruby_runtime_own_rb_iseq_t exports_ruby_js_ruby_runtime_rb_iseq_new(exports_ruby_js_ruby_runtime_rb_iseq_t *rep) {
167-
return (exports_ruby_js_ruby_runtime_own_rb_iseq_t) { __wasm_import_exports_ruby_js_ruby_runtime_rb_iseq_new((int32_t) rep) };
168-
}
169-
170-
exports_ruby_js_ruby_runtime_rb_iseq_t* exports_ruby_js_ruby_runtime_rb_iseq_rep(exports_ruby_js_ruby_runtime_own_rb_iseq_t handle) {
171-
return (exports_ruby_js_ruby_runtime_rb_iseq_t*) __wasm_import_exports_ruby_js_ruby_runtime_rb_iseq_rep(handle.__handle);
172-
}
173-
174-
__attribute__((__export_name__("ruby:js/ruby-runtime#[dtor]rb_iseq")))
175-
void __wasm_export_exports_ruby_js_ruby_runtime_rb_iseq_dtor(exports_ruby_js_ruby_runtime_rb_iseq_t* arg) {
176-
exports_ruby_js_ruby_runtime_rb_iseq_destructor(arg);
177-
}
178-
179150
__attribute__((__import_module__("[export]ruby:js/ruby-runtime"), __import_name__("[resource-drop]rb-abi-value")))
180151
extern void __wasm_import_exports_ruby_js_ruby_runtime_rb_abi_value_drop(int32_t handle);
181152

@@ -437,27 +408,9 @@ void __wasm_export_exports_ruby_js_ruby_runtime_ruby_show_version(void) {
437408
}
438409

439410
__attribute__((__export_name__("ruby:js/ruby-runtime#ruby-init")))
440-
void __wasm_export_exports_ruby_js_ruby_runtime_ruby_init(void) {
441-
exports_ruby_js_ruby_runtime_ruby_init();
442-
}
443-
444-
__attribute__((__export_name__("ruby:js/ruby-runtime#ruby-sysinit")))
445-
void __wasm_export_exports_ruby_js_ruby_runtime_ruby_sysinit(uint8_t * arg, size_t arg0) {
411+
void __wasm_export_exports_ruby_js_ruby_runtime_ruby_init(uint8_t * arg, size_t arg0) {
446412
ext_list_string_t arg1 = (ext_list_string_t) { (ext_string_t*)(arg), (arg0) };
447-
exports_ruby_js_ruby_runtime_ruby_sysinit(&arg1);
448-
}
449-
450-
__attribute__((__export_name__("ruby:js/ruby-runtime#ruby-options")))
451-
int32_t __wasm_export_exports_ruby_js_ruby_runtime_ruby_options(uint8_t * arg, size_t arg0) {
452-
ext_list_string_t arg1 = (ext_list_string_t) { (ext_string_t*)(arg), (arg0) };
453-
exports_ruby_js_ruby_runtime_own_rb_iseq_t ret = exports_ruby_js_ruby_runtime_ruby_options(&arg1);
454-
return (ret).__handle;
455-
}
456-
457-
__attribute__((__export_name__("ruby:js/ruby-runtime#ruby-script")))
458-
void __wasm_export_exports_ruby_js_ruby_runtime_ruby_script(uint8_t * arg, size_t arg0) {
459-
ext_string_t arg1 = (ext_string_t) { (uint8_t*)(arg), (arg0) };
460-
exports_ruby_js_ruby_runtime_ruby_script(&arg1);
413+
exports_ruby_js_ruby_runtime_ruby_init(&arg1);
461414
}
462415

463416
__attribute__((__export_name__("ruby:js/ruby-runtime#ruby-init-loadpath")))

packages/gems/js/ext/js/bindgen/ext.h

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,6 @@ typedef struct ruby_js_js_runtime_list_borrow_js_abi_value_t {
4848
size_t len;
4949
} ruby_js_js_runtime_list_borrow_js_abi_value_t;
5050

51-
typedef struct exports_ruby_js_ruby_runtime_own_rb_iseq_t {
52-
int32_t __handle;
53-
} exports_ruby_js_ruby_runtime_own_rb_iseq_t;
54-
55-
typedef struct exports_ruby_js_ruby_runtime_rb_iseq_t exports_ruby_js_ruby_runtime_rb_iseq_t;
56-
57-
typedef exports_ruby_js_ruby_runtime_rb_iseq_t* exports_ruby_js_ruby_runtime_borrow_rb_iseq_t;
58-
5951
typedef struct exports_ruby_js_ruby_runtime_own_rb_abi_value_t {
6052
int32_t __handle;
6153
} exports_ruby_js_ruby_runtime_own_rb_abi_value_t;
@@ -108,10 +100,7 @@ extern void ruby_js_js_runtime_throw_prohibit_rewind_exception(ext_string_t *mes
108100

109101
// Exported Functions from `ruby:js/ruby-runtime`
110102
void exports_ruby_js_ruby_runtime_ruby_show_version(void);
111-
void exports_ruby_js_ruby_runtime_ruby_init(void);
112-
void exports_ruby_js_ruby_runtime_ruby_sysinit(ext_list_string_t *args);
113-
exports_ruby_js_ruby_runtime_own_rb_iseq_t exports_ruby_js_ruby_runtime_ruby_options(ext_list_string_t *args);
114-
void exports_ruby_js_ruby_runtime_ruby_script(ext_string_t *name);
103+
void exports_ruby_js_ruby_runtime_ruby_init(ext_list_string_t *args);
115104
void exports_ruby_js_ruby_runtime_ruby_init_loadpath(void);
116105
void exports_ruby_js_ruby_runtime_rb_eval_string_protect(ext_string_t *str, exports_ruby_js_ruby_runtime_tuple2_own_rb_abi_value_s32_t *ret);
117106
void exports_ruby_js_ruby_runtime_rb_funcallv_protect(exports_ruby_js_ruby_runtime_borrow_rb_abi_value_t recv, exports_ruby_js_ruby_runtime_rb_id_t mid, exports_ruby_js_ruby_runtime_list_borrow_rb_abi_value_t *args, exports_ruby_js_ruby_runtime_tuple2_own_rb_abi_value_s32_t *ret);
@@ -137,12 +126,6 @@ void ruby_js_js_runtime_raw_integer_free(ruby_js_js_runtime_raw_integer_t *ptr);
137126

138127
void ruby_js_js_runtime_list_borrow_js_abi_value_free(ruby_js_js_runtime_list_borrow_js_abi_value_t *ptr);
139128

140-
extern void exports_ruby_js_ruby_runtime_rb_iseq_drop_own(exports_ruby_js_ruby_runtime_own_rb_iseq_t handle);
141-
142-
extern exports_ruby_js_ruby_runtime_own_rb_iseq_t exports_ruby_js_ruby_runtime_rb_iseq_new(exports_ruby_js_ruby_runtime_rb_iseq_t *rep);
143-
extern exports_ruby_js_ruby_runtime_rb_iseq_t* exports_ruby_js_ruby_runtime_rb_iseq_rep(exports_ruby_js_ruby_runtime_own_rb_iseq_t handle);
144-
void exports_ruby_js_ruby_runtime_rb_iseq_destructor(exports_ruby_js_ruby_runtime_rb_iseq_t *rep);
145-
146129
extern void exports_ruby_js_ruby_runtime_rb_abi_value_drop_own(exports_ruby_js_ruby_runtime_own_rb_abi_value_t handle);
147130

148131
extern exports_ruby_js_ruby_runtime_own_rb_abi_value_t exports_ruby_js_ruby_runtime_rb_abi_value_new(exports_ruby_js_ruby_runtime_rb_abi_value_t *rep);
Binary file not shown.

packages/gems/js/ext/js/bindgen/legacy/rb-abi-guest.c

Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,6 @@ size_t new_size
1414
return ret;
1515
}
1616

17-
__attribute__((import_module("canonical_abi"), import_name("resource_drop_rb-iseq")))
18-
void __resource_rb_iseq_drop(uint32_t idx);
19-
20-
void rb_abi_guest_rb_iseq_free(rb_abi_guest_rb_iseq_t *ptr) {
21-
__resource_rb_iseq_drop(ptr->idx);
22-
}
23-
24-
__attribute__((import_module("canonical_abi"), import_name("resource_clone_rb-iseq")))
25-
uint32_t __resource_rb_iseq_clone(uint32_t idx);
26-
27-
rb_abi_guest_rb_iseq_t rb_abi_guest_rb_iseq_clone(rb_abi_guest_rb_iseq_t *ptr) {
28-
return (rb_abi_guest_rb_iseq_t){__resource_rb_iseq_clone(ptr->idx)};
29-
}
30-
31-
__attribute__((import_module("canonical_abi"), import_name("resource_new_rb-iseq")))
32-
uint32_t __resource_rb_iseq_new(uint32_t val);
33-
34-
rb_abi_guest_rb_iseq_t rb_abi_guest_rb_iseq_new(void *data) {
35-
return (rb_abi_guest_rb_iseq_t){__resource_rb_iseq_new((uint32_t) data)};
36-
}
37-
38-
__attribute__((import_module("canonical_abi"), import_name("resource_get_rb-iseq")))
39-
uint32_t __resource_rb_iseq_get(uint32_t idx);
40-
41-
void* rb_abi_guest_rb_iseq_get(rb_abi_guest_rb_iseq_t *ptr) {
42-
return (void*) __resource_rb_iseq_get(ptr->idx);
43-
}
44-
45-
__attribute__((export_name("canonical_abi_drop_rb-iseq")))
46-
void __resource_rb_iseq_dtor(uint32_t val) {
47-
if (rb_abi_guest_rb_iseq_dtor)
48-
rb_abi_guest_rb_iseq_dtor((void*) val);
49-
}
50-
5117
__attribute__((import_module("canonical_abi"), import_name("resource_drop_rb-abi-value")))
5218
void __resource_rb_abi_value_drop(uint32_t idx);
5319

@@ -127,25 +93,10 @@ __attribute__((export_name("ruby-show-version: func() -> ()")))
12793
void __wasm_export_rb_abi_guest_ruby_show_version(void) {
12894
rb_abi_guest_ruby_show_version();
12995
}
130-
__attribute__((export_name("ruby-init: func() -> ()")))
131-
void __wasm_export_rb_abi_guest_ruby_init(void) {
132-
rb_abi_guest_ruby_init();
133-
}
134-
__attribute__((export_name("ruby-sysinit: func(args: list<string>) -> ()")))
135-
void __wasm_export_rb_abi_guest_ruby_sysinit(int32_t arg, int32_t arg0) {
96+
__attribute__((export_name("ruby-init: func(args: list<string>) -> ()")))
97+
void __wasm_export_rb_abi_guest_ruby_init(int32_t arg, int32_t arg0) {
13698
rb_abi_guest_list_string_t arg1 = (rb_abi_guest_list_string_t) { (rb_abi_guest_string_t*)(arg), (size_t)(arg0) };
137-
rb_abi_guest_ruby_sysinit(&arg1);
138-
}
139-
__attribute__((export_name("ruby-options: func(args: list<string>) -> handle<rb-iseq>")))
140-
int32_t __wasm_export_rb_abi_guest_ruby_options(int32_t arg, int32_t arg0) {
141-
rb_abi_guest_list_string_t arg1 = (rb_abi_guest_list_string_t) { (rb_abi_guest_string_t*)(arg), (size_t)(arg0) };
142-
rb_abi_guest_rb_iseq_t ret = rb_abi_guest_ruby_options(&arg1);
143-
return (ret).idx;
144-
}
145-
__attribute__((export_name("ruby-script: func(name: string) -> ()")))
146-
void __wasm_export_rb_abi_guest_ruby_script(int32_t arg, int32_t arg0) {
147-
rb_abi_guest_string_t arg1 = (rb_abi_guest_string_t) { (char*)(arg), (size_t)(arg0) };
148-
rb_abi_guest_ruby_script(&arg1);
99+
rb_abi_guest_ruby_init(&arg1);
149100
}
150101
__attribute__((export_name("ruby-init-loadpath: func() -> ()")))
151102
void __wasm_export_rb_abi_guest_ruby_init_loadpath(void) {

packages/gems/js/ext/js/bindgen/legacy/rb-abi-guest.h

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,6 @@ extern "C"
88
#include <stdint.h>
99
#include <stdbool.h>
1010

11-
typedef struct {
12-
uint32_t idx;
13-
} rb_abi_guest_rb_iseq_t;
14-
void rb_abi_guest_rb_iseq_free(rb_abi_guest_rb_iseq_t *ptr);
15-
rb_abi_guest_rb_iseq_t rb_abi_guest_rb_iseq_clone(rb_abi_guest_rb_iseq_t *ptr);
16-
rb_abi_guest_rb_iseq_t rb_abi_guest_rb_iseq_new(void *data);
17-
void* rb_abi_guest_rb_iseq_get(rb_abi_guest_rb_iseq_t *ptr);
18-
19-
__attribute__((weak))
20-
void rb_abi_guest_rb_iseq_dtor(void *data);
21-
2211
typedef struct {
2312
uint32_t idx;
2413
} rb_abi_guest_rb_abi_value_t;
@@ -56,10 +45,7 @@ extern "C"
5645
} rb_abi_guest_list_rb_abi_value_t;
5746
void rb_abi_guest_list_rb_abi_value_free(rb_abi_guest_list_rb_abi_value_t *ptr);
5847
void rb_abi_guest_ruby_show_version(void);
59-
void rb_abi_guest_ruby_init(void);
60-
void rb_abi_guest_ruby_sysinit(rb_abi_guest_list_string_t *args);
61-
rb_abi_guest_rb_iseq_t rb_abi_guest_ruby_options(rb_abi_guest_list_string_t *args);
62-
void rb_abi_guest_ruby_script(rb_abi_guest_string_t *name);
48+
void rb_abi_guest_ruby_init(rb_abi_guest_list_string_t *args);
6349
void rb_abi_guest_ruby_init_loadpath(void);
6450
void rb_abi_guest_rb_eval_string_protect(rb_abi_guest_string_t *str, rb_abi_guest_tuple2_rb_abi_value_s32_t *ret0);
6551
void rb_abi_guest_rb_funcallv_protect(rb_abi_guest_rb_abi_value_t recv, rb_abi_guest_rb_id_t mid, rb_abi_guest_list_rb_abi_value_t *args, rb_abi_guest_tuple2_rb_abi_value_s32_t *ret0);

packages/gems/js/ext/js/bindgen/legacy/rb-abi-guest.wit

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
resource rb-iseq
21
resource rb-abi-value
32
type rb-errno = s32
43
type rb-id = u32
54

65
ruby-show-version: func()
7-
ruby-init: func()
8-
ruby-sysinit: func(args: list<string>)
9-
ruby-options: func(args: list<string>) -> rb-iseq
10-
ruby-script: func(name: string)
6+
ruby-init: func(args: list<string>)
117
ruby-init-loadpath: func()
128
rb-eval-string-protect: func(str: string) -> tuple<rb-abi-value, s32>
139
rb-funcallv-protect: func(recv: rb-abi-value, mid: rb-id, args: list<rb-abi-value>) -> tuple<rb-abi-value, s32>

packages/gems/js/ext/js/types.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ typedef exports_ruby_js_ruby_runtime_own_rb_abi_value_t
1010
rb_abi_guest_own_rb_abi_value_t;
1111
typedef exports_ruby_js_ruby_runtime_list_borrow_rb_abi_value_t
1212
rb_abi_guest_list_rb_abi_value_t;
13-
typedef exports_ruby_js_ruby_runtime_own_rb_iseq_t rb_abi_guest_rb_iseq_t;
1413
typedef exports_ruby_js_ruby_runtime_rb_id_t rb_abi_guest_rb_id_t;
1514
typedef exports_ruby_js_ruby_runtime_tuple2_own_rb_abi_value_s32_t
1615
rb_abi_guest_tuple2_rb_abi_value_s32_t;

0 commit comments

Comments
 (0)