mirror of
https://gitlab.com/freepascal.org/fpc/pas2js.git
synced 2025-04-05 21:47:47 +02:00
wasmjob: global objects via names
This commit is contained in:
parent
264336babc
commit
25172f1dd1
@ -3,8 +3,7 @@ program BrowserButton1;
|
||||
{$mode objfpc}
|
||||
|
||||
uses
|
||||
BrowserConsole, BrowserApp, JS, Classes, SysUtils, Web, WebAssembly, Types,
|
||||
WasiEnv, WasiHostApp, JOB_Shared, JOB_Browser;
|
||||
BrowserConsole, JS, Classes, SysUtils, Web, WasiEnv, WasiHostApp, JOB_Browser;
|
||||
|
||||
Type
|
||||
|
||||
@ -16,7 +15,7 @@ Type
|
||||
function OnBeforeStart(Sender: TObject;
|
||||
aDescriptor: TWebAssemblyStartDescriptor): Boolean;
|
||||
Public
|
||||
Constructor Create(aOwner : TComponent); override;
|
||||
constructor Create(aOwner : TComponent); override;
|
||||
procedure DoRun; override;
|
||||
end;
|
||||
|
||||
@ -35,7 +34,6 @@ begin
|
||||
end;
|
||||
|
||||
procedure TMyApplication.DoRun;
|
||||
|
||||
begin
|
||||
// Your code here
|
||||
StartWebAssembly('WasiButton1.wasm',true,@OnBeforeStart);
|
||||
|
@ -14,10 +14,11 @@
|
||||
<UseAppBundle Value="False"/>
|
||||
<ResourceType Value="res"/>
|
||||
</General>
|
||||
<CustomData Count="3">
|
||||
<CustomData Count="4">
|
||||
<Item0 Name="MaintainHTML" Value="1"/>
|
||||
<Item1 Name="Pas2JSProject" Value="1"/>
|
||||
<Item2 Name="PasJSWebBrowserProject" Value="1"/>
|
||||
<Item2 Name="PasJSLocation" Value="BrowserDomTest1"/>
|
||||
<Item3 Name="PasJSWebBrowserProject" Value="1"/>
|
||||
</CustomData>
|
||||
<BuildModes>
|
||||
<Item Name="Default" Default="True"/>
|
||||
|
@ -3,8 +3,7 @@ program BrowserDomTest1;
|
||||
{$mode objfpc}
|
||||
|
||||
uses
|
||||
BrowserConsole, BrowserApp, JS, Classes, SysUtils, Web, WebAssembly, Types,
|
||||
wasienv, job_shared, JOB_Browser;
|
||||
BrowserConsole, JS, Classes, SysUtils, Web, WasiEnv, WasiHostApp, JOB_Browser, JOB_Shared;
|
||||
|
||||
Type
|
||||
|
||||
@ -28,20 +27,13 @@ Type
|
||||
|
||||
{ TMyApplication }
|
||||
|
||||
TMyApplication = class(TBrowserApplication)
|
||||
TMyApplication = class(TBrowserWASIHostApplication)
|
||||
Private
|
||||
FWasiEnv: TPas2JSWASIEnvironment;
|
||||
FMemory : TJSWebAssemblyMemory; // Memory of webassembly
|
||||
FTable : TJSWebAssemblyTable; // Table of exported functions
|
||||
FWADomBridge : TJSObjectBridge;
|
||||
function CreateWebAssembly(Path: string; ImportObject: TJSObject
|
||||
): TJSPromise;
|
||||
procedure DoWrite(Sender: TObject; const aOutput: String);
|
||||
function InitEnv(aValue: JSValue): JSValue;
|
||||
procedure InitWebAssembly;
|
||||
function OnBeforeStart(Sender: TObject;
|
||||
aDescriptor: TWebAssemblyStartDescriptor): Boolean;
|
||||
Public
|
||||
Constructor Create(aOwner : TComponent); override;
|
||||
Destructor Destroy; override;
|
||||
constructor Create(aOwner : TComponent); override;
|
||||
procedure DoRun; override;
|
||||
end;
|
||||
|
||||
@ -119,86 +111,23 @@ begin
|
||||
Result:=Result+']';
|
||||
end;
|
||||
|
||||
function TMyApplication.InitEnv(aValue: JSValue): JSValue;
|
||||
Var
|
||||
Module : TJSInstantiateResult absolute aValue;
|
||||
Exps : TWASIExports;
|
||||
InitFunc: TProc;
|
||||
begin
|
||||
Result:=True;
|
||||
FWasiEnv.Instance:=Module.Instance;
|
||||
Exps := TWASIExports(TJSObject(Module.Instance.exports_));
|
||||
//writeln('TMyApplication.InitEnv wasm exports=',TJSObject.keys(Exps));
|
||||
FWADomBridge.WasiExports:=Exps;
|
||||
|
||||
// init the library
|
||||
InitFunc:=TProc(Exps.functions['_initialize']);
|
||||
InitFunc();
|
||||
end;
|
||||
|
||||
{ TMyApplication }
|
||||
|
||||
procedure TMyApplication.DoWrite(Sender: TObject; const aOutput: String);
|
||||
function TMyApplication.OnBeforeStart(Sender: TObject;
|
||||
aDescriptor: TWebAssemblyStartDescriptor): Boolean;
|
||||
begin
|
||||
Writeln(aOutput);
|
||||
FWADomBridge.WasiExports:=aDescriptor.Exported;
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
constructor TMyApplication.Create(aOwner: TComponent);
|
||||
begin
|
||||
inherited Create(aOwner);
|
||||
FWasiEnv:=TPas2JSWASIEnvironment.Create;
|
||||
FWasiEnv.OnStdErrorWrite:=@DoWrite;
|
||||
FWasiEnv.OnStdOutputWrite:=@DoWrite;
|
||||
FWADomBridge:=TJSObjectBridge.Create(FWasiEnv);
|
||||
FWADomBridge:=TJSObjectBridge.Create(WasiEnvironment);
|
||||
RunEntryFunction:='_initialize';
|
||||
|
||||
if FWADomBridge.RegisterGlobalObject(TJSObject(TBird.Create('Root')))<>JObjIdBird then
|
||||
raise Exception.Create('Root TBird wrong number');
|
||||
end;
|
||||
|
||||
function TMyApplication.CreateWebAssembly(Path: string; ImportObject: TJSObject): TJSPromise;
|
||||
begin
|
||||
Result:=window.fetch(Path)._then(Function (res : jsValue) : JSValue
|
||||
begin
|
||||
Result:=TJSResponse(Res).arrayBuffer._then(Function (res2 : jsValue) : JSValue
|
||||
begin
|
||||
Result:=TJSWebAssembly.instantiate(TJSArrayBuffer(res2),ImportObject);
|
||||
end,Nil)
|
||||
end,Nil
|
||||
);
|
||||
end;
|
||||
|
||||
procedure TMyApplication.InitWebAssembly;
|
||||
|
||||
Var
|
||||
mDesc : TJSWebAssemblyMemoryDescriptor;
|
||||
tDesc: TJSWebAssemblyTableDescriptor;
|
||||
ImportObj : TJSObject;
|
||||
|
||||
begin
|
||||
// Setup memory
|
||||
mDesc.initial:=256;
|
||||
mDesc.maximum:=256;
|
||||
FMemory:=TJSWebAssemblyMemory.New(mDesc);
|
||||
// Setup table
|
||||
tDesc.initial:=0;
|
||||
tDesc.maximum:=0;
|
||||
tDesc.element:='anyfunc';
|
||||
FTable:=TJSWebAssemblyTable.New(tDesc);
|
||||
// Setup ImportObject
|
||||
ImportObj:=new([
|
||||
'js', new([
|
||||
'mem', FMemory,
|
||||
'tbl', FTable
|
||||
])
|
||||
]);
|
||||
FWasiEnv.AddImports(ImportObj);
|
||||
CreateWebAssembly('WasiDomTest1.wasm',ImportObj)._then(@InitEnv);
|
||||
end;
|
||||
|
||||
destructor TMyApplication.Destroy;
|
||||
begin
|
||||
FreeAndNil(FWasiEnv);
|
||||
inherited Destroy;
|
||||
if FWADomBridge.RegisterGlobalObject(TBird.Create('Root'),'Bird')=0 then
|
||||
raise Exception.Create('failed to register TBird');
|
||||
end;
|
||||
|
||||
procedure TMyApplication.DoRun;
|
||||
@ -206,7 +135,7 @@ procedure TMyApplication.DoRun;
|
||||
begin
|
||||
// Your code here
|
||||
Terminate;
|
||||
InitWebAssembly;
|
||||
StartWebAssembly('WasiDomTest1.wasm',true,@OnBeforeStart);
|
||||
end;
|
||||
|
||||
var
|
||||
|
@ -66,7 +66,7 @@ begin
|
||||
|
||||
exit;
|
||||
|
||||
obj:=TJSObject.JOBCreateFromID(JObjIdBird);
|
||||
obj:=TJSObject.JOBCreateGlobal('Bird');
|
||||
obj.WriteJSPropertyUnicodeString('Caption','Root');
|
||||
writeln('AAA1 ');
|
||||
//u:='äbc';
|
||||
|
@ -292,6 +292,7 @@ type
|
||||
public
|
||||
constructor JOBCast(Intf: IJSObject); overload;
|
||||
constructor JOBCreateFromID(aID: TJOBObjectID); virtual; // use this only for the owner (it will release it on free)
|
||||
constructor JOBCreateGlobal(const aID: UnicodeString); virtual;
|
||||
class function Cast(Intf: IJSObject): IJSObject; overload;
|
||||
destructor Destroy; override;
|
||||
property JOBObjectID: TJOBObjectID read FJOBObjectID;
|
||||
@ -439,6 +440,11 @@ function __job_invoke_arraystringresult(
|
||||
ResultLenP: PByte // nativeint
|
||||
): TJOBResult; external JOBExportName name JOBFn_InvokeArrayStringResult;
|
||||
|
||||
function __job_get_global(
|
||||
NameP: PWideChar;
|
||||
NameLen: longint
|
||||
): TJOBObjectID; external JOBExportName name JOBFn_GetGlobal;
|
||||
|
||||
function JOBCallback(const Func: TJOBCallback; Data, Code: Pointer; Args: PByte): PByte;
|
||||
function VarRecToJSValue(const V: TVarRec): TJOB_JSValue;
|
||||
|
||||
@ -1658,6 +1664,13 @@ begin
|
||||
FJOBObjectID:=aID;
|
||||
end;
|
||||
|
||||
constructor TJSObject.JOBCreateGlobal(const aID: UnicodeString);
|
||||
begin
|
||||
FJOBObjectID:=__job_get_global(PWideChar(aID),length(aID));
|
||||
if FJOBObjectID=0 then
|
||||
raise EJSObject.Create('JS object "'+String(aID)+'" is not registered');
|
||||
end;
|
||||
|
||||
class function TJSObject.Cast(Intf: IJSObject): IJSObject;
|
||||
begin
|
||||
Result:=JOBCast(Intf);
|
||||
@ -1989,8 +2002,8 @@ begin
|
||||
end;
|
||||
|
||||
initialization
|
||||
JSObject:=TJSObject.JOBCreateFromID(JOBObjIdObject) as IJSObject;
|
||||
JSDate:=TJSDate.JOBCreateFromID(JOBObjIdDate) as IJSDate;
|
||||
JSObject:=TJSObject.JOBCreateGlobal('Object') as IJSObject;
|
||||
JSDate:=TJSDate.JOBCreateGlobal('Date') as IJSDate;
|
||||
|
||||
end.
|
||||
|
||||
|
@ -6,7 +6,7 @@ unit JOB_Web;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, JOB_Shared, JOB_WAsm, JOB_JS;
|
||||
Classes, SysUtils, JOB_Shared, JOB_JS;
|
||||
|
||||
type
|
||||
IJSEvent = interface;
|
||||
@ -476,8 +476,8 @@ begin
|
||||
end;
|
||||
|
||||
initialization
|
||||
JSDocument:=TJSDocument.JOBCreateFromID(JOBObjIdDocument);
|
||||
JSWindow:=TJSWindow.JOBCreateFromID(JOBObjIdWindow);
|
||||
JSDocument:=TJSDocument.JOBCreateGlobal('document');
|
||||
JSWindow:=TJSWindow.JOBCreateGlobal('window');
|
||||
finalization
|
||||
JSDocument.Free;
|
||||
JSWindow.Free;
|
||||
|
@ -21,7 +21,8 @@ Type
|
||||
TJSObjectBridge = class(TImportExtension)
|
||||
Private
|
||||
FCallbackHandler: TJOBCallback;
|
||||
FGlobalObjects: TJSArray;
|
||||
FGlobalObjects: TJSArray; // id to TJSObject
|
||||
FGlobalNames: TJSObject; // name to id
|
||||
FLocalObjects: TJSArray;
|
||||
FFreeLocalIds: TJSArray; // free positions in FLocalObjects
|
||||
FStringResult: string;
|
||||
@ -33,6 +34,7 @@ Type
|
||||
function CreateCallbackArgs(View: TJSDataView; const Args: TJSFunctionArguments): TWasmNativeInt; virtual;
|
||||
function EatCallbackResult(View: TJSDataView; ResultP: TWasmNativeInt): jsvalue; virtual;
|
||||
// exports
|
||||
function Get_GlobalID(NameP, NameLen: NativeInt): TJOBObjectID; virtual;
|
||||
function Invoke_NoResult(ObjId: TJOBObjectID; NameP, NameLen, Invoke, ArgsP: NativeInt): TJOBResult; virtual;
|
||||
function Invoke_BooleanResult(ObjId: TJOBObjectID; NameP, NameLen, Invoke, ArgsP, ResultP: NativeInt): TJOBResult; virtual;
|
||||
function Invoke_DoubleResult(ObjId: TJOBObjectID; NameP, NameLen, Invoke, ArgsP, ResultP: NativeInt): TJOBResult; virtual;
|
||||
@ -48,8 +50,9 @@ Type
|
||||
Procedure FillImportObject(aObject: TJSObject); override;
|
||||
Function ImportName: String; override;
|
||||
function FindObject(ObjId: TJOBObjectID): TJSObject; virtual;
|
||||
function FindGlobalObject(const aName: string): TJOBObjectID; virtual; // 0=not found
|
||||
function RegisterLocalObject(Obj: TJSObject): TJOBObjectID; virtual;
|
||||
Function RegisterGlobalObject(Obj: TJSObject): TJOBObjectID; virtual;
|
||||
Function RegisterGlobalObject(Obj: JSValue; const aName: string): TJOBObjectID; virtual;
|
||||
Function GetJOBResult(v: jsvalue): TJOBResult;
|
||||
property CallbackHandler: TJOBCallback read FCallbackHandler write FCallbackHandler;
|
||||
property WasiExports: TWASIExports read FWasiExports write SetWasiExports;
|
||||
@ -99,27 +102,30 @@ constructor TJSObjectBridge.Create(aEnv: TPas2JSWASIEnvironment);
|
||||
begin
|
||||
Inherited Create(aEnv);
|
||||
FGlobalObjects:=TJSArray.new;
|
||||
FGlobalObjects[-JOBObjIdDocument]:=document;
|
||||
FGlobalObjects[-JOBObjIdWindow]:=window;
|
||||
FGlobalObjects[-JOBObjIdConsole]:=console;
|
||||
FGlobalObjects[-JOBObjIdCaches]:=caches;
|
||||
FGlobalObjects[-JOBObjIdObject]:=TJSObject;
|
||||
FGlobalObjects[-JOBObjIdFunction]:=TJSFunction;
|
||||
FGlobalObjects[-JOBObjIdDate]:=TJSDate;
|
||||
FGlobalObjects[-JOBObjIdString]:=TJSString;
|
||||
FGlobalObjects[-JOBObjIdArray]:=TJSArray;
|
||||
FGlobalObjects[-JOBObjIdArrayBuffer]:=TJSArrayBuffer;
|
||||
FGlobalObjects[-JOBObjIdInt8Array]:=TJSInt8Array;
|
||||
FGlobalObjects[-JOBObjIdUint8Array]:=TJSUint8Array;
|
||||
FGlobalObjects[-JOBObjIdUint8ClampedArray]:=TJSUint8ClampedArray;
|
||||
FGlobalObjects[-JOBObjIdInt16Array]:=TJSInt16Array;
|
||||
FGlobalObjects[-JOBObjIdUint16Array]:=TJSUint16Array;
|
||||
FGlobalObjects[-JOBObjIdInt32Array]:=TJSUint32Array;
|
||||
FGlobalObjects[-JOBObjIdFloat32Array]:=TJSFloat32Array;
|
||||
FGlobalObjects[-JOBObjIdFloat64Array]:=TJSFloat64Array;
|
||||
FGlobalObjects[-JOBObjIdJSON]:=TJSJSON;
|
||||
FGlobalObjects[-JOBObjIdPromise]:=TJSPromise;
|
||||
FGlobalObjects.push(nil); // allocate FGlobalObjects[0]
|
||||
FGlobalNames:=TJSObject.new;
|
||||
RegisterGlobalObject(document,'document');
|
||||
RegisterGlobalObject(window,'window');
|
||||
RegisterGlobalObject(console,'console');
|
||||
RegisterGlobalObject(caches,'caches');
|
||||
RegisterGlobalObject(TJSObject,'Object');
|
||||
RegisterGlobalObject(TJSFunction,'Function');
|
||||
RegisterGlobalObject(TJSDate,'Date');
|
||||
RegisterGlobalObject(TJSString,'String');
|
||||
RegisterGlobalObject(TJSArray,'Array');
|
||||
RegisterGlobalObject(TJSArrayBuffer,'ArrayBuffer');
|
||||
RegisterGlobalObject(TJSInt8Array,'Int8Array');
|
||||
RegisterGlobalObject(TJSUint8Array,'Uint8Array');
|
||||
RegisterGlobalObject(TJSUint8ClampedArray,'Uint8ClampedArray');
|
||||
RegisterGlobalObject(TJSInt16Array,'Int16Array');
|
||||
RegisterGlobalObject(TJSUint16Array,'Uint16Array');
|
||||
RegisterGlobalObject(TJSUint32Array,'Uint32Array');
|
||||
RegisterGlobalObject(TJSFloat32Array,'Float32Array');
|
||||
RegisterGlobalObject(TJSFloat64Array,'Float64Array');
|
||||
RegisterGlobalObject(TJSJSON,'JSON');
|
||||
RegisterGlobalObject(TJSPromise,'Promise');
|
||||
FLocalObjects:=TJSArray.new;
|
||||
FLocalObjects.push(nil); // allocate FLocalObjects[0]
|
||||
FFreeLocalIds:=TJSArray.new;
|
||||
end;
|
||||
|
||||
@ -128,13 +134,18 @@ begin
|
||||
Result:=JOBExportName;
|
||||
end;
|
||||
|
||||
function TJSObjectBridge.RegisterGlobalObject(Obj: TJSObject): TJOBObjectID;
|
||||
function TJSObjectBridge.RegisterGlobalObject(Obj: JSValue; const aName: string
|
||||
): TJOBObjectID;
|
||||
begin
|
||||
if FGlobalNames.hasOwnProperty(aName) then
|
||||
raise EJOBBridge.Create('duplicate "'+aName+'"');
|
||||
Result:=-(FGlobalObjects.push(Obj)-1);
|
||||
FGlobalNames[aName]:=Result;
|
||||
end;
|
||||
|
||||
procedure TJSObjectBridge.FillImportObject(aObject: TJSObject);
|
||||
begin
|
||||
aObject[JOBFn_GetGlobal]:=@Get_GlobalID;
|
||||
aObject[JOBFn_InvokeNoResult]:=@Invoke_NoResult;
|
||||
aObject[JOBFn_InvokeBooleanResult]:=@Invoke_BooleanResult;
|
||||
aObject[JOBFn_InvokeDoubleResult]:=@Invoke_DoubleResult;
|
||||
@ -157,6 +168,13 @@ begin
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
function TJSObjectBridge.FindGlobalObject(const aName: string): TJOBObjectID;
|
||||
begin
|
||||
if not FGlobalNames.hasOwnProperty(aName) then
|
||||
exit(0);
|
||||
Result:=NativeInt(FGlobalNames[aName]);
|
||||
end;
|
||||
|
||||
function TJSObjectBridge.RegisterLocalObject(Obj: TJSObject): TJOBObjectID;
|
||||
var
|
||||
NewId: JSValue;
|
||||
@ -770,6 +788,19 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TJSObjectBridge.Get_GlobalID(NameP, NameLen: NativeInt
|
||||
): TJOBObjectID;
|
||||
var
|
||||
View: TJSDataView;
|
||||
aWords: TJSUint16Array;
|
||||
aName: String;
|
||||
begin
|
||||
View:=getModuleMemoryDataView();
|
||||
aWords:=TJSUint16Array.New(View.buffer, NameP, NameLen);
|
||||
aName:=TypedArrayToString(aWords);
|
||||
Result:=FindGlobalObject(aName);
|
||||
end;
|
||||
|
||||
function TJSObjectBridge.GetJOBResult(v: jsvalue): TJOBResult;
|
||||
begin
|
||||
case jstypeof(v) of
|
||||
|
@ -51,6 +51,7 @@ const
|
||||
);
|
||||
|
||||
JOBExportName = 'job';
|
||||
JOBFn_GetGlobal = 'get_registered';
|
||||
JOBFn_InvokeNoResult = 'invoke_noresult';
|
||||
JOBFn_InvokeBooleanResult = 'invoke_boolresult';
|
||||
JOBFn_InvokeDoubleResult = 'invoke_doubleresult';
|
||||
@ -110,30 +111,6 @@ const
|
||||
'New'
|
||||
);
|
||||
|
||||
// JS base classes
|
||||
JOBObjIdDocument = -1;
|
||||
JOBObjIdWindow = -2;
|
||||
JOBObjIdConsole = -3;
|
||||
JOBObjIdCaches = -4;
|
||||
JOBObjIdObject = -5;
|
||||
JOBObjIdFunction = -6;
|
||||
JOBObjIdDate = -7;
|
||||
JOBObjIdString = -8;
|
||||
JOBObjIdArray = -9;
|
||||
JOBObjIdArrayBuffer = -10;
|
||||
JOBObjIdInt8Array = -11;
|
||||
JOBObjIdUint8Array = -12;
|
||||
JOBObjIdUint8ClampedArray = -13;
|
||||
JOBObjIdInt16Array = -13;
|
||||
JOBObjIdUint16Array = -14;
|
||||
JOBObjIdInt32Array = -16;
|
||||
JOBObjIdFloat32Array = -17;
|
||||
JOBObjIdFloat64Array = -18;
|
||||
JOBObjIdJSON = -19;
|
||||
JOBObjIdPromise = -20;
|
||||
|
||||
JObjIdBird = -21;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user