Przeglądaj źródła

demo: wasidom: invoke string result

mattias 3 lat temu
rodzic
commit
b359b4d41f

+ 30 - 5
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.
 

+ 67 - 4
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

+ 8 - 4
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;

+ 70 - 14
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