Skip to content

Commit f61c620

Browse files
Select eval style for ruby script tag based on data-eval attr
1 parent 14a4f83 commit f61c620

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

ext/js/lib/js.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ def await(promise)
5151
->(value) { current.transfer(value, :failure) }
5252
)
5353
if @loop == current
54-
raise "JS::Object#await can be called only from evalAsync"
54+
raise ("JS::Object#await can be called only from RubyVM#evalAsync JS API\n" +
55+
"If you are using browser.script.iife.js, please ensure that you specify `data-eval=\"async\"` in your script tag\n" +
56+
"e.g. <script type=\"text/ruby\" data-eval=\"async\">puts :hello</script>\n" +
57+
"Or <script type=\"text/ruby\" data-eval=\"async\" src=\"path/to/script.rb\"></script>")
58+
5559
end
5660
value, status = @loop.transfer
5761
raise JS::Error.new(value) if status == :failure

packages/npm-packages/ruby-wasm-wasi/src/browser.script.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,32 @@ const runRubyScriptsInHtml = async (vm) => {
3333
);
3434

3535
// Run Ruby scripts sequentially.
36-
for await (const rubyScript of promisingRubyScripts) {
37-
if (rubyScript) {
38-
vm.eval(rubyScript);
36+
for await (const script of promisingRubyScripts) {
37+
if (script) {
38+
const { scriptContent, evalStyle } = script;
39+
switch (evalStyle) {
40+
case "async":
41+
vm.evalAsync(scriptContent);
42+
break;
43+
case "sync":
44+
vm.eval(scriptContent);
45+
break;
46+
}
3947
}
4048
}
4149
};
4250

43-
const loadScriptAsync = async (tag: Element): Promise<string> => {
51+
const deriveEvalStyle = (tag: Element): "async" | "sync" => {
52+
const rawEvalStyle = tag.getAttribute("data-eval") || "sync";
53+
if (rawEvalStyle !== "async" && rawEvalStyle !== "sync") {
54+
console.warn(`data-eval attribute of script tag must be "async" or "sync". ${rawEvalStyle} is ignored and "sync" is used instead.`);
55+
return "sync";
56+
}
57+
return rawEvalStyle;
58+
};
59+
60+
const loadScriptAsync = async (tag: Element): Promise<{ scriptContent: string, evalStyle: "async" | "sync" } | null> => {
61+
const evalStyle = deriveEvalStyle(tag);
4462
// Inline comments can be written with the src attribute of the script tag.
4563
// The presence of the src attribute is checked before the presence of the inline.
4664
// see: https://html.spec.whatwg.org/multipage/scripting.html#inline-documentation-for-external-scripts
@@ -49,11 +67,11 @@ const loadScriptAsync = async (tag: Element): Promise<string> => {
4967
const response = await fetch(url);
5068

5169
if (response.ok) {
52-
return await response.text();
70+
return { scriptContent: await response.text(), evalStyle };
5371
}
5472

5573
return Promise.resolve(null);
5674
}
5775

58-
return Promise.resolve(tag.innerHTML);
76+
return Promise.resolve({ scriptContent: tag.innerHTML, evalStyle });
5977
};

0 commit comments

Comments
 (0)