Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"url": "git+https://github.com/opencor/webapp.git"
},
"type": "module",
"version": "1.20261016.1",
"version": "1.20261016.2",
"engines": {
"bun": ">=1.2.0"
},
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
},
"./style.css": "./dist/opencor.css"
},
"version": "1.20261016.1",
"version": "1.20261016.2",
"libopencorVersion": "1.20261016.1",
"scripts": {
"build": "vite build && bun scripts/generate.version.ts",
Expand Down
45 changes: 12 additions & 33 deletions src/renderer/src/common/initialisation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,11 @@ const importLibOpenCORGlue = async (): Promise<WasmFactory> => {

// Import libOpenCOR's glue from https://opencor.ws, for a host application that doesn't serve it itself (see
// importLibOpenCORGlue()).
// Note: to make its module worker same-origin, we fetch the glue's source, patch its worker-script URL so that it
// points to a same-origin blob URL, and import the patched source from that blob URL.
// Note: to make its pthread workers same-origin, we fetch the glue's source and import it from a same-origin blob URL.
// Indeed, on the Web, the glue spawns each of its pthread workers from a blob that imports the glue's own URL
// (i.e. import.meta.url), so that the workers import the glue from our same-origin blob URL. This also means that
// the blob URL must remain valid since libOpenCOR spawns its pthread workers lazily (on the first simulation run,
// and again whenever no worker is available), so revoking it would prevent the workers from being spawned.

const importLibOpenCORGlueFromOpencorWs = async (): Promise<WasmFactory> => {
const libOpenCORSource = await withRetries('libOpenCOR', async (attempt) => {
Expand All @@ -279,40 +282,16 @@ const importLibOpenCORGlueFromOpencorWs = async (): Promise<WasmFactory> => {
return response.text();
});

// The URL of the worker script, which must be the same glue, but served from a same-origin blob URL.
const libOpenCORUrl = URL.createObjectURL(new Blob([libOpenCORSource], { type: 'text/javascript' }));

const libOpenCORWorkerUrl = URL.createObjectURL(new Blob([libOpenCORSource], { type: 'text/javascript' }));

// Patch the glue's worker-script URL so that its worker is spawned from the same-origin blob URL.

const workerUrlPattern = 'new URL("libopencor.js",import.meta.url)';

if (!libOpenCORSource.includes(workerUrlPattern)) {
// The glue doesn't contain the expected worker-script URL, which means a future version of libOpenCOR generates
// different code. So, import it directly from https://opencor.ws, which works in standard browsers (the worker will
// then be cross-origin, which is allowed with CORS), but may not in restricted ones.
// Note: the worker URL is not used in this case, so it can be revoked.

URL.revokeObjectURL(libOpenCORWorkerUrl);

return importLibOpenCOR(`${libOpenCORWasmBaseUrl}/libopencor.js`);
}
try {
return await importLibOpenCOR(libOpenCORUrl);
} catch (error: unknown) {
// The glue couldn't be imported, so its blob URL is no longer needed and can be revoked.

const patchedLibOpenCORUrl = URL.createObjectURL(
new Blob([libOpenCORSource.replace(workerUrlPattern, JSON.stringify(libOpenCORWorkerUrl))], {
type: 'text/javascript'
})
);
URL.revokeObjectURL(libOpenCORUrl);

try {
return await importLibOpenCOR(patchedLibOpenCORUrl);
} finally {
// The patched glue has now been imported, so its blob URL is no longer needed and can be revoked.
// Note: libOpenCORWorkerUrl, on the other hand, must remain valid since libOpenCOR spawns its module worker lazily
// (on the first simulation run, and again whenever no worker is available), so revoking it now would prevent
// the worker from being spawned.

URL.revokeObjectURL(patchedLibOpenCORUrl);
throw error;
}
};

Expand Down
Loading