Browse Source

wasmjob: added class functions cast

mattias 3 years ago
parent
commit
0303bf9da9

+ 19 - 1
demo/wasienv/dom/job_browser.pp

@@ -39,6 +39,7 @@ Type
     function Invoke_StringResult(ObjId: TJOBObjectID; NameP, NameLen, Invoke, ArgsP, ResultP: NativeInt): TJOBResult; virtual;
     function Invoke_ObjectResult(ObjId: TJOBObjectID; NameP, NameLen, Invoke, ArgsP, ResultP: NativeInt): TJOBResult; virtual;
     function Invoke_JSValueResult(ObjId: TJOBObjectID; NameP, NameLen, Invoke, ArgsP, ResultP: NativeInt): TJOBResult; virtual;
+    function Invoke_ArrayStringResult(ObjId: TJOBObjectID; NameP, NameLen, Invoke, ArgsP, ResultP: NativeInt): TJOBResult; virtual;
     function ReleaseObject(ObjId: TJOBObjectID): TJOBResult; virtual;
     function GetStringResult(ResultP: NativeInt): TJOBResult; virtual;
     function ReleaseStringResult: TJOBResult; virtual;
@@ -143,6 +144,7 @@ begin
   aObject[JOBFn_InvokeObjectResult]:=@Invoke_ObjectResult;
   aObject[JOBFn_ReleaseObject]:=@ReleaseObject;
   aObject[JOBFn_InvokeJSValueResult]:=@Invoke_JSValueResult;
+  aObject[JOBFn_InvokeArrayStringResult]:=@Invoke_ArrayStringResult;
 end;
 
 function TJSObjectBridge.FindObject(ObjId: TJOBObjectID): TJSObject;
@@ -406,6 +408,22 @@ begin
   end;
 end;
 
+function TJSObjectBridge.Invoke_ArrayStringResult(ObjId: TJOBObjectID; NameP,
+  NameLen, Invoke, ArgsP, ResultP: NativeInt): TJOBResult;
+var
+  JSResult: JSValue;
+begin
+  // invoke
+  Result:=Invoke_JSResult(ObjId,NameP,NameLen,Invoke,ArgsP,JSResult);
+  if Result<>JOBResult_Success then
+    exit;
+  raise EJOBBridge.Create('TJSObjectBridge.Invoke_ArrayStringResult not yet implemented');
+  // check result type
+  //exit(GetJOBResult(JSResult));
+  Result:=JOBResult_String;
+  if ResultP=0 then ;
+end;
+
 function TJSObjectBridge.ReleaseObject(ObjId: TJOBObjectID): TJOBResult;
 begin
   {$IFDEF VerboseJOB}
@@ -710,7 +728,7 @@ begin
 end;
 
 function TJSObjectBridge.EatCallbackResult(View: TJSDataView;
-  ResultP: TWasmNativeInt): JSValue;
+  ResultP: TWasmNativeInt): jsvalue;
 var
   p: TWasmNativeInt;
   aType: Byte;

+ 12 - 3
demo/wasienv/dom/job_js.pas

@@ -13,6 +13,9 @@ type
 
   IJSDate = interface(IJSObject)
     ['{F12818EA-542E-488C-A3C5-279E05639E9E}']
+    function Create(aYear: NativeInt; aMonth: NativeInt; aDayOfMonth: NativeInt = 1;
+      TheHours: NativeInt = 0; TheMinutes: NativeInt = 0; TheSeconds: NativeInt = 0;
+      TheMilliseconds: NativeInt = 0): IJSDate;
     function toLocaleDateString: UnicodeString; overload; // date in locale timezone, no time
   end;
 
@@ -20,7 +23,8 @@ type
 
   TJSDate = class(TJSObject,IJSDate)
   public
-    class function Create(aYear: NativeInt; aMonth: NativeInt; aDayOfMonth: NativeInt = 1;
+    class function Cast(Intf: IJSObject): IJSDate; overload;
+    function Create(aYear: NativeInt; aMonth: NativeInt; aDayOfMonth: NativeInt = 1;
       TheHours: NativeInt = 0; TheMinutes: NativeInt = 0; TheSeconds: NativeInt = 0;
       TheMilliseconds: NativeInt = 0): IJSDate;
     function toLocaleDateString: UnicodeString; overload; // date in locale timezone, no time
@@ -33,7 +37,12 @@ implementation
 
 { TJSDate }
 
-class function TJSDate.Create(aYear: NativeInt; aMonth: NativeInt;
+class function TJSDate.Cast(Intf: IJSObject): IJSDate;
+begin
+  Result:=TJSDate.JOBCast(Intf);
+end;
+
+function TJSDate.Create(aYear: NativeInt; aMonth: NativeInt;
   aDayOfMonth: NativeInt; TheHours: NativeInt; TheMinutes: NativeInt;
   TheSeconds: NativeInt; TheMilliseconds: NativeInt): IJSDate;
 begin
@@ -46,7 +55,7 @@ begin
 end;
 
 initialization
-  JSDate:=TJSDate.CreateFromID(JOBObjIdDate);
+  JSDate:=TJSDate.JOBCreateFromID(JOBObjIdDate);
 
 end.
 

+ 41 - 35
demo/wasienv/dom/job_wasm.pas

@@ -257,8 +257,8 @@ type
 
   TJSObject = class(TInterfacedObject,IJSObject)
   private
-    FObjectID: TJOBObjectID;
-    FCastSrc: IJSObject;
+    FJOBObjectID: TJOBObjectID;
+    FJOBCastSrc: IJSObject;
   protected
     type
       TJOBInvokeNoResultFunc = function(
@@ -291,11 +291,12 @@ type
     procedure InvokeJS_RaiseResultMismatchStr(const aName: string; const Expected, Actual: string); virtual;
     function CreateInvokeJSArgs(const Args: array of const): PByte; virtual;
   public
-    constructor Cast(Intf: IJSObject);
-    constructor CreateFromID(aID: TJOBObjectID); virtual; // use this only for the owner (it will release it on free)
+    constructor JOBCast(Intf: IJSObject); overload;
+    constructor JOBCreateFromID(aID: TJOBObjectID); virtual; // use this only for the owner (it will release it on free)
+    class function Cast(Intf: IJSObject): IJSObject; overload;
     destructor Destroy; override;
-    property ObjectID: TJOBObjectID read FObjectID;
-    property CastSrc: IJSObject read FCastSrc; // nil means it is the owner, otherwise it is a typecast
+    property JOBObjectID: TJOBObjectID read FJOBObjectID;
+    property JOBCastSrc: IJSObject read FJOBCastSrc; // nil means it is the owner, otherwise it is a typecast
     // call a function
     procedure InvokeJSNoResult(const aName: string; Const Args: Array of const; Invoke: TJOBInvokeType = jiCall); virtual;
     function InvokeJSBooleanResult(const aName: string; Const Args: Array of const; Invoke: TJOBInvokeType = jiCall): Boolean; virtual;
@@ -693,7 +694,7 @@ begin
       inc(p);
       ObjId:=PLongWord(p)^;
       inc(p,4);
-      Result:=aResultClass.CreateFromID(ObjId);
+      Result:=aResultClass.JOBCreateFromID(ObjId);
     end
   else
     raise EJSArgParse.Create(JOBArgNames[p^]);
@@ -754,7 +755,7 @@ begin
       inc(p);
       ObjId:=PLongWord(p)^;
       inc(p,4);
-      Obj:=TJSObject.CreateFromID(ObjId);
+      Obj:=TJSObject.JOBCreateFromID(ObjId);
       Result:=TJOB_Object.Create(Obj);
     end;
   else
@@ -845,7 +846,7 @@ begin
   if Obj=nil then
     Result:=AllocNil
   else
-    Result:=AllocObjId(Obj.ObjectID);
+    Result:=AllocObjId(Obj.JOBObjectID);
 end;
 
 function TJOBCallbackHelper.AllocObjId(ObjId: TJOBObjectID): PByte;
@@ -1059,12 +1060,12 @@ end;
 
 function TJSObject.GetJSObjectID: TJOBObjectID;
 begin
-  Result:=FObjectID;
+  Result:=FJOBObjectID;
 end;
 
 function TJSObject.GetJSObjectCastSrc: IJSObject;
 begin
-  Result:=FCastSrc;
+  Result:=FJOBCastSrc;
 end;
 
 function TJSObject.GetPascalClassName: string;
@@ -1107,11 +1108,11 @@ var
   InvokeArgs: PByte;
 begin
   if length(Args)=0 then
-    Result:=InvokeFunc(ObjectID,PChar(aName),length(aName),InvokeGetToInt[Invoke],nil)
+    Result:=InvokeFunc(JOBObjectID,PChar(aName),length(aName),InvokeGetToInt[Invoke],nil)
   else begin
     InvokeArgs:=CreateInvokeJSArgs(Args);
     try
-      Result:=InvokeFunc(ObjectID,PChar(aName),length(aName),InvokeGetToInt[Invoke],InvokeArgs);
+      Result:=InvokeFunc(JOBObjectID,PChar(aName),length(aName),InvokeGetToInt[Invoke],InvokeArgs);
     finally
       if InvokeArgs<>nil then
         FreeMem(InvokeArgs);
@@ -1126,11 +1127,11 @@ var
   InvokeArgs: PByte;
 begin
   if length(Args)=0 then
-    Result:=InvokeFunc(ObjectID,PChar(aName),length(aName),InvokeGetToInt[Invoke],nil,ResultP)
+    Result:=InvokeFunc(JOBObjectID,PChar(aName),length(aName),InvokeGetToInt[Invoke],nil,ResultP)
   else begin
     InvokeArgs:=CreateInvokeJSArgs(Args);
     try
-      Result:=InvokeFunc(ObjectID,PChar(aName),length(aName),InvokeGetToInt[Invoke],InvokeArgs,ResultP);
+      Result:=InvokeFunc(JOBObjectID,PChar(aName),length(aName),InvokeGetToInt[Invoke],InvokeArgs,ResultP);
     finally
       if InvokeArgs<>nil then
         FreeMem(InvokeArgs);
@@ -1143,7 +1144,7 @@ var
   E: EJSInvoke;
 begin
   E:=EJSInvoke.Create(Msg);
-  E.ObjectID:=ObjectID;
+  E.ObjectID:=JOBObjectID;
   E.FuncName:=aName;
   raise E;
 end;
@@ -1152,8 +1153,8 @@ procedure TJSObject.InvokeJS_RaiseResultMismatch(const aName: string;
   Expected, Actual: TJOBResult);
 begin
   case Actual of
-  JOBResult_UnknownObjId: InvokeJS_Raise(aName,'unknown object id '+IntToStr(ObjectID));
-  JOBResult_NotAFunction: InvokeJS_Raise(aName,'object '+IntToStr(ObjectID)+' does not have a function "'+aName+'"');
+  JOBResult_UnknownObjId: InvokeJS_Raise(aName,'unknown object id '+IntToStr(JOBObjectID));
+  JOBResult_NotAFunction: InvokeJS_Raise(aName,'object '+IntToStr(JOBObjectID)+' does not have a function "'+aName+'"');
   else
     InvokeJS_RaiseResultMismatchStr(aName,JOBResult_Names[Expected],JOBResult_Names[Actual]);
   end;
@@ -1162,7 +1163,7 @@ end;
 procedure TJSObject.InvokeJS_RaiseResultMismatchStr(const aName: string;
   const Expected, Actual: string);
 begin
-  InvokeJS_Raise(aName,'expected '+Expected+', but got '+Actual+' from object '+IntToStr(ObjectID)+' function "'+aName+'"');
+  InvokeJS_Raise(aName,'expected '+Expected+', but got '+Actual+' from object '+IntToStr(JOBObjectID)+' function "'+aName+'"');
 end;
 
 function TJSObject.CreateInvokeJSArgs(const Args: array of const): PByte;
@@ -1551,7 +1552,7 @@ begin
           p^:=JOBArgNil;
           inc(p);
         end else if Obj is TJSObject then
-          AddObjectID(TJSObject(Obj).ObjectID)
+          AddObjectID(TJSObject(Obj).JOBObjectID)
         else if Obj is TJOB_JSValue then
         begin
           JSValue:=TJOB_JSValue(Obj);
@@ -1623,26 +1624,31 @@ begin
   {$ENDIF}
 end;
 
-constructor TJSObject.Cast(Intf: IJSObject);
+constructor TJSObject.JOBCast(Intf: IJSObject);
 begin
-  FObjectID:=Intf.GetJSObjectID;
-  FCastSrc:=Intf.GetJSObjectCastSrc;
-  if FCastSrc=nil then
-    FCastSrc:=Intf;
+  FJOBObjectID:=Intf.GetJSObjectID;
+  FJOBCastSrc:=Intf.GetJSObjectCastSrc;
+  if FJOBCastSrc=nil then
+    FJOBCastSrc:=Intf;
 end;
 
-constructor TJSObject.CreateFromID(aID: TJOBObjectID);
+constructor TJSObject.JOBCreateFromID(aID: TJOBObjectID);
 begin
-  FObjectID:=aID;
+  FJOBObjectID:=aID;
+end;
+
+class function TJSObject.Cast(Intf: IJSObject): IJSObject;
+begin
+  Result:=JOBCast(Intf);
 end;
 
 destructor TJSObject.Destroy;
 begin
-  if FCastSrc<>nil then
-    FCastSrc:=nil
-  else if ObjectID>=0 then
-    __job_release_object(ObjectID);
-  FObjectID:=0;
+  if FJOBCastSrc<>nil then
+    FJOBCastSrc:=nil
+  else if JOBObjectID>=0 then
+    __job_release_object(JOBObjectID);
+  FJOBObjectID:=0;
   inherited Destroy;
 end;
 
@@ -1719,7 +1725,7 @@ begin
   if aError<>JOBResult_Object then
     InvokeJS_RaiseResultMismatch(aName,JOBResult_Object,aError);
 
-  Result:=aResultClass.CreateFromID(NewObjId);
+  Result:=aResultClass.JOBCreateFromID(NewObjId);
 end;
 
 function TJSObject.InvokeJSValueResult(const aName: string;
@@ -1748,7 +1754,7 @@ begin
   JOBResult_Function,
   JOBResult_Object:
     begin
-    Obj:=TJSObject.CreateFromID(PJOBObjectID(p)^);
+    Obj:=TJSObject.JOBCreateFromID(PJOBObjectID(p)^);
     Result:=TJOB_Object.Create(Obj);
     end;
   else
@@ -1943,7 +1949,7 @@ begin
 end;
 
 initialization
-  JSObject:=TJSObject.CreateFromID(JOBObjIdObject) as IJSObject;
+  JSObject:=TJSObject.JOBCreateFromID(JOBObjIdObject) as IJSObject;
 
 end.
 

+ 191 - 7
demo/wasienv/dom/job_web.pas

@@ -6,7 +6,7 @@ unit JOB_Web;
 interface
 
 uses
-  Classes, SysUtils, JOB_Shared, JOB_WAsm;
+  Classes, SysUtils, JOB_Shared, JOB_WAsm, JOB_JS;
 
 type
   IJSEvent = interface;
@@ -17,7 +17,7 @@ type
 
   TJSEventHandler = function(Event: IJSEventListenerEvent): boolean of object;
 
-  IJSEventTarget = interface
+  IJSEventTarget = interface(IJSObject)
     ['{1883145B-C826-47D1-9C63-47546BA536BD}']
     procedure addEventListener(const aName: UnicodeString; const aListener: TJSEventHandler);
   end;
@@ -25,6 +25,7 @@ type
   { TJSEventTarget }
 
   TJSEventTarget = class(TJSObject,IJSEventTarget)
+    class function Cast(Intf: IJSObject): IJSEventTarget; overload;
     procedure addEventListener(const aName: UnicodeString; const aListener: TJSEventHandler);
   end;
 
@@ -40,6 +41,7 @@ type
   { TJSNode }
 
   TJSNode = class(TJSEventTarget,IJSNode)
+    class function Cast(Intf: IJSObject): IJSNode; overload;
     function GetInnerText: UnicodeString;
     procedure SetInnerText(const AValue: UnicodeString);
   end;
@@ -50,28 +52,50 @@ type
     ['{A160069E-378F-4B76-BE64-1979A28B9EEA}']
     function childElementCount : Integer;
     function firstElementChild : IJSElement;
+    function Getid: UnicodeString;
     function GetInnerHTML: UnicodeString;
     function GetName: UnicodeString;
+    function GetOuterHTML: UnicodeString;
     function Get_ClassName: UnicodeString;
+    procedure append(const aNode : IJSElement); overload;
+    procedure append(const aText : UnicodeString); overload;
+    procedure Setid(const AValue: UnicodeString);
     procedure SetInnerHTML(const AValue: UnicodeString);
     procedure SetName(const AValue: UnicodeString);
+    procedure SetOuterHTML(const AValue: UnicodeString);
     procedure Set_ClassName(const AValue: UnicodeString);
     property Name: UnicodeString read GetName write SetName;
     property _ClassName: UnicodeString read Get_ClassName write Set_ClassName;
+    property id : UnicodeString read Getid write Setid;
     property InnerHTML: UnicodeString read GetInnerHTML write SetInnerHTML;
+    property OuterHTML : UnicodeString read GetOuterHTML write SetOuterHTML;
   end;
 
   { TJSElement }
 
   TJSElement = class(TJSNode,IJSElement)
-    function childElementCount : Integer;
-    function firstElementChild : IJSElement;
+  private
+    function Getid: UnicodeString;
     function GetInnerHTML: UnicodeString;
     function GetName: UnicodeString;
+    function GetOuterHTML: UnicodeString;
     function Get_ClassName: UnicodeString;
+    procedure Setid(const AValue: UnicodeString);
     procedure SetInnerHTML(const AValue: UnicodeString);
     procedure SetName(const AValue: UnicodeString);
+    procedure SetOuterHTML(const AValue: UnicodeString);
     procedure Set_ClassName(const AValue: UnicodeString);
+  public
+    class function Cast(Intf: IJSObject): IJSElement; overload;
+    procedure append(const aText : UnicodeString); overload;
+    procedure append(const aNode : IJSElement); overload;
+    function childElementCount : Integer;
+    function firstElementChild : IJSElement;
+    property Name : UnicodeString read GetName write SetName;
+    property _className : UnicodeString read Get_ClassName write Set_ClassName;
+    property id : UnicodeString read Getid write Setid;
+    property InnerHTML : UnicodeString read GetInnerHTML write SetInnerHTML;
+    property OuterHTML : UnicodeString read GetOuterHTML write SetOuterHTML;
   end;
 
   { IJSEvent }
@@ -85,20 +109,33 @@ type
   { TJSEvent }
 
   TJSEvent = class(TJSObject,IJSEvent)
+    class function Cast(Intf: IJSObject): IJSEvent; overload;
     function CurrentTargetElement: IJSElement;
     function TargetElement: IJSElement;
   end;
 
+  { IJSUIEvent }
+
   IJSUIEvent = interface(IJSEvent)
     ['{A1234998-5180-4905-B820-10FAB9B2DD12}']
   end;
+
+  { TJSUIEvent }
+
   TJSUIEvent = class(TJSEvent,IJSUIEvent)
+    class function Cast(Intf: IJSObject): IJSUIEvent; overload;
   end;
 
+  { IJSMouseEvent }
+
   IJSMouseEvent = interface(IJSUIEvent)
     ['{B91DC727-1164-43AE-8481-55421D3148C4}']
   end;
+
+  { TJSMouseEvent }
+
   TJSMouseEvent = class(TJSUIEvent,IJSMouseEvent)
+    class function Cast(Intf: IJSObject): IJSMouseEvent; overload;
   end;
 
   TJSHTMLClickEventHandler = function(aEvent: IJSMouseEvent) : boolean of object;
@@ -107,24 +144,62 @@ type
 
   IJSHTMLElement = interface(IJSElement)
     ['{D50E53E1-5B3B-4DA4-ACB0-1FD0DE32B711}']
+    function Gettitle: UnicodeString;
+    procedure Settitle(const AValue: UnicodeString);
     procedure set_onclick(const h: TJSHTMLClickEventHandler);
+    property title: UnicodeString read Gettitle write Settitle;
   end;
 
   { TJSHTMLElement }
 
   TJSHTMLElement = class(TJSElement,IJSHTMLElement)
+  private
+    function Gettitle: UnicodeString;
+    procedure Settitle(const AValue: UnicodeString);
+  public
+    class function Cast(Intf: IJSObject): IJSHTMLElement; overload;
     procedure set_onclick(const h: TJSHTMLClickEventHandler);
+    property title: UnicodeString read Gettitle write Settitle;
+  end;
+
+  { IJSHTMLButtonElement }
+
+  IJSHTMLButtonElement = interface(IJSHTMLElement)
+    ['{81DC2F80-FEF4-4705-A6DC-A04B2E32B72D}']
+  end;
+
+  { TJSHTMLButtonElement }
+
+  TJSHTMLButtonElement = class(TJSHTMLElement,IJSHTMLButtonElement)
+    class function Cast(Intf: IJSObject): IJSHTMLButtonElement; overload;
+  end;
+
+  { IJSHTMLDivElement }
+
+  IJSHTMLDivElement = interface(IJSHTMLElement)
+    ['{A02A19B2-85B6-4C96-9281-AF90459E1CEC}']
+  end;
+
+  { TJSHTMLDivElement }
+
+  TJSHTMLDivElement = class(TJSHTMLElement,IJSHTMLDivElement)
+    class function Cast(Intf: IJSObject): IJSHTMLDivElement; overload;
   end;
 
+  { IJSDocument }
+
   IJSDocument = interface(IJSNode)
     ['{CC3FB7C1-C4ED-4BBC-80AB-7B6C2989E026}']
+    function createElement(const tagName : UnicodeString) : IJSElement; overload;
     function getElementById(const aID : UnicodeString) : IJSElement;
   end;
 
   { TJSDocument }
 
   TJSDocument = class(TJSNode,IJSDocument)
-    function getElementById(const aID : UnicodeString) : IJSElement;
+    class function Cast(Intf: IJSObject): IJSDocument; overload;
+    function createElement(const tagName : UnicodeString) : IJSElement; overload;
+    function getElementById(const aID : UnicodeString) : IJSElement; overload;
   end;
 
   { IJSWindow }
@@ -138,6 +213,7 @@ type
   { TJSWindow }
 
   TJSWindow = class(TJSObject,IJSWindow)
+    class function Cast(Intf: IJSObject): IJSWindow; overload;
     procedure addEventListener(const aName: UnicodeString; const aListener: TJSEventHandler);
     procedure Alert(Const Msg: UnicodeString);
   end;
@@ -169,8 +245,41 @@ begin
   Result:=H.AllocBool(TJSEventHandler(aMethod)(Event));
 end;
 
+{ TJSHTMLDivElement }
+
+class function TJSHTMLDivElement.Cast(Intf: IJSObject): IJSHTMLDivElement;
+begin
+  Result:=TJSHTMLDivElement.JOBCast(Intf);
+end;
+
+{ TJSHTMLButtonElement }
+
+class function TJSHTMLButtonElement.Cast(Intf: IJSObject): IJSHTMLButtonElement;
+begin
+  Result:=TJSHTMLButtonElement.JOBCast(Intf);
+end;
+
+{ TJSMouseEvent }
+
+class function TJSMouseEvent.Cast(Intf: IJSObject): IJSMouseEvent;
+begin
+  Result:=TJSMouseEvent.JOBCast(Intf);
+end;
+
+{ TJSUIEvent }
+
+class function TJSUIEvent.Cast(Intf: IJSObject): IJSUIEvent;
+begin
+  Result:=TJSUIEvent.JOBCast(Intf);
+end;
+
 { TJSEventTarget }
 
+class function TJSEventTarget.Cast(Intf: IJSObject): IJSEventTarget;
+begin
+  Result:=TJSEventTarget.JOBCast(Intf);
+end;
+
 procedure TJSEventTarget.addEventListener(const aName: UnicodeString;
   const aListener: TJSEventHandler);
 var
@@ -186,6 +295,21 @@ end;
 
 { TJSHTMLElement }
 
+function TJSHTMLElement.Gettitle: UnicodeString;
+begin
+  Result:=ReadJSPropertyUnicodeString('title');
+end;
+
+procedure TJSHTMLElement.Settitle(const AValue: UnicodeString);
+begin
+  WriteJSPropertyUnicodeString('title',AValue);
+end;
+
+class function TJSHTMLElement.Cast(Intf: IJSObject): IJSHTMLElement;
+begin
+  Result:=TJSHTMLElement.JOBCast(Intf);
+end;
+
 procedure TJSHTMLElement.set_onclick(const h: TJSHTMLClickEventHandler);
 var
   cb1: TJOB_Method;
@@ -200,6 +324,11 @@ end;
 
 { TJSEvent }
 
+class function TJSEvent.Cast(Intf: IJSObject): IJSEvent;
+begin
+  Result:=TJSEvent.JOBCast(Intf);
+end;
+
 function TJSEvent.CurrentTargetElement: IJSElement;
 begin
   Result:=ReadJSPropertyObject('currentTargetElement',TJSElement) as IJSElement;
@@ -212,6 +341,11 @@ end;
 
 { TJSNode }
 
+class function TJSNode.Cast(Intf: IJSObject): IJSNode;
+begin
+  Result:=TJSNode.JOBCast(Intf);
+end;
+
 function TJSNode.GetInnerText: UnicodeString;
 begin
   Result:=ReadJSPropertyUnicodeString('innerText');
@@ -224,6 +358,41 @@ end;
 
 { TJSElement }
 
+function TJSElement.Getid: UnicodeString;
+begin
+  Result:=ReadJSPropertyUnicodeString('id');
+end;
+
+function TJSElement.GetOuterHTML: UnicodeString;
+begin
+  Result:=ReadJSPropertyUnicodeString('outerHTML');
+end;
+
+procedure TJSElement.Setid(const AValue: UnicodeString);
+begin
+  WriteJSPropertyUnicodeString('id',AValue);
+end;
+
+procedure TJSElement.SetOuterHTML(const AValue: UnicodeString);
+begin
+  WriteJSPropertyUnicodeString('outerHTML',AValue);
+end;
+
+class function TJSElement.Cast(Intf: IJSObject): IJSElement;
+begin
+  Result:=TJSElement.JOBCast(Intf);
+end;
+
+procedure TJSElement.append(const aText: UnicodeString);
+begin
+  InvokeJSNoResult('append',[aText]);
+end;
+
+procedure TJSElement.append(const aNode: IJSElement);
+begin
+  InvokeJSNoResult('append',[aNode]);
+end;
+
 function TJSElement.childElementCount: Integer;
 begin
   Result:=ReadJSPropertyLongInt('childElementCount');
@@ -266,6 +435,16 @@ end;
 
 { TJSDocument }
 
+class function TJSDocument.Cast(Intf: IJSObject): IJSDocument;
+begin
+  Result:=TJSDocument.JOBCast(Intf);
+end;
+
+function TJSDocument.createElement(const tagName: UnicodeString): IJSElement;
+begin
+  Result:=InvokeJSObjectResult('createElement',[tagName],TJSElement) as IJSElement;
+end;
+
 function TJSDocument.getElementById(const aID: UnicodeString): IJSElement;
 begin
   Result:=InvokeJSObjectResult('getElementById',[aID],TJSElement) as IJSElement;
@@ -273,6 +452,11 @@ end;
 
 { TJSWindow }
 
+class function TJSWindow.Cast(Intf: IJSObject): IJSWindow;
+begin
+  Result:=TJSWindow.JOBCast(Intf);
+end;
+
 procedure TJSWindow.addEventListener(const aName: UnicodeString;
   const aListener: TJSEventHandler);
 var
@@ -292,8 +476,8 @@ begin
 end;
 
 initialization
-  JSDocument:=TJSDocument.CreateFromID(JOBObjIdDocument);
-  JSWindow:=TJSWindow.CreateFromID(JOBObjIdWindow);
+  JSDocument:=TJSDocument.JOBCreateFromID(JOBObjIdDocument);
+  JSWindow:=TJSWindow.JOBCreateFromID(JOBObjIdWindow);
 finalization
   JSDocument.Free;
   JSWindow.Free;