Skip to content

Commit

Permalink
Fix splitbrain between .js being ESM & CJS inconsistently
Browse files Browse the repository at this point in the history
  • Loading branch information
t3chguy committed Jan 8, 2025
1 parent 23b22c6 commit 58e94ed
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 62 deletions.
File renamed without changes.
File renamed without changes.
26 changes: 12 additions & 14 deletions index.mjs → index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,16 @@
// @ts-check

/**
* This is the entrypoint on non-node ESM environments.
* This is the entrypoint on non-node CommonJS environments.
* `asyncLoad` will load the WASM module using a `fetch` call.
*/

import * as bindings from "./pkg/matrix_sdk_crypto_wasm_bg.js";
const bindings = require("./pkg/matrix_sdk_crypto_wasm_bg.cjs");

const moduleUrl = new URL("./pkg/matrix_sdk_crypto_wasm_bg.wasm", import.meta.url);
const moduleUrl = require.resolve("./pkg/matrix_sdk_crypto_wasm_bg.wasm");

// Although we could simply instantiate the WASM at import time with a top-level `await`,
// we avoid that, to make it easier for callers to delay loading the WASM (and instead
// wait until `initAsync` is called). (Also, Safari 14 doesn't support top-level `await`.)
//
// However, having done so, there is no way to synchronously load the WASM if the user ends
// up using the bindings before calling `initAsync` (unlike under Node.js), so we just throw
// an error.
// We want to throw an error if the user tries to use the bindings before
// calling `initAsync`.
bindings.__wbg_set_wasm(
new Proxy(
{},
Expand All @@ -44,7 +39,7 @@ bindings.__wbg_set_wasm(
);

/**
* Stores a promise of the `loadModuleAsync` call
* Stores a promise of the `loadModule` call
* @type {Promise<void> | null}
*/
let modPromise = null;
Expand Down Expand Up @@ -72,10 +67,13 @@ async function loadModuleAsync() {
*
* @returns {Promise<void>}
*/
export async function initAsync() {
async function initAsync() {
if (!modPromise) modPromise = loadModuleAsync();
await modPromise;
}

// Re-export everything from the generated javascript wrappers
export * from "./pkg/matrix_sdk_crypto_wasm_bg.js";
module.exports = {
// Re-export everything from the generated javascript wrappers
...bindings,
initAsync,
};
26 changes: 14 additions & 12 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,21 @@
// @ts-check

/**
* This is the entrypoint on non-node CommonJS environments.
* This is the entrypoint on non-node ESM environments.
* `asyncLoad` will load the WASM module using a `fetch` call.
*/

const bindings = require("./pkg/matrix_sdk_crypto_wasm_bg.cjs");
import * as bindings from "./pkg/matrix_sdk_crypto_wasm_bg.js";

const moduleUrl = require.resolve("./pkg/matrix_sdk_crypto_wasm_bg.wasm");
const moduleUrl = new URL("./pkg/matrix_sdk_crypto_wasm_bg.wasm", import.meta.url);

// We want to throw an error if the user tries to use the bindings before
// calling `initAsync`.
// Although we could simply instantiate the WASM at import time with a top-level `await`,
// we avoid that, to make it easier for callers to delay loading the WASM (and instead
// wait until `initAsync` is called). (Also, Safari 14 doesn't support top-level `await`.)
//
// However, having done so, there is no way to synchronously load the WASM if the user ends
// up using the bindings before calling `initAsync` (unlike under Node.js), so we just throw
// an error.
bindings.__wbg_set_wasm(
new Proxy(
{},
Expand All @@ -39,7 +44,7 @@ bindings.__wbg_set_wasm(
);

/**
* Stores a promise of the `loadModule` call
* Stores a promise of the `loadModuleAsync` call
* @type {Promise<void> | null}
*/
let modPromise = null;
Expand Down Expand Up @@ -67,13 +72,10 @@ async function loadModuleAsync() {
*
* @returns {Promise<void>}
*/
async function initAsync() {
export async function initAsync() {
if (!modPromise) modPromise = loadModuleAsync();
await modPromise;
}

module.exports = {
// Re-export everything from the generated javascript wrappers
...bindings,
initAsync,
};
// Re-export everything from the generated javascript wrappers
export * from "./pkg/matrix_sdk_crypto_wasm_bg.js";
31 changes: 17 additions & 14 deletions node.mjs → node.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@
// @ts-check

/**
* This is the entrypoint on node-compatible ESM environments.
* This is the entrypoint on node-compatible CommonJS environments.
* `asyncLoad` will use `fs.readFile` to load the WASM module.
*/

import { fileURLToPath } from "node:url";
import { readFileSync } from "node:fs";
import { readFile } from "node:fs/promises";
import * as bindings from "./pkg/matrix_sdk_crypto_wasm_bg.js";
const { readFileSync } = require("node:fs");
const { readFile } = require("node:fs/promises");
const path = require("node:path");
const bindings = require("./pkg/matrix_sdk_crypto_wasm_bg.cjs");

const filename = fileURLToPath(new URL("./pkg/matrix_sdk_crypto_wasm_bg.wasm", import.meta.url));
const filename = path.join(__dirname, "pkg/matrix_sdk_crypto_wasm_bg.wasm");

// In node environments, we want to automatically load the WASM module
// synchronously if the consumer did not call `initAsync`. To do so, we install
Expand Down Expand Up @@ -59,7 +59,7 @@ let initialised = false;
*
* It will throw if there is an attempt to load the module asynchronously running
*
* @returns {typeof import("./pkg/matrix_sdk_crypto_wasm_bg.wasm.d.ts")}
* @returns {typeof import("./pkg/matrix_sdk_crypto_wasm_bg.wasm.d")}

Check failure on line 62 in node.cjs

View workflow job for this annotation

GitHub Actions / test

Type import of an ECMAScript module from a CommonJS module must have a 'resolution-mode' attribute.
*/
function loadModuleSync() {
if (modPromise) throw new Error("The WASM module is being loaded asynchronously but hasn't finished");
Expand All @@ -73,14 +73,14 @@ function loadModuleSync() {

initInstance(instance);

// @ts-expect-error: Typescript doesn't know what the module exports are
// @ts-expect-error: Typescript doesn't know what the instance exports exactly
return instance.exports;
}

/**
* Loads and instantiates the WASM module asynchronously
*
* @returns {Promise<typeof import("./pkg/matrix_sdk_crypto_wasm_bg.wasm.d.ts")>}
* @returns {Promise<typeof import("./pkg/matrix_sdk_crypto_wasm_bg.wasm.d")>}

Check failure on line 83 in node.cjs

View workflow job for this annotation

GitHub Actions / test

Type import of an ECMAScript module from a CommonJS module must have a 'resolution-mode' attribute.
*/
async function loadModuleAsync() {
const bytes = await readFile(filename);
Expand All @@ -91,7 +91,7 @@ async function loadModuleAsync() {

initInstance(instance);

// @ts-expect-error: Typescript doesn't know what the module exports are
// @ts-expect-error: Typescript doesn't know what the instance exports exactly
return instance.exports;
}

Expand All @@ -103,7 +103,7 @@ async function loadModuleAsync() {
function initInstance(instance) {
if (initialised) throw new Error("initInstance called twice");
bindings.__wbg_set_wasm(instance.exports);
// @ts-expect-error: Typescript doesn't know what the module exports are
// @ts-expect-error: Typescript doesn't know what the instance exports exactly
instance.exports.__wbindgen_start();
initialised = true;
}
Expand All @@ -115,11 +115,14 @@ function initInstance(instance) {
*
* @returns {Promise<void>}
*/
export async function initAsync() {
async function initAsync() {
if (initialised) return;
if (!modPromise) modPromise = loadModuleAsync();
await modPromise;
}

// Re-export everything from the generated javascript wrappers
export * from "./pkg/matrix_sdk_crypto_wasm_bg.js";
module.exports = {
// Re-export everything from the generated javascript wrappers
...bindings,
initAsync,
};
31 changes: 14 additions & 17 deletions node.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@
// @ts-check

/**
* This is the entrypoint on node-compatible CommonJS environments.
* This is the entrypoint on node-compatible ESM environments.
* `asyncLoad` will use `fs.readFile` to load the WASM module.
*/

const { readFileSync } = require("node:fs");
const { readFile } = require("node:fs/promises");
const path = require("node:path");
const bindings = require("./pkg/matrix_sdk_crypto_wasm_bg.cjs");
import { fileURLToPath } from "node:url";
import { readFileSync } from "node:fs";
import { readFile } from "node:fs/promises";
import * as bindings from "./pkg/matrix_sdk_crypto_wasm_bg.js";

const filename = path.join(__dirname, "pkg/matrix_sdk_crypto_wasm_bg.wasm");
const filename = fileURLToPath(new URL("./pkg/matrix_sdk_crypto_wasm_bg.wasm", import.meta.url));

// In node environments, we want to automatically load the WASM module
// synchronously if the consumer did not call `initAsync`. To do so, we install
Expand Down Expand Up @@ -59,7 +59,7 @@ let initialised = false;
*
* It will throw if there is an attempt to load the module asynchronously running
*
* @returns {typeof import("./pkg/matrix_sdk_crypto_wasm_bg.wasm.d")}
* @returns {typeof import("./pkg/matrix_sdk_crypto_wasm_bg.wasm.d.ts")}
*/
function loadModuleSync() {
if (modPromise) throw new Error("The WASM module is being loaded asynchronously but hasn't finished");
Expand All @@ -73,14 +73,14 @@ function loadModuleSync() {

initInstance(instance);

// @ts-expect-error: Typescript doesn't know what the instance exports exactly
// @ts-expect-error: Typescript doesn't know what the module exports are
return instance.exports;
}

/**
* Loads and instantiates the WASM module asynchronously
*
* @returns {Promise<typeof import("./pkg/matrix_sdk_crypto_wasm_bg.wasm.d")>}
* @returns {Promise<typeof import("./pkg/matrix_sdk_crypto_wasm_bg.wasm.d.ts")>}
*/
async function loadModuleAsync() {
const bytes = await readFile(filename);
Expand All @@ -91,7 +91,7 @@ async function loadModuleAsync() {

initInstance(instance);

// @ts-expect-error: Typescript doesn't know what the instance exports exactly
// @ts-expect-error: Typescript doesn't know what the module exports are
return instance.exports;
}

Expand All @@ -103,7 +103,7 @@ async function loadModuleAsync() {
function initInstance(instance) {
if (initialised) throw new Error("initInstance called twice");
bindings.__wbg_set_wasm(instance.exports);
// @ts-expect-error: Typescript doesn't know what the instance exports exactly
// @ts-expect-error: Typescript doesn't know what the module exports are
instance.exports.__wbindgen_start();
initialised = true;
}
Expand All @@ -115,14 +115,11 @@ function initInstance(instance) {
*
* @returns {Promise<void>}
*/
async function initAsync() {
export async function initAsync() {
if (initialised) return;
if (!modPromise) modPromise = loadModuleAsync();
await modPromise;
}

module.exports = {
// Re-export everything from the generated javascript wrappers
...bindings,
initAsync,
};
// Re-export everything from the generated javascript wrappers
export * from "./pkg/matrix_sdk_crypto_wasm_bg.js";
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,22 @@
"ruma",
"nio"
],
"type": "module",
"exports": {
".": {
"matrix-org:wasm-esm": {
"types": "./index.d.ts",
"default": "./index-wasm-esm.mjs"
"default": "./index-wasm-esm.js"
},
"require": {
"types": "./index.d.ts",
"node": "./node.js",
"default": "./index.js"
"node": "./node.cjs",
"default": "./index.cjs"
},
"import": {
"types": "./index.d.ts",
"node": "./node.mjs",
"default": "./index.mjs"
"node": "./node.js",
"default": "./index.js"
}
}
},
Expand Down

0 comments on commit 58e94ed

Please sign in to comment.