blob: 129432f80c72c87372d06562efba117a0e707660 [file] [log] [blame]
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {defer} from '../base/deferred';
import {assertExists, assertTrue} from '../base/logging';
import * as init_trace_processor from '../gen/trace_processor';
function writeToUIConsole(line: string) {
console.log(line);
}
export interface WasmBridgeRequest {
id: number;
serviceName: string;
methodName: string;
data: Uint8Array;
}
export interface WasmBridgeResponse {
id: number;
success: boolean;
data?: Uint8Array;
}
export class WasmBridge {
// When this promise has resolved it is safe to call callWasm.
whenInitialized: Promise<void>;
private aborted: boolean;
private currentRequestResult: WasmBridgeResponse|null;
private connection: init_trace_processor.Module;
constructor(init: init_trace_processor.InitWasm) {
this.aborted = false;
this.currentRequestResult = null;
const deferredRuntimeInitialized = defer<void>();
this.connection = init({
locateFile: (s: string) => s,
print: writeToUIConsole,
printErr: writeToUIConsole,
onRuntimeInitialized: () => deferredRuntimeInitialized.resolve(),
onAbort: () => this.aborted = true,
});
this.whenInitialized = deferredRuntimeInitialized.then(() => {
const fn = this.connection.addFunction(this.onReply.bind(this), 'viiii');
this.connection.ccall('Initialize', 'void', ['number'], [fn]);
});
}
callWasm(req: WasmBridgeRequest): WasmBridgeResponse {
if (this.aborted) {
return {
id: req.id,
success: false,
data: undefined,
};
}
// TODO(b/124805622): protoio can generate CamelCase names - normalize.
const methodName = req.methodName;
const name = methodName.charAt(0).toLowerCase() + methodName.slice(1);
this.connection.ccall(
`${req.serviceName}_${name}`, // C method name.
'void', // Return type.
['number', 'array', 'number'], // Input args.
[req.id, req.data, req.data.length] // Args.
);
const result = assertExists(this.currentRequestResult);
assertTrue(req.id === result.id);
this.currentRequestResult = null;
return result;
}
// This is invoked from ccall in the same call stack as callWasm.
private onReply(
reqId: number, success: boolean, heapPtr: number, size: number) {
const data = this.connection.HEAPU8.slice(heapPtr, heapPtr + size);
this.currentRequestResult = {
id: reqId,
success,
data,
};
}
}