From b359b4d41f910de252068eee68703ee0f004ea24 Mon Sep 17 00:00:00 2001 From: mattias Date: Tue, 24 May 2022 08:03:27 +0200 Subject: [PATCH] demo: wasidom: invoke string result --- demo/wasienv/dom/WasiDomTest1.lpr | 35 +++++++++++-- demo/wasienv/dom/wadom_browser.pp | 71 ++++++++++++++++++++++++-- demo/wasienv/dom/wadom_shared.pp | 12 +++-- demo/wasienv/dom/wadom_wasm.pas | 84 +++++++++++++++++++++++++------ 4 files changed, 175 insertions(+), 27 deletions(-) diff --git a/demo/wasienv/dom/WasiDomTest1.lpr b/demo/wasienv/dom/WasiDomTest1.lpr index 2c4c97b..61b72f0 100644 --- a/demo/wasienv/dom/WasiDomTest1.lpr +++ b/demo/wasienv/dom/WasiDomTest1.lpr @@ -7,19 +7,44 @@ program WasiDomTest1; uses SysUtils, wadom_wasm, wadom_shared; +type + + { TBird } + + TBird = class(TJSObject) + public + function GetDouble: double; + end; + +{ TBird } + +function TBird.GetDouble: double; +begin + Result:=InvokeJSDoubleResult('GetDouble',[]); +end; + var obj: TJSObject; d: Double; u: UnicodeString; + Freddy: TBird; begin obj:=TJSObject.CreateFromID(WasiObjIdBird); writeln('AAA1 '); - obj.InvokeJSNoResult('Proc',[]); - writeln('AAA2 '); + u:='äbc'; + + u:=obj.InvokeJSUnicodeStringResult('GetString',[u]); + writeln('AAA2 u="',u,'"'); + exit; - u:='äbc'; - d:=obj.InvokeJSDoubleResult('GetDouble',[u,12345678901]); - writeln('AAA3 ',d); + //obj.InvokeJSNoResult('Proc',[]); + //d:=obj.InvokeJSDoubleResult('GetDouble',[u,12345678901]); + Freddy:=obj.InvokeJSObjResult('CreateChick',TBird,['Freddy']) as TBird; + writeln('AAA3 '); + d:=Freddy.GetDouble; + writeln('AAA4 ',d); + Freddy.Free; + writeln('AAA5 '); end. diff --git a/demo/wasienv/dom/wadom_browser.pp b/demo/wasienv/dom/wadom_browser.pp index 88772bc..a364c5d 100644 --- a/demo/wasienv/dom/wadom_browser.pp +++ b/demo/wasienv/dom/wadom_browser.pp @@ -8,6 +8,7 @@ interface uses sysutils, types, js, web, wasienv, wadom_shared; Type + EWABridge = class(Exception); { TWADomBridge } @@ -16,13 +17,18 @@ Type FGlobalObjects: TJSArray; FLocalObjects: TJSArray; FFreeLocalIds: TJSArray; // free positions in FLocalObjects + FStringResult: string; Protected function FindObject(ObjId: TWasiDomObjectID): TJSObject; virtual; function Invoke_JSResult(ObjId: TWasiDomObjectID; FuncNameP, FuncNameLen, ArgsP: NativeInt; out JSResult: JSValue): TWasiDomResult; virtual; function Invoke_NoResult(ObjId: TWasiDomObjectID; FuncNameP, FuncNameLen, ArgsP, Dummy: NativeInt): TWasiDomResult; virtual; function Invoke_BooleanResult(ObjId: TWasiDomObjectID; FuncNameP, FuncNameLen, ArgsP, ResultP: NativeInt): TWasiDomResult; virtual; function Invoke_DoubleResult(ObjId: TWasiDomObjectID; FuncNameP, FuncNameLen, ArgsP, ResultP: NativeInt): TWasiDomResult; virtual; + function Invoke_StringResult(ObjId: TWasiDomObjectID; FuncNameP, FuncNameLen, ArgsP, ResultP: NativeInt): TWasiDomResult; virtual; function Invoke_ObjectResult(ObjId: TWasiDomObjectID; FuncNameP, FuncNameLen, ArgsP, ResultP: NativeInt): TWasiDomResult; virtual; + function ReleaseObject(ObjId: TWasiDomObjectID): TWasiDomResult; virtual; + function GetStringResult(ResultP: NativeInt): TWasiDomResult; virtual; + function ReleaseStringResult: TWasiDomResult; virtual; function GetInvokeArguments(View: TJSDataView; ArgsP: NativeInt): TJSValueDynArray; virtual; function GetWasiDomResult(const v: jsvalue): TWasiDomResult; Public @@ -63,10 +69,14 @@ end; procedure TWADomBridge.FillImportObject(aObject: TJSObject); begin - aObject[WasiDomInvokeNoResult]:=@Invoke_NoResult; - aObject[WasiDomInvokeBooleanResult]:=@Invoke_BooleanResult; - aObject[WasiDomInvokeDoubleResult]:=@Invoke_DoubleResult; - aObject[WasiDomInvokeObjectResult]:=@Invoke_ObjectResult; + aObject[WasiBridgeFn_InvokeNoResult]:=@Invoke_NoResult; + aObject[WasiBridgeFn_InvokeBooleanResult]:=@Invoke_BooleanResult; + aObject[WasiBridgeFn_InvokeDoubleResult]:=@Invoke_DoubleResult; + aObject[WasiBridgeFn_InvokeStringResult]:=@Invoke_StringResult; + aObject[WasiBridgeFn_GetStringResult]:=@GetStringResult; + aObject[WasiBridgeFn_ReleaseStringResult]:=@ReleaseStringResult; + aObject[WasiBridgeFn_InvokeObjectResult]:=@Invoke_ObjectResult; + aObject[WasiBridgeFn_ReleaseObject]:=@ReleaseObject; end; function TWADomBridge.FindObject(ObjId: TWasiDomObjectID): TJSObject; @@ -163,6 +173,25 @@ begin Result:=WasiDomResult_Double; end; +function TWADomBridge.Invoke_StringResult(ObjId: TWasiDomObjectID; FuncNameP, + FuncNameLen, ArgsP, ResultP: NativeInt): TWasiDomResult; +var + JSResult: JSValue; +begin + // invoke + Result:=Invoke_JSResult(ObjId,FuncNameP,FuncNameLen,ArgsP,JSResult); + if Result<>WasiDomResult_Success then + exit; + // check result type + if jstypeof(JSResult)<>'string' then + exit(GetWasiDomResult(JSResult)); + Result:=WasiDomResult_String; + FStringResult:=String(JSResult); + + // set result length + getModuleMemoryDataView().setInt32(ResultP, length(FStringResult), env.IsLittleEndian); +end; + function TWADomBridge.Invoke_ObjectResult(ObjId: TWasiDomObjectID; FuncNameP, FuncNameLen, ArgsP, ResultP: NativeInt): TWasiDomResult; var @@ -192,6 +221,40 @@ begin Result:=WasiDomResult_Object; end; +function TWADomBridge.ReleaseObject(ObjId: TWasiDomObjectID): TWasiDomResult; +begin + writeln('TWADomBridge.ReleaseObject ',ObjId); + if ObjId<0 then + raise EWABridge.Create('cannot release a global object'); + if ObjId>=FLocalObjects.Length then + raise EWABridge.Create('cannot release unknown object'); + if FLocalObjects[ObjId]=nil then + raise EWABridge.Create('object already released'); + FLocalObjects[ObjId]:=nil; + FFreeLocalIds.push(ObjId); + Result:=WasiDomResult_Success; +end; + +function TWADomBridge.GetStringResult(ResultP: NativeInt): TWasiDomResult; +var + View: TJSDataView; + l, i: SizeInt; +begin + Result:=WasiDomResult_Success; + l:=length(FStringResult); + if l=0 then exit; + View:=getModuleMemoryDataView(); + for i:=0 to l-1 do + View.setUint16(ResultP+2*i,ord(FStringResult[i]),env.IsLittleEndian); + FStringResult:=''; +end; + +function TWADomBridge.ReleaseStringResult: TWasiDomResult; +begin + Result:=WasiDomResult_Success; + FStringResult:=''; +end; + function TWADomBridge.GetInvokeArguments(View: TJSDataView; ArgsP: NativeInt ): TJSValueDynArray; var diff --git a/demo/wasienv/dom/wadom_shared.pp b/demo/wasienv/dom/wadom_shared.pp index aa93405..2b8f4ff 100644 --- a/demo/wasienv/dom/wadom_shared.pp +++ b/demo/wasienv/dom/wadom_shared.pp @@ -47,10 +47,14 @@ const ); WasiDomExportName = 'wasi_dom'; - WasiDomInvokeNoResult = 'invoke_noresult'; - WasiDomInvokeBooleanResult = 'invoke_boolresult'; - WasiDomInvokeDoubleResult = 'invoke_doubleresult'; - WasiDomInvokeObjectResult = 'invoke_objectresult'; + WasiBridgeFn_InvokeNoResult = 'invoke_noresult'; + WasiBridgeFn_InvokeBooleanResult = 'invoke_boolresult'; + WasiBridgeFn_InvokeDoubleResult = 'invoke_doubleresult'; + WasiBridgeFn_InvokeStringResult = 'invoke_stringresult'; + WasiBridgeFn_GetStringResult = 'get_stringresult'; + WasiBridgeFn_ReleaseStringResult = 'release_stringresult'; + WasiBridgeFn_InvokeObjectResult = 'invoke_objectresult'; + WasiBridgeFn_ReleaseObject = 'release_object'; WasiArgNone = 0; WasiArgLongint = 1; diff --git a/demo/wasienv/dom/wadom_wasm.pas b/demo/wasienv/dom/wadom_wasm.pas index 29315a7..75be06c 100644 --- a/demo/wasienv/dom/wadom_wasm.pas +++ b/demo/wasienv/dom/wadom_wasm.pas @@ -56,7 +56,7 @@ Type procedure InvokeJSNoResult(const aName: string; Const Args: Array of const); function InvokeJSBooleanResult(const aName: string; Const Args: Array of const): Boolean; function InvokeJSDoubleResult(const aName: string; Const Args: Array of const): Double; - //function InvokeJSUnicodeStringResult(const aName: string; Const args: Array of const): UnicodeString; + function InvokeJSUnicodeStringResult(const aName: string; Const args: Array of const): UnicodeString; function InvokeJSObjResult(const aName: string; aResultClass: TJSObjectClass; Const args: Array of const): TJSObject; // ToDo: InvokeJSVarRecResult //function InvokeJSUtf8StringResult(const aName: string; Const args: Array of const): String; @@ -65,37 +65,56 @@ Type var JSDocument: TJSObject; // ToDo -function __wasidom_invoke_noresult( +function __wasibridgefn_invoke_noresult( ObjID: TWasiDomObjectID; FuncNameP: PChar; FuncNameLen: longint; ArgP: PByte; Dummy: PByte -): TWasiDomResult; external WasiDomExportName name WasiDomInvokeNoResult; +): TWasiDomResult; external WasiDomExportName name WasiBridgeFn_InvokeNoResult; -function __wasidom_invoke_boolresult( +function __wasibridgefn_invoke_boolresult( ObjID: TWasiDomObjectID; FuncNameP: PChar; FuncNameLen: longint; ArgP: PByte; ResultP: PByte // bytebool -): TWasiDomResult; external WasiDomExportName name WasiDomInvokeBooleanResult; +): TWasiDomResult; external WasiDomExportName name WasiBridgeFn_InvokeBooleanResult; -function __wasidom_invoke_doubleresult( +function __wasibridgefn_invoke_doubleresult( ObjID: TWasiDomObjectID; FuncNameP: PChar; FuncNameLen: longint; ArgP: PByte; ResultP: PByte // double -): TWasiDomResult; external WasiDomExportName name WasiDomInvokeDoubleResult; +): TWasiDomResult; external WasiDomExportName name WasiBridgeFn_InvokeDoubleResult; -function __wasidom_invoke_objectresult( +function __wasibridgefn_invoke_stringresult( + ObjID: TWasiDomObjectID; + FuncNameP: PChar; + FuncNameLen: longint; + ArgP: PByte; + ResultLenP: PNativeInt // length +): TWasiDomResult; external WasiDomExportName name WasiBridgeFn_InvokeStringResult; + +function __wasibridgefn_getstringresult( + ResultP: PByte +): TWasiDomResult; external WasiDomExportName name WasiBridgeFn_GetStringResult; + +function __wasibridgefn_releasestringresult( +): TWasiDomResult; external WasiDomExportName name WasiBridgeFn_ReleaseStringResult; + +function __wasibridgefn_invoke_objectresult( ObjID: TWasiDomObjectID; FuncNameP: PChar; FuncNameLen: longint; ArgP: PByte; ResultP: PByte // nativeint -): TWasiDomResult; external WasiDomExportName name WasiDomInvokeObjectResult; +): TWasiDomResult; external WasiDomExportName name WasiBridgeFn_InvokeObjectResult; + +function __wasibridgefn_release_object( + ObjID: TWasiDomObjectID +): TWasiDomResult; external WasiDomExportName name WasiBridgeFn_ReleaseObject; implementation @@ -423,6 +442,8 @@ end; destructor TJSObject.Destroy; begin + if ObjectID>=0 then + __wasibridgefn_release_object(ObjectID); inherited Destroy; end; @@ -433,11 +454,11 @@ var InvokeArgs: PByte; begin if length(Args)=0 then - aError:=__wasidom_invoke_noresult(ObjectID,PChar(aName),length(aName),nil,nil) + aError:=__wasibridgefn_invoke_noresult(ObjectID,PChar(aName),length(aName),nil,nil) else begin InvokeArgs:=CreateInvokeJSArgs(Args); try - aError:=__wasidom_invoke_noresult(ObjectID,PChar(aName),length(aName),InvokeArgs,nil); + aError:=__wasibridgefn_invoke_noresult(ObjectID,PChar(aName),length(aName),InvokeArgs,nil); finally if InvokeArgs<>nil then FreeMem(InvokeArgs); @@ -454,7 +475,7 @@ var b: bytebool; begin b:=false; - aError:=InvokeJSOneResult(aName,Args,@__wasidom_invoke_boolresult,@b); + aError:=InvokeJSOneResult(aName,Args,@__wasibridgefn_invoke_boolresult,@b); if aError<>WasiDomResult_Boolean then WasiInvokeRaiseResultMismatch(aName,WasiDomResult_Boolean,aError); Result:=b; @@ -466,11 +487,46 @@ var aError: TWasiDomResult; begin Result:=NaN; - aError:=InvokeJSOneResult(aName,Args,@__wasidom_invoke_doubleresult,@Result); + aError:=InvokeJSOneResult(aName,Args,@__wasibridgefn_invoke_doubleresult,@Result); if aError<>WasiDomResult_Double then WasiInvokeRaiseResultMismatch(aName,WasiDomResult_Double,aError); end; +function TJSObject.InvokeJSUnicodeStringResult(const aName: string; + const args: array of const): UnicodeString; +var + ResultLen: NativeInt; + aError: TWasiDomResult; + InvokeArgs: PByte; +begin + ResultLen:=0; + if length(Args)=0 then + aError:=__wasibridgefn_invoke_stringresult(ObjectID,PChar(aName),length(aName),nil,@ResultLen) + else begin + InvokeArgs:=CreateInvokeJSArgs(Args); + try + aError:=__wasibridgefn_invoke_stringresult(ObjectID,PChar(aName),length(aName),InvokeArgs,@ResultLen); + finally + if InvokeArgs<>nil then + FreeMem(InvokeArgs); + end; + end; + if aError<>WasiDomResult_String then + WasiInvokeRaiseResultMismatch(aName,WasiDomResult_String,aError); + if ResultLen=0 then + exit(''); + try + // try to allocate the memory + SetLength(Result,ResultLen); + aError:=WasiDomResult_Success; + finally + if aError<>WasiDomResult_Success then + __wasibridgefn_releasestringresult(); + end; + __wasibridgefn_getstringresult(PByte(Result)); + writeln('TJSObject.InvokeJSUnicodeStringResult Result="',Result,'"'); +end; + function TJSObject.InvokeJSObjResult(const aName: string; aResultClass: TJSObjectClass; const args: array of const): TJSObject; var @@ -479,7 +535,7 @@ var begin Result:=nil; NewObjId:=-1; - aError:=InvokeJSOneResult(aName,Args,@__wasidom_invoke_objectresult,@NewObjId); + aError:=InvokeJSOneResult(aName,Args,@__wasibridgefn_invoke_objectresult,@NewObjId); if aError=WasiDomResult_Null then exit; if aError<>WasiDomResult_Object then