Skip to content

Commit

Permalink
feat(loadmodule): expose locatebinary
Browse files Browse the repository at this point in the history
  • Loading branch information
kwonoj committed Oct 24, 2018
1 parent cca9ed2 commit 606ff1b
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 30 deletions.
5 changes: 3 additions & 2 deletions examples/browser_remote/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//tslint:disable:no-console
//tslint:disable:no-console no-require-imports
import { loadModule } from '../../src/index';
import { enableLogger } from '../../src/util/logger';
import { runCld } from '../runCld';
Expand All @@ -7,7 +7,8 @@ enableLogger(console.log.bind(console));

const runBrowserCld = async () => {
const cldFactory = await loadModule({
binaryRemoteEndpoint: `http://localhost:8888`
//let file-loader resolves wasm binary when bundling
locateBinary: (_wasmPath: string) => require('../../src/lib/cld3_web.wasm')
});

runCld(cldFactory);
Expand Down
5 changes: 1 addition & 4 deletions examples/browser_remote/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ module.exports = {
{
test: /.wasm$/,
type: 'javascript/auto',
loader: 'file-loader',
options: {
name: '[name].[ext]'
}
loader: 'file-loader'
}
]
},
Expand Down
39 changes: 31 additions & 8 deletions spec/cld-asm/loadModule-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jest.mock('emscripten-wasm-loader', () => ({
describe('loadModule', () => {
it('should create moduleLoader on browser', async () => {
const mockModuleLoader = jest.fn();
(isNode as jest.Mock).mockReturnValueOnce(false);
(isNode as jest.Mock).mockReturnValue(false);

(getModuleLoaderMock as jest.Mock).mockImplementationOnce((cb: Function) => {
cb();
Expand All @@ -35,28 +35,51 @@ describe('loadModule', () => {

it('should create module on node', async () => {
const mockModuleLoader = jest.fn();
(isNode as jest.Mock).mockReturnValueOnce(true);
(isNode as jest.Mock).mockReturnValue(true);

(getModuleLoaderMock as jest.Mock).mockReturnValueOnce(mockModuleLoader);
await loadModule();

expect((getModuleLoaderMock as jest.Mock).mock.calls[0][1]).to.equal(nodecld3Mock);
});

it('should use remoteEndpoint on browser', async () => {
it('should use lookupBinary on browser', async () => {
const mockModuleLoader = jest.fn();
(isNode as jest.Mock).mockReturnValueOnce(false);
(isNode as jest.Mock).mockReturnValue(false);

(getModuleLoaderMock as jest.Mock).mockReturnValueOnce(mockModuleLoader);
await loadModule({ binaryRemoteEndpoint: 'dummy' });
await loadModule({ locateBinary: () => 'dummy' });

expect((getModuleLoaderMock as jest.Mock).mock.calls[0][2].locateFile('test.wasm')).to.equal('dummy');
});

it('should use lookupBinary on node', async () => {
const mockModuleLoader = jest.fn();
(isNode as jest.Mock).mockReturnValue(true);

(getModuleLoaderMock as jest.Mock).mockReturnValueOnce(mockModuleLoader);
await loadModule({ locateBinary: () => 'dummy' });

const { locateFile } = (getModuleLoaderMock as jest.Mock).mock.calls[0][2];
expect(locateFile('test.wasm')).to.equal('dummy');
});

it('should not override path for wasm binary on node', async () => {
const mockModuleLoader = jest.fn();
(isNode as jest.Mock).mockReturnValue(true);

(getModuleLoaderMock as jest.Mock).mockImplementationOnce((cb: Function) => {
cb();
return mockModuleLoader;
});
await loadModule();

expect((getModuleLoaderMock as jest.Mock).mock.calls[0][2]).to.be.undefined;
expect((getModuleLoaderMock as jest.Mock).mock.calls[0][3]).to.deep.equal({ binaryRemoteEndpoint: 'dummy' });
});

it('should override path for wasm binary on browser without remote endpoint', async () => {
it('should override path for wasm binary on browser', async () => {
const mockModuleLoader = jest.fn();
(isNode as jest.Mock).mockReturnValueOnce(false);
(isNode as jest.Mock).mockReturnValue(false);

(getModuleLoaderMock as jest.Mock).mockImplementationOnce((cb: Function) => {
cb();
Expand Down
38 changes: 22 additions & 16 deletions src/loadModule.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { getModuleLoader, isNode } from 'emscripten-wasm-loader';
import { ModuleInitOption } from 'emscripten-wasm-loader/dist/types/getModuleLoader';
import { CldAsmModule } from './cldAsmModule';
import { CldFactory } from './cldFactory';
import { cldLoader } from './cldLoader';
Expand All @@ -8,34 +7,41 @@ import { log } from './util/logger';
/**
* Load, initialize wasm / asm.js binary to use actual cld wasm instances.
*
* @param {moduleInitOption} [ModuleInitOption] additional option to configure module loader
* @param [InitOptions] Options to initialize cld3 wasm binary.
* @param {number} [InitOptions.timeout] - timeout to wait wasm binary compilation & load.
* @param {string | object} [InitOptions.locateBinary] - custom resolution logic for wasm binary.
* It could be either remote endpoint url, or loader-returned object for bundler. Check examples/browser_* for references.
*
* @returns {() => Promise<CldFactory>} Function to load module
*/
const loadModule = async (moduleInitOption?: Partial<ModuleInitOption>) => {
const loadModule = async ({
timeout,
locateBinary
}: Partial<{ timeout: number; locateBinary: (filePath: string) => string | object }> = {}) => {
log(`loadModule: loading cld3 module`);

//imports MODULARIZED emscripten preamble
const runtimeModule = isNode() ? require(`./lib/cld3_node`) : require(`./lib/cld3_web`); //tslint:disable-line:no-require-imports no-var-requires

// in Browser environment if remote endpoint is not specified cld3-asm overrides preamble's locateFile to provide wasm binary
// instead of preamble triggers fetch to file:// resource paths.
// Bundler (i.e webpack) should configure proper loader settings for this.
const isPathOverrideRequired = !isNode() && (!moduleInitOption || !moduleInitOption.binaryRemoteEndpoint);
const overriddenModule = !isPathOverrideRequired
? undefined
: {
locateFile: (filePath: string) =>
filePath.endsWith('.wasm')
? require('./lib/cld3_web.wasm') //tslint:disable-line:no-require-imports no-var-requires
: filePath
};
//tslint:disable-next-line:no-require-imports no-var-requires
const lookupBinary = locateBinary || ((_filePath: string) => require('./lib/cld3_web.wasm'));

//Build module object to construct wasm binary module via emscripten preamble.
//This allows to override default wasm binary resolution in preamble.
//By default, cld3-asm overrides to direct require to binary on *browser* environment to allow bundler like webpack resolves it.
//On node, it relies on default resolution logic.
const overriddenModule =
isNode() && !locateBinary
? undefined
: {
locateFile: (filePath: string) => (filePath.endsWith('.wasm') ? lookupBinary(filePath) : filePath)
};

const moduleLoader = await getModuleLoader<CldFactory, CldAsmModule>(
(runtime: CldAsmModule) => cldLoader(runtime),
runtimeModule,
overriddenModule,
moduleInitOption
{ timeout }
);

return moduleLoader();
Expand Down

0 comments on commit 606ff1b

Please sign in to comment.