Skip to content

Commit

Permalink
Publish a dual CJS/ESM package with platform-specific loaders
Browse files Browse the repository at this point in the history
  • Loading branch information
t3chguy committed Dec 23, 2024
1 parent b94addf commit 4e55cbd
Show file tree
Hide file tree
Showing 36 changed files with 738 additions and 272 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [Web] Add typescript checking to bindings/wysiwyg-wasm.
- [Web] Update vite and related packages.
- [Web] Simplify build scripts.
- [Web] Publish a dual CJS/ESM package with platform-specific loaders.

# [2.37.14]
- [Android] Have separate modes for parsing HTML for 'editor mode' and 'message mode' using `isEditor: Boolean` parameter.
Expand Down
11 changes: 2 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,8 @@ ios: targets-ios
web:
cd bindings/wysiwyg-wasm && \
yarn && \
yarn build && \
mkdir -p ../../platforms/web/generated && \
cp \
pkg/wysiwyg_bg.wasm \
pkg/wysiwyg_bg.wasm.d.ts \
pkg/wysiwyg.d.ts \
pkg/wysiwyg.js \
../../platforms/web/generated/
cd platforms/web && yarn install && yarn build
yarn build
cd platforms/web && yarn && yarn build

web-format:
cd platforms/web && \
Expand Down
5 changes: 3 additions & 2 deletions bindings/wysiwyg-wasm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ These files should be copied into a web project and imported with code like:

```html
<script type="module">
import init, { some_method_from_rust }
from './generated/matrix_sdk_wysiwyg.js';
TODO this is all wrong
import { initAsync, some_method_from_rust }
from './pkg/matrix_sdk_wysiwyg.js';
async function run() {
await init();
Expand Down
64 changes: 64 additions & 0 deletions bindings/wysiwyg-wasm/index-wasm-esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
Copyright 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/

// @ts-check

/**
* This is the entrypoint on non-node ESM environments which support the ES Module Integration Proposal for WebAssembly [1]
* (such as Element Web).
*
* [1]: https://github.com/webassembly/esm-integration
*/

import * as bindings from './pkg/wysiwyg_bg.js';

// We want to throw an error if the user tries to use the bindings before
// calling `initAsync`.
bindings.__wbg_set_wasm(
new Proxy(
{},
{
get() {
throw new Error(
'@element-hq/matrix-wysiwyg was used before it was initialized. Call `initAsync` first.',
);
},
},
),
);

/**
* Stores a promise of the `loadModule` call
* @type {Promise<void> | null}
*/
let modPromise = null;

/**
* Loads the WASM module asynchronously
*
* @returns {Promise<void>}
*/
async function loadModule() {
const wasm = await import('./pkg/wysiwyg_bg.wasm');
bindings.__wbg_set_wasm(wasm);
wasm.__wbindgen_start();
}

/**
* Load the WebAssembly module in the background, if it has not already been loaded.
*
* Returns a promise which will resolve once the other methods are ready.
*
* @returns {Promise<void>}
*/
export default async function initAsync() {
if (!modPromise) modPromise = loadModule();
await modPromise;
}

// Re-export everything from the generated javascript wrappers
export * from './pkg/wysiwyg_bg.js';
85 changes: 85 additions & 0 deletions bindings/wysiwyg-wasm/index.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
Copyright 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/

// @ts-check

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

const bindings = require("./pkg/wysiwyg_bg.cjs");

const moduleUrl = require.resolve("./pkg/wysiwyg_bg.wasm");

// We want to throw an error if the user tries to use the bindings before
// calling `initAsync`.
bindings.__wbg_set_wasm(
new Proxy(
{},
{
get() {
throw new Error(
'@element-hq/matrix-wysiwyg was used before it was initialized. Call `initAsync` first.',
);
},
},
),
);

/**
* Stores a promise of the `loadModule` call
* @type {Promise<void> | null}
*/
let modPromise = null;

/**
* Loads the WASM module asynchronously
*
* @returns {Promise<void>}
*/
async function loadModule() {
let mod;
if (typeof WebAssembly.compileStreaming === 'function') {
mod = await WebAssembly.compileStreaming(fetch(moduleUrl));
} else {
// Fallback to fetch and compile
const response = await fetch(moduleUrl);
if (!response.ok) {
throw new Error(`Failed to fetch wasm module: ${moduleUrl}`);
}
const bytes = await response.arrayBuffer();
mod = await WebAssembly.compile(bytes);
}

/** @type {{exports: typeof import("./pkg/wysiwyg_bg.wasm.d.ts")}} */
// @ts-expect-error: Typescript doesn't know what the instance exports exactly
const instance = await WebAssembly.instantiate(mod, {
'./wysiwyg_bg.js': bindings,
});

bindings.__wbg_set_wasm(instance.exports);
instance.exports.__wbindgen_start();
}

/**
* Load the WebAssembly module in the background, if it has not already been loaded.
*
* Returns a promise which will resolve once the other methods are ready.
*
* @returns {Promise<void>}
*/
async function initAsync() {
if (!modPromise) modPromise = loadModule();
await modPromise;
}

module.exports = {
// Re-export everything from the generated javascript wrappers
...bindings,
initAsync,
};
17 changes: 17 additions & 0 deletions bindings/wysiwyg-wasm/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
Copyright 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/

export * from './pkg/wysiwyg.d';

/**
* Load the WebAssembly module in the background, if it has not already been loaded.
*
* Returns a promise which will resolve once the other methods are ready.
*
* @returns {Promise<void>}
*/
export function initAsync(): Promise<void>;
85 changes: 85 additions & 0 deletions bindings/wysiwyg-wasm/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
Copyright 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/

// @ts-check

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

import * as bindings from './pkg/wysiwyg_bg.js';

const moduleUrl = new URL(
'./pkg/wysiwyg_bg.wasm?url',
import.meta.url,
);

// We want to throw an error if the user tries to use the bindings before
// calling `initAsync`.
bindings.__wbg_set_wasm(
new Proxy(
{},
{
get() {
throw new Error(
'@element-hq/matrix-wysiwyg was used before it was initialized. Call `initAsync` first.',
);
},
},
),
);

/**
* Stores a promise of the `loadModule` call
* @type {Promise<void> | null}
*/
let modPromise = null;

/**
* Loads the WASM module asynchronously
*
* @returns {Promise<void>}
*/
async function loadModule() {
let mod;
if (typeof WebAssembly.compileStreaming === 'function') {
mod = await WebAssembly.compileStreaming(fetch(moduleUrl));
} else {
// Fallback to fetch and compile
const response = await fetch(moduleUrl);
if (!response.ok) {
throw new Error(`Failed to fetch wasm module: ${moduleUrl}`);
}
const bytes = await response.arrayBuffer();
mod = await WebAssembly.compile(bytes);
}

/** @type {{exports: typeof import("./pkg/wysiwyg_bg.wasm.d.ts")}} */
// @ts-expect-error: Typescript doesn't know what the instance exports exactly
const instance = await WebAssembly.instantiate(mod, {
'./wysiwyg_bg.js': bindings,
});

bindings.__wbg_set_wasm(instance.exports);
instance.exports.__wbindgen_start();
}

/**
* Load the WebAssembly module in the background, if it has not already been loaded.
*
* Returns a promise which will resolve once the other methods are ready.
*
* @returns {Promise<void>}
*/
export async function initAsync() {
if (!modPromise) modPromise = loadModule();
await modPromise;
}

// Re-export everything from the generated javascript wrappers
export * from './pkg/wysiwyg_bg.js';
Loading

0 comments on commit 4e55cbd

Please sign in to comment.