pas2js: changed TGuid to record

git-svn-id: trunk@38792 -
This commit is contained in:
Mattias Gaertner 2018-04-19 12:16:03 +00:00
parent f64115913d
commit 2945f4a3c9
2 changed files with 117 additions and 35 deletions

View File

@ -99,12 +99,12 @@ var rtl = {
$intfcode: intfcode, $intfcode: intfcode,
$implcode: implcode, $implcode: implcode,
$impl: null, $impl: null,
$rtti: Object.create(rtl.tSectionRTTI), $rtti: Object.create(rtl.tSectionRTTI)
}; };
module.$rtti.$module = module; module.$rtti.$module = module;
if (implcode) module.$impl = { if (implcode) module.$impl = {
$module: module, $module: module,
$rtti: module.$rtti, $rtti: module.$rtti
}; };
}, },
@ -405,6 +405,7 @@ var rtl = {
i.$name = name; i.$name = name;
i.$fullname = module.$name+'.'+name; i.$fullname = module.$name+'.'+name;
i.$guid = guid; i.$guid = guid;
i.$guidr = null;
i.$names = fnnames?fnnames:[]; i.$names = fnnames?fnnames:[];
if (rtl.isFunction(initfn)){ if (rtl.isFunction(initfn)){
// rtti // rtti
@ -418,8 +419,65 @@ var rtl = {
return i; return i;
}, },
strToGUIDR: function(s,g){
var p = 0;
function n(l){
var h = s.substr(p,l);
p+=l;
return parseInt(h,16);
}
p+=1; // skip {
g.D1 = n(8);
p+=1; // skip -
g.D2 = n(4);
p+=1; // skip -
g.D3 = n(4);
p+=1; // skip -
if (!g.D4) g.D4=[];
g.D4[0] = n(2);
g.D4[1] = n(2);
p+=1; // skip -
for(var i=2; i<8; i++) g.D4[i] = n(2);
return g;
},
guidrToStr: function(g){
if (g.$intf) return g.$intf.$guid;
function h(n,digits){
return ("0000000"+n.toString(16).toUpperCase()).slice(-digits);
}
var s='{'+h(g.D1,8)+'-'+h(g.D2,4)+'-'+h(g.D3,4)+'-'+h(g.D4[0],2)+h(g.D4[1],2)+'-';
for (var i=2; i<8; i++) s+=h(g.D4[i],2);
s+='}';
return s;
},
createTGUID: function(guid){
var TGuid = (pas.System)?pas.System.TGuid:pas.system.tguid;
var g = rtl.strToGUIDR(guid,new TGuid());
return g;
},
getIntfGUIDR: function(intfTypeOrVar){
if (!intfTypeOrVar) return null;
if (!intfTypeOrVar.$guidr){
var g = rtl.createTGUID(intfTypeOrVar.$guid);
if (!intfTypeOrVar.hasOwnProperty('$guid')) intfTypeOrVar = Object.getPrototypeOf(intfTypeOrVar);
g.$intf = intfTypeOrVar;
intfTypeOrVar.$guidr = g;
}
return intfTypeOrVar.$guidr;
},
addIntf: function (aclass, intf, map){ addIntf: function (aclass, intf, map){
'use strict'; 'use strict';
function jmp(fn){
if (typeof(fn)==="function"){
return function(){ return fn.apply(this.$o,arguments); };
} else {
return function(){ rtl.raiseE('EAbstractError'); };
}
}
if(!map) map = {}; if(!map) map = {};
var t = intf; var t = intf;
var item = Object.create(t); var item = Object.create(t);
@ -431,13 +489,8 @@ var rtl = {
var intfname = names[i]; var intfname = names[i];
var fnname = map[intfname]; var fnname = map[intfname];
if (!fnname) fnname = intfname; if (!fnname) fnname = intfname;
let fn = aclass[fnname];
//console.log('addIntf: intftype='+t.$name+' index='+i+' intfname="'+intfname+'" fnname="'+fnname+'" proc='+typeof(fn)); //console.log('addIntf: intftype='+t.$name+' index='+i+' intfname="'+intfname+'" fnname="'+fnname+'" proc='+typeof(fn));
if (typeof(fn)==="function"){ item[intfname] = jmp(aclass[fnname]);
item[intfname] = function(){ return fn.apply(this.$o,arguments); };
} else {
item[intfname] = function(){ rtl.raiseE('EAbstractError'); };
}
} }
t = Object.getPrototypeOf(t); t = Object.getPrototypeOf(t);
}while(t!=null); }while(t!=null);
@ -453,30 +506,31 @@ var rtl = {
if (!item) return null; if (!item) return null;
// check delegation // check delegation
//console.log('getIntfG: obj='+obj.$classname+' guid='+guid+' query='+query+' item='+typeof(item)); //console.log('getIntfG: obj='+obj.$classname+' guid='+guid+' query='+query+' item='+typeof(item));
if (typeof item === 'function') return item.call(obj); if (typeof item === 'function') return item.call(obj); // COM: contains _AddRef
// check cache // check cache
var intf = null; var intf = null;
if (obj.$interfaces){ if (obj.$interfaces){
intf = obj.$interfaces[guid]; intf = obj.$interfaces[guid];
// intf can be undefined!
//console.log('getIntfG: obj='+obj.$classname+' guid='+guid+' cache='+typeof(intf)); //console.log('getIntfG: obj='+obj.$classname+' guid='+guid+' cache='+typeof(intf));
} }
if (!intf){ if (!intf){ // intf can be undefined!
intf = Object.create(item); intf = Object.create(item);
intf.$o = obj; intf.$o = obj;
if (!obj.$interfaces) obj.$interfaces = {}; if (!obj.$interfaces) obj.$interfaces = {};
obj.$interfaces[guid] = intf; obj.$interfaces[guid] = intf;
} }
if (query===1){ if (typeof(query)==='object'){
// called by queryIntfT
var o = null; var o = null;
if (intf.QueryInterface(guid, if (intf.QueryInterface(rtl.getIntfGUIDR(query),
{get:function(){ return o; }, set:function(v){ o=v; }}) === 0){ {get:function(){ return o; }, set:function(v){ o=v; }}) === 0){
return o; return o;
} else { } else {
return null; return null;
} }
} else if(query===2){ } else if(query===2){
intf._AddRef(); // called by TObject.GetInterfaceByStr
if (intf.$kind === 'com') intf._AddRef();
} }
return intf; return intf;
}, },
@ -485,23 +539,19 @@ var rtl = {
return rtl.getIntfG(obj,intftype.$guid); return rtl.getIntfG(obj,intftype.$guid);
}, },
queryIntfG: function(obj,guid){
return rtl.getIntfG(obj,guid,1);
},
queryIntfT: function(obj,intftype){ queryIntfT: function(obj,intftype){
return rtl.queryIntfG(obj,intftype.$guid); return rtl.getIntfG(obj,intftype.$guid,intftype);
}, },
queryIntfIsT: function(obj,intftype){ queryIntfIsT: function(obj,intftype){
var i = rtl.queryIntfG(obj,intftype.$guid); var i = rtl.queryIntfG(obj,intftype.$guid);
if (!i) return false; if (!i) return false;
if (i._Release) i._Release(); if (i.$kind === 'com') i._Release();
return true; return true;
}, },
asIntfT: function (obj,intftype){ asIntfT: function (obj,intftype){
var i = getIntfG(obj,intftype.$guid); var i = rtl.getIntfG(obj,intftype.$guid);
if (i!==null) return i; if (i!==null) return i;
rtl.raiseEInvalidCast(); rtl.raiseEInvalidCast();
}, },
@ -536,10 +586,10 @@ var rtl = {
}, },
free: function(){ free: function(){
//console.log('rtl.intfRefs.free...'); //console.log('rtl.intfRefs.free...');
for (id in this){ for (var id in this){
if (this.hasOwnProperty(id)) this[id]._Release; if (this.hasOwnProperty(id)) this[id]._Release;
} }
}, }
}, },
createIntfRefs: function(){ createIntfRefs: function(){
@ -570,6 +620,10 @@ var rtl = {
if (old!==null){ if (old!==null){
old._Release(); // Release after AddRef, to avoid double Release if Release creates an exception old._Release(); // Release after AddRef, to avoid double Release if Release creates an exception
} }
} else if (skipAddRef){
if (old!==null){
old._Release(); // value has an AddRef
}
} }
return value; return value;
}, },
@ -633,6 +687,14 @@ var rtl = {
return setLength(arr,2); return setLength(arr,2);
}, },
arrayEq: function(a,b){
if (a===null) return b===null;
if (b===null) return false;
if (a.length!==b.length) return false;
for (var i=0; i<a.length; i++) if (a[i]!==b[i]) return false;
return true;
},
arrayClone: function(type,src,srcpos,end,dst,dstpos){ arrayClone: function(type,src,srcpos,end,dst,dstpos){
// type: 0 for references, "refset" for calling refSet(), a function for new type() // type: 0 for references, "refset" for calling refSet(), a function for new type()
// src must not be null // src must not be null
@ -640,7 +702,7 @@ var rtl = {
if (rtl.isFunction(type)){ if (rtl.isFunction(type)){
for (; srcpos<end; srcpos++) dst[dstpos++] = new type(src[srcpos]); // clone record for (; srcpos<end; srcpos++) dst[dstpos++] = new type(src[srcpos]); // clone record
} else if((typeof(type)==="string") && (type === 'refSet')) { } else if((typeof(type)==="string") && (type === 'refSet')) {
for (; srcpos<end; srcpos++) dst[dstpos++] = refSet(src[srcpos]); // ref set for (; srcpos<end; srcpos++) dst[dstpos++] = rtl.refSet(src[srcpos]); // ref set
} else { } else {
for (; srcpos<end; srcpos++) dst[dstpos++] = src[srcpos]; // reference for (; srcpos<end; srcpos++) dst[dstpos++] = src[srcpos]; // reference
}; };
@ -669,7 +731,7 @@ var rtl = {
if (index < 0) index = 0; if (index < 0) index = 0;
if (count === undefined) count=srcarray.length; if (count === undefined) count=srcarray.length;
var end = index+count; var end = index+count;
if (end>scrarray.length) end = scrarray.length; if (end>scrarray.length) end = srcarray.length;
if (index>=end) return []; if (index>=end) return [];
if (type===0){ if (type===0){
return srcarray.slice(index,end); return srcarray.slice(index,end);
@ -1014,7 +1076,7 @@ var rtl = {
$Class: function(name,o){ return this.$Scope(name,rtl.tTypeInfoClass,o); }, $Class: function(name,o){ return this.$Scope(name,rtl.tTypeInfoClass,o); },
$ClassRef: function(name,o){ return this.$inherited(name,rtl.tTypeInfoClassRef,o); }, $ClassRef: function(name,o){ return this.$inherited(name,rtl.tTypeInfoClassRef,o); },
$Pointer: function(name,o){ return this.$inherited(name,rtl.tTypeInfoPointer,o); }, $Pointer: function(name,o){ return this.$inherited(name,rtl.tTypeInfoPointer,o); },
$Interface: function(name,o){ return this.$Scope(name,rtl.tTypeInfoInterface,o); }, $Interface: function(name,o){ return this.$Scope(name,rtl.tTypeInfoInterface,o); }
}, },
newTIParam: function(param){ newTIParam: function(param){
@ -1022,7 +1084,7 @@ var rtl = {
var t = { var t = {
name: param[0], name: param[0],
typeinfo: param[1], typeinfo: param[1],
flags: (rtl.isNumber(param[2]) ? param[2] : 0), flags: (rtl.isNumber(param[2]) ? param[2] : 0)
}; };
return t; return t;
}, },

View File

@ -632,6 +632,8 @@ function(){
<li>Supported: Assign, pass as argument, equal, not equal, array of record</li> <li>Supported: Assign, pass as argument, equal, not equal, array of record</li>
<li>Not yet implemented: Constants, pointer of record, advanced records, operators.</li> <li>Not yet implemented: Constants, pointer of record, advanced records, operators.</li>
<li>When assigning a record it is cloned. This is compatible with Delphi and FPC.</li> <li>When assigning a record it is cloned. This is compatible with Delphi and FPC.</li>
<li>Since record types are JS objects it is possible to typecast a record type
to the JS Object, e.g. TJSObject(TPoint)</li>
</ul> </ul>
</div> </div>
@ -1629,7 +1631,8 @@ function(){
} }
</pre> </pre>
When an interface is created for an object (here: a Pascal class instance), When an interface is created for an object (here: a Pascal class instance),
for example by using the <i>as</i>-operator "<i>ObjVar as IUnknown</i>", a JS object is created, which for example by using the <i>as</i>-operator "<i>ObjVar as IUnknown</i>",
a JS object is created, which
is an instance of the map object with its <i>$o</i> set to the <i>ObjVar</i>.<br> is an instance of the map object with its <i>$o</i> set to the <i>ObjVar</i>.<br>
<br> <br>
Supported: Supported:
@ -1644,8 +1647,9 @@ function(){
</ul> </ul>
</li> </li>
<li>inheriting</li> <li>inheriting</li>
<li>Contrary to Delphi/FPC the GUIDs are simple string literals, TGUID = string.</li>
<li>An interface without a GUID gets one autogenerated from its name and method names.</li> <li>An interface without a GUID gets one autogenerated from its name and method names.</li>
<li>Contrary to Delphi/FPC you can assign an interface type or var to
the type TGuidString.</li>
<li>a class implementing an interface must not be external</li> <li>a class implementing an interface must not be external</li>
<li>a ClassType "supports" an interface, if it itself or one of its <li>a ClassType "supports" an interface, if it itself or one of its
ancestors implements the interface. ancestors implements the interface.
@ -1663,17 +1667,15 @@ function(){
<li>IntfVar as IntfType - types must be releated</li> <li>IntfVar as IntfType - types must be releated</li>
<li>IntfVar as ClassType - types can be unrelated, nil returns nil, <li>IntfVar as ClassType - types can be unrelated, nil returns nil,
invalid raises EInvalidCast</li> invalid raises EInvalidCast</li>
<li>ObjVar as IntfType - mode delphi: types must be related, <li>ObjVar as IntfType - can be unrelated, nil if not found, COM: uses _AddRef</li>
objfpc: can be unrelated, nil if not found, COM: uses _AddRef</li>
</ul> </ul>
<li>typecast:</li> <li>typecast:</li>
<ul> <ul>
<li>IntfType(IntfVar) - must be related</li> <li>IntfType(IntfVar) - must be related</li>
<li>ClassType(IntfVar) - can be unrelated, nil if invalid</li> <li>ClassType(IntfVar) - can be unrelated, nil if invalid</li>
<li>IntfType(ObjVar) - mode delphi: must be related, <li>IntfType(ObjVar) - nil if not found,
objfpc: can be unrelated, nil if not found,
COM: if ObjVar has delegate uses _AddRef</li> COM: if ObjVar has delegate uses _AddRef</li>
<li>TJSObject(intfvar)</li> <li>TJSObject(IntfTypeOrVar)</li>
<li>jsvalue(intfvar)</li> <li>jsvalue(intfvar)</li>
</ul> </ul>
<li>Assign operator:</li> <li>Assign operator:</li>
@ -1682,9 +1684,25 @@ function(){
<li>IntfVar:=IntfVar2; - IntfVar2 must be same type or a descendant</li> <li>IntfVar:=IntfVar2; - IntfVar2 must be same type or a descendant</li>
<li>IntfVar:=ObjVar; - nil if unsupported</li> <li>IntfVar:=ObjVar; - nil if unsupported</li>
<li>jsvalue:=IntfVar;</li> <li>jsvalue:=IntfVar;</li>
<li>TGUIDVar:=IntfType;</li>
<li>TGUIDVar:=IntfVar;</li>
<li>TGUIDVar:=stringconstant;</li>
<li>TGUIDStringVar:=IntfVar;</li>
<li>StringVar:=GuidVar;</li>
</ul> </ul>
<li>Equal/Inequal operator:</li>
<ul>
<li>IntfVar=nil;</li>
<li>IntfVar=IntfVar2; - must be related</li>
<li>jsvalue=IntfVar;</li>
<li>TGUIDVar=IntfType;</li>
<li>TGUIDVar=IntfVar;</li>
<li>TGUIDVar=string;</li>
<li>TGUIDStringVar=IntfVar;</li>
</ul>
<li>Passing an COMIntfVar to an untyped parameter does not trigger _AddRef, _Release.</li>
<li>Assigned(IntfVar)</li> <li>Assigned(IntfVar)</li>
<li>RTTI</li> <li>RTTI, typeinfo(IntfType), typeinfo(IntfVar)</li>
</ul> </ul>
Not yet supported: array of intferfacetype, interface as record member. Not yet supported: array of intferfacetype, interface as record member.
</div> </div>
@ -2446,6 +2464,8 @@ End.
For example you can call the class function <i>TJSString.fromCharCode()</i>, but you cannot For example you can call the class function <i>TJSString.fromCharCode()</i>, but you cannot
call <i>aJSString.fromCharCode()</i>.</li> call <i>aJSString.fromCharCode()</i>.</li>
<li>An external class can descend from another external class.</li> <li>An external class can descend from another external class.</li>
<li>Since class types are JS objects it is possible to typecast a class type
to the JS Object, e.g. TJSObject(TObject)</li>
</ul> </ul>
</div> </div>