mirror of
https://github.com/fluencelabs/aquavm
synced 2025-03-15 20:40:50 +00:00
AVM client: move embedded wasm into a separate file (#200)
This commit is contained in:
parent
63160dd0f0
commit
91021d8b40
1
avm/client/.gitignore
vendored
1
avm/client/.gitignore
vendored
@ -6,3 +6,4 @@ wasm
|
||||
# this file is auto-generated
|
||||
src/wasm.js
|
||||
src/importObject.ts
|
||||
src/avm.wasm
|
||||
|
@ -2,11 +2,6 @@
|
||||
New-Item -ItemType Directory -Force -Path ./wasm
|
||||
wasm-pack build ../../air-interpreter --no-typescript --release -d ../avm/client/wasm
|
||||
|
||||
$base64string = [Convert]::ToBase64String([IO.File]::ReadAllBytes('./wasm/air_interpreter_client_bg.wasm'))
|
||||
|
||||
$data = "// auto-generated
|
||||
|
||||
module.exports = `"${base64string}`""
|
||||
|
||||
$data | Out-File "./src/wasm.js"
|
||||
|
||||
New-Item -ItemType Directory -Force -Path ./dist
|
||||
cp wasm/air_interpreter_client_bg.wasm dist/avm.wasm
|
||||
cp dist/avm.wasm src/__test__/
|
||||
|
@ -9,16 +9,6 @@
|
||||
wasm-pack build ./air-interpreter --no-typescript --release -d ../avm/client/wasm
|
||||
)
|
||||
|
||||
## base64 on MacOS doesn't have -w option
|
||||
if echo | base64 -w0 > /dev/null 2>&1;
|
||||
then
|
||||
BASE64=$(base64 -w0 wasm/air_interpreter_client_bg.wasm)
|
||||
else
|
||||
BASE64=$(base64 wasm/air_interpreter_client_bg.wasm)
|
||||
fi
|
||||
|
||||
cat << EOF > ./src/wasm.js
|
||||
// auto-generated
|
||||
|
||||
module.exports = "$BASE64";
|
||||
EOF
|
||||
mkdir -p ./dist/
|
||||
cp wasm/air_interpreter_client_bg.wasm dist/avm.wasm
|
||||
cp dist/avm.wasm src/__test__/
|
||||
|
@ -1,4 +1,5 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testPathIgnorePatterns: ['dist'],
|
||||
};
|
||||
|
5806
avm/client/package-lock.json
generated
5806
avm/client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -10,14 +10,15 @@
|
||||
"files": [
|
||||
"dist/*"
|
||||
],
|
||||
"bin": {
|
||||
"copy-avm": "./dist/copyAvm.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "jest"
|
||||
},
|
||||
"private": false,
|
||||
"dependencies": {
|
||||
"base64-js": "1.5.1"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^26.0.23",
|
||||
"@types/node": "^14.0.0",
|
||||
|
@ -1,9 +1,13 @@
|
||||
import { AirInterpreter } from '..';
|
||||
import { readFileSync } from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const vmPeerId = '12D3KooWNzutuy8WHXDKFqFsATvCR6j9cj2FijYbnd47geRKaQZS';
|
||||
|
||||
const createTestInterpreter = async () => {
|
||||
return AirInterpreter.create('off', (level, message) => {
|
||||
const file = readFileSync(path.resolve(__dirname, './avm.wasm'));
|
||||
const module = await WebAssembly.compile(file);
|
||||
return AirInterpreter.create(module, 'off', (level, message) => {
|
||||
console.log(`level: ${level}, message=${message}`);
|
||||
});
|
||||
};
|
||||
|
33
avm/client/src/copyAvm.ts
Normal file
33
avm/client/src/copyAvm.ts
Normal file
@ -0,0 +1,33 @@
|
||||
#! /usr/bin/env node
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const firstArgument = process.argv[2];
|
||||
|
||||
if (!firstArgument) {
|
||||
console.log(`Expected exactly 1 argument, got 0. Usage: ${path.basename(process.argv[1])} <destination directory>`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let destPath = firstArgument;
|
||||
if (!path.isAbsolute(destPath)) {
|
||||
destPath = path.join(process.cwd(), destPath);
|
||||
}
|
||||
|
||||
const wasmName = 'avm.wasm';
|
||||
const packageName = '@fluencelabs/avm';
|
||||
|
||||
const modulePath = require.resolve(packageName);
|
||||
const source = path.join(path.dirname(modulePath), wasmName);
|
||||
const dest = path.join(destPath, wasmName);
|
||||
|
||||
console.log('ensure directory exists: ', destPath);
|
||||
fs.mkdirSync(destPath, { recursive: true });
|
||||
|
||||
console.log('copying AVM wasm');
|
||||
console.log('from: ', source);
|
||||
console.log('to: ', dest);
|
||||
fs.copyFileSync(source, dest);
|
||||
|
||||
console.log('done!');
|
@ -14,9 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { toByteArray } from 'base64-js';
|
||||
import { getStringFromWasm0, invoke } from './wrapper';
|
||||
import wasmBs64 from './wasm';
|
||||
|
||||
export type LogLevel = 'info' | 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'off';
|
||||
|
||||
@ -82,28 +80,34 @@ class HostImportsConfig {
|
||||
}
|
||||
}
|
||||
|
||||
const interpreter_wasm = toByteArray(wasmBs64);
|
||||
|
||||
/// Instantiates WebAssembly runtime with AIR interpreter module
|
||||
async function interpreterInstance(cfg: HostImportsConfig, logFunction: LogFunction): Promise<Instance> {
|
||||
/// Create host imports that use module exports internally
|
||||
/**
|
||||
* Instantiates WebAssembly runtime with AIR interpreter module
|
||||
*/
|
||||
async function interpreterInstance(
|
||||
module: WebAssembly.Module,
|
||||
cfg: HostImportsConfig,
|
||||
logFunction: LogFunction,
|
||||
): Promise<Instance> {
|
||||
// create host imports that use module exports internally
|
||||
let imports = cfg.newImportObject();
|
||||
|
||||
/// Instantiate interpreter
|
||||
let interpreter_module = await WebAssembly.compile(interpreter_wasm);
|
||||
// instantiate interpreter
|
||||
let interpreter_module = module;
|
||||
let instance: Instance = await WebAssembly.instantiate(interpreter_module, imports);
|
||||
|
||||
/// Set exports, so host imports can use them
|
||||
// set exports, so host imports can use them
|
||||
cfg.setExports(instance.exports);
|
||||
|
||||
/// Trigger interpreter initialization (i.e., call main function)
|
||||
// trigger interpreter initialization (i.e., call main function)
|
||||
call_export(instance.exports.main, logFunction);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// If export is a function, call it. Otherwise log a warning.
|
||||
/// NOTE: any here is unavoidable, see Function interface definition
|
||||
/**
|
||||
* If export is a function, call it. Otherwise log a warning.
|
||||
* NOTE: any here is unavoidable, see Function interface definition
|
||||
*/
|
||||
function call_export(f: ExportValue, logFunction: LogFunction): any {
|
||||
if (typeof f === 'function') {
|
||||
return f();
|
||||
@ -146,13 +150,18 @@ function log_import(cfg: HostImportsConfig, logFunction: LogFunction): LogImport
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns import object that describes host functions called by AIR interpreter
|
||||
/**
|
||||
* Returns import object that describes host functions called by AIR interpreter
|
||||
*/
|
||||
function newImportObject(cfg: HostImportsConfig, logFunction: LogFunction): ImportObject {
|
||||
return {
|
||||
host: log_import(cfg, logFunction),
|
||||
};
|
||||
}
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
const encoder = new TextEncoder();
|
||||
|
||||
export class AirInterpreter {
|
||||
private wasmWrapper;
|
||||
private logLevel: LogLevel;
|
||||
@ -161,12 +170,12 @@ export class AirInterpreter {
|
||||
this.wasmWrapper = wasmWrapper;
|
||||
}
|
||||
|
||||
static async create(logLevel: LogLevel, logFunction: LogFunction) {
|
||||
static async create(module: WebAssembly.Module, logLevel: LogLevel, logFunction: LogFunction) {
|
||||
const cfg = new HostImportsConfig((cfg) => {
|
||||
return newImportObject(cfg, logFunction);
|
||||
});
|
||||
|
||||
const instance = await interpreterInstance(cfg, logFunction);
|
||||
const instance = await interpreterInstance(module, cfg, logFunction);
|
||||
const res = new AirInterpreter(instance);
|
||||
res.logLevel = logLevel;
|
||||
return res;
|
||||
@ -187,7 +196,7 @@ export class AirInterpreter {
|
||||
};
|
||||
}
|
||||
|
||||
const paramsToPass = Buffer.from(
|
||||
const paramsToPass = encoder.encode(
|
||||
JSON.stringify({
|
||||
init_peer_id: params.initPeerId,
|
||||
current_peer_id: params.currentPeerId,
|
||||
@ -201,7 +210,7 @@ export class AirInterpreter {
|
||||
prevData,
|
||||
data,
|
||||
paramsToPass,
|
||||
Buffer.from(JSON.stringify(callResultsToPass)),
|
||||
encoder.encode(JSON.stringify(callResultsToPass)),
|
||||
this.logLevel,
|
||||
);
|
||||
|
||||
@ -210,7 +219,7 @@ export class AirInterpreter {
|
||||
result = JSON.parse(rawResult);
|
||||
} catch (ex) {}
|
||||
|
||||
const callRequestsStr = new TextDecoder().decode(Buffer.from(result.call_requests));
|
||||
const callRequestsStr = decoder.decode(new Uint8Array(result.call_requests));
|
||||
let parsedCallRequests;
|
||||
try {
|
||||
if (callRequestsStr.length === 0) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user