Skip to content

Commit f939f2d

Browse files
committed
Prevention of double loading
1 parent 554800c commit f939f2d

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

ext/js/lib/js/require_remote.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class RequireRemote
1010

1111
def initialize
1212
set_base_url
13+
@loaded_urls = Set.new
1314
end
1415

1516
# Load the given feature from remote.
@@ -18,11 +19,17 @@ def initialize
1819
# Maps like import maps will be used.
1920
def load(relative_feature, use_maps: false)
2021
location = get_location(relative_feature)
22+
23+
# Do not load the same URL twice.
24+
return false if @loaded_urls.include?(location.url[:href].to_s)
25+
2126
response = JS.global.fetch(location.url).await
2227

2328
if response[:status].to_i == 200
2429
code = response.text().await.to_s
2530
eval_code(code, location)
31+
@loaded_urls << response[:url].to_s
32+
true
2633
else
2734
raise LoadError.new "cannot load such url -- #{location.url}"
2835
end

packages/npm-packages/ruby-wasm-wasi/test-e2e/integrations/browser-script.spec.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,40 @@ if (!process.env.RUBY_NPM_PACKAGE_ROOT) {
6161
});
6262
});
6363

64-
test.describe('JS::RequireRemote#load', () => {
64+
test.describe("JS::RequireRemote#load", () => {
65+
test("JS::RequireRemote#load returns true", async ({ page }) => {
66+
const resolve = await resolveBinding(page, "checkResolved");
67+
await page.goto(
68+
"https://cdn.jsdelivr.net/npm/ruby-head-wasm-wasi@latest/dist/",
69+
);
70+
await page.setContent(`
71+
<script src="browser.script.iife.js"></script>
72+
<script type="text/ruby" data-eval="async">
73+
require 'js/require_remote'
74+
JS.global.checkResolved JS::RequireRemote.instance.load 'error_on_load_twice'
75+
</script>
76+
`);
77+
expect(await resolve()).toBe(true);
78+
});
79+
80+
test("JS::RequireRemote#load returns false when same gem is loaded twice", async ({
81+
page,
82+
}) => {
83+
const resolve = await resolveBinding(page, "checkResolved");
84+
await page.goto(
85+
"https://cdn.jsdelivr.net/npm/ruby-head-wasm-wasi@latest/dist/",
86+
);
87+
await page.setContent(`
88+
<script src="browser.script.iife.js"></script>
89+
<script type="text/ruby" data-eval="async">
90+
require 'js/require_remote'
91+
JS::RequireRemote.instance.load 'error_on_load_twice'
92+
JS.global.checkResolved JS::RequireRemote.instance.load 'error_on_load_twice'
93+
</script>
94+
`);
95+
expect(await resolve()).toBe(false);
96+
});
97+
6598
test("JS::RequireRemote#load throws error when gem is not found", async ({
6699
page,
67100
}) => {

packages/npm-packages/ruby-wasm-wasi/test-e2e/support.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,13 @@ export const setupProxy = (context: BrowserContext) => {
3030
relativePath,
3131
);
3232

33-
if (fs.existsSync(mockedPath)) {
33+
if (relativePath.match("error_on_load_twice.rb")) {
34+
route.fulfill({
35+
body: `raise 'load twice' if defined? ALREADY_LOADED
36+
ALREADY_LOADED = true`,
37+
contentType: "text/ruby",
38+
});
39+
} else if (fs.existsSync(mockedPath)) {
3440
route.fulfill({
3541
path: mockedPath,
3642
});

0 commit comments

Comments
 (0)