* Let the StartWebAssembly return a promise, allow to initialize library

This commit is contained in:
Michael Van Canneyt 2023-06-13 19:05:06 +02:00
parent 6e630afa75
commit c85aad66f4
2 changed files with 52 additions and 11 deletions

View File

@ -307,7 +307,10 @@ type
// Standard FPC exports.
TWASIExports = Class External name 'Object' (TJSModulesExports)
Public
// Program
Procedure start; external name '_start';
// Library
Procedure initialize; external name '_initialize';
function AllocMem(aSize : Integer) : Integer; external name 'wasiAlloc';
function freeMem(aLocation : Integer) : Integer; external name 'wasiFree';
end;
@ -497,6 +500,8 @@ type
FReadLineCount : Integer;
FRunEntryFunction: String;
FTableDescriptor : TJSWebAssemblyTableDescriptor;
function GetIsLibrary: Boolean;
function GetIsProgram: Boolean;
function GetStartDescriptorReady: Boolean;
function GetUseSharedMemory: Boolean;
procedure SetPredefinedConsoleInput(AValue: TStrings);
@ -539,7 +544,7 @@ type
// Load and start webassembly. If DoRun is true, then Webassembly entry point is called.
// If aBeforeStart is specified, then it is called prior to calling run, and can disable running.
// If aAfterStart is specified, then it is called after calling run. It is not called if running was disabled.
Procedure StartWebAssembly(aPath: string; DoRun: Boolean; aBeforeStart: TBeforeStartCallback; aAfterStart: TAfterStartCallback);
function StartWebAssembly(aPath: string; DoRun: Boolean; aBeforeStart: TBeforeStartCallback; aAfterStart: TAfterStartCallback) : TJSPromise;
// Run the prepared descriptor
Procedure RunPreparedDescriptor;
// Initial memory descriptor
@ -554,7 +559,10 @@ type
Property StartDescriptorReady : Boolean Read GetStartDescriptorReady;
// Default console input
Property PredefinedConsoleInput : TStrings Read FPredefinedConsoleInput Write SetPredefinedConsoleInput;
// Is it a library ?
Property IsLibrary : Boolean Read GetIsLibrary;
// Is it a program ?
Property IsProgram : Boolean Read GetIsProgram;
// Name of function to run. If empty, the FPC default _start is used.
Property RunEntryFunction : String Read FRunEntryFunction Write FRunEntryFunction;
// Called after webassembly start was run. Not called if webassembly was not run.
@ -622,6 +630,16 @@ begin
Result:=Assigned(Memory) and Assigned(Module);
end;
function TWASIHost.GetIsLibrary: Boolean;
begin
Result:=Assigned(FExported.functions['_initialize']);
end;
function TWASIHost.GetIsProgram: Boolean;
begin
Result:=Assigned(FExported.functions['_start']);
end;
procedure TWASIHost.SetUseSharedMemory(AValue: Boolean);
begin
FMemoryDescriptor.shared:=aValue;
@ -707,6 +725,21 @@ begin
WriteOutput(aOutput);
end;
function ValueToMessage(Res : JSValue) : string;
begin
if isObject(Res) then
begin
Result:=TObject(Res).ClassName;
if TObject(Res) is Exception then
Result:=Result+': '+Exception(Res).Message
end;
if (JsTypeOf(Res)='object') and (TJSObject(Res).hasOwnProperty('message')) then
Result:=String(TJSObject(Res)['message'])
else
Result:=TJSJSON.Stringify(Res);
end;
function TWASIHost.CreateWebAssembly(aPath: string; aImportObject: TJSObject
): TJSPromise;
@ -718,8 +751,12 @@ function TWASIHost.CreateWebAssembly(aPath: string; aImportObject: TJSObject
Function InstantiateFail(Res : JSValue) : JSValue;
var
S : String;
begin
Result:=False;
console.Log('Instantiating of WebAssembly from '+aPath+' failed '+ValueToMessage(Res));
DoInstantiateFail(res);
end;
@ -739,6 +776,7 @@ function TWASIHost.CreateWebAssembly(aPath: string; aImportObject: TJSObject
function DoFail(res : jsValue) : JSValue;
begin
Result:=False;
console.Log('Loading of WebAssembly from '+aPath+' failed '+ValueToMessage(Res));
DoLoadFail(res);
end;
@ -802,7 +840,7 @@ begin
Result:=RunWebAssemblyInstance(aBeforeStart,aAfterStart,Nil);
end;
procedure TWASIHost.StartWebAssembly(aPath: string; DoRun: Boolean; aBeforeStart: TBeforeStartCallback; aAfterStart: TAfterStartCallback);
function TWASIHost.StartWebAssembly(aPath: string; DoRun: Boolean; aBeforeStart: TBeforeStartCallback; aAfterStart: TAfterStartCallback) : TJSPromise;
Var
WASD : TWebAssemblyStartDescriptor;
@ -813,7 +851,6 @@ Var
InstResult : TJSInstantiateResult absolute aValue;
begin
Result:=True;
if not (jsTypeOf(aValue)='object') then
Raise EWasiError.Create('Did not get a instantiated webassembly');
WASD.Instance:=InstResult.Instance;
@ -822,13 +859,17 @@ Var
WASD.CallRun:=Procedure(aExports : TWASIExports)
begin
if FRunEntryFunction='' then
aExports.Start
if Assigned(aExports['_initialize']) then
aExports.initialize
else
aExports.Start
else
TProcedure(aExports[RunEntryFunction])();
end;
PrepareWebAssemblyInstance(WASD);
if DoRun then
RunWebAssemblyInstance(aBeforeStart,aAfterStart,Nil);
Result:=TJSPromise.resolve(WASD);
end;
function DoFail(aValue: JSValue): JSValue;
@ -844,7 +885,7 @@ begin
// Clear current descriptor.
FPreparedStartDescriptor:=Default(TWebAssemblyStartDescriptor);
WASD:=InitStartDescriptor(GetMemory,GetTable,Nil);
CreateWebAssembly(aPath,WASD.Imports)._then(@initEnv,@DoFail).catch(@DoFail);
Result:=CreateWebAssembly(aPath,WASD.Imports)._then(@initEnv,@DoFail).catch(@DoFail);
end;
procedure TWASIHost.RunPreparedDescriptor;

View File

@ -5,7 +5,7 @@ unit wasihostapp;
interface
uses
Classes, SysUtils, browserapp, webassembly, wasienv;
Classes, SysUtils, browserapp, js, webassembly, wasienv;
Type
@ -41,7 +41,7 @@ Type
// Load and start webassembly. If DoRun is true, then Webassembly entry point is called.
// If aBeforeStart is specified, then it is called prior to calling run, and can disable running.
// If aAfterStart is specified, then it is called after calling run. It is not called is running was disabled.
Procedure StartWebAssembly(aPath: string; DoRun : Boolean = True; aBeforeStart : TBeforeStartCallback = Nil; aAfterStart : TAfterStartCallback = Nil);
function StartWebAssembly(aPath: string; DoRun : Boolean = True; aBeforeStart : TBeforeStartCallback = Nil; aAfterStart : TAfterStartCallback = Nil) : TJSPromise;
// Initial memory descriptor
Property MemoryDescriptor : TJSWebAssemblyMemoryDescriptor Read GetMemoryDescriptor Write SetMemoryDescriptor;
// Import/export table descriptor
@ -179,11 +179,11 @@ begin
inherited Destroy;
end;
procedure TBrowserWASIHostApplication.StartWebAssembly(aPath: string; DoRun: Boolean;
aBeforeStart: TBeforeStartCallback = nil; aAfterStart: TAfterStartCallback = nil);
function TBrowserWASIHostApplication.StartWebAssembly(aPath: string; DoRun: Boolean;
aBeforeStart: TBeforeStartCallback = nil; aAfterStart: TAfterStartCallback = nil) : TJSPromise;
begin
FHost.StartWebAssembly(aPath,DoRun,aBeforeStart,aAfterStart);
Result:=FHost.StartWebAssembly(aPath,DoRun,aBeforeStart,aAfterStart);
end;
end.