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,
$implcode: implcode,
$impl: null,
$rtti: Object.create(rtl.tSectionRTTI),
$rtti: Object.create(rtl.tSectionRTTI)
};
module.$rtti.$module = module;
if (implcode) module.$impl = {
$module: module,
$rtti: module.$rtti,
$rtti: module.$rtti
};
},
@ -405,6 +405,7 @@ var rtl = {
i.$name = name;
i.$fullname = module.$name+'.'+name;
i.$guid = guid;
i.$guidr = null;
i.$names = fnnames?fnnames:[];
if (rtl.isFunction(initfn)){
// rtti
@ -418,8 +419,65 @@ var rtl = {
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){
'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 = {};
var t = intf;
var item = Object.create(t);
@ -431,13 +489,8 @@ var rtl = {
var intfname = names[i];
var fnname = map[intfname];
if (!fnname) fnname = intfname;
let fn = aclass[fnname];
//console.log('addIntf: intftype='+t.$name+' index='+i+' intfname="'+intfname+'" fnname="'+fnname+'" proc='+typeof(fn));
if (typeof(fn)==="function"){
item[intfname] = function(){ return fn.apply(this.$o,arguments); };
} else {
item[intfname] = function(){ rtl.raiseE('EAbstractError'); };
}
item[intfname] = jmp(aclass[fnname]);
}
t = Object.getPrototypeOf(t);
}while(t!=null);
@ -453,30 +506,31 @@ var rtl = {
if (!item) return null;
// check delegation
//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
var intf = null;
if (obj.$interfaces){
intf = obj.$interfaces[guid];
// intf can be undefined!
//console.log('getIntfG: obj='+obj.$classname+' guid='+guid+' cache='+typeof(intf));
}
if (!intf){
if (!intf){ // intf can be undefined!
intf = Object.create(item);
intf.$o = obj;
if (!obj.$interfaces) obj.$interfaces = {};
obj.$interfaces[guid] = intf;
}
if (query===1){
if (typeof(query)==='object'){
// called by queryIntfT
var o = null;
if (intf.QueryInterface(guid,
if (intf.QueryInterface(rtl.getIntfGUIDR(query),
{get:function(){ return o; }, set:function(v){ o=v; }}) === 0){
return o;
} else {
return null;
}
} else if(query===2){
intf._AddRef();
// called by TObject.GetInterfaceByStr
if (intf.$kind === 'com') intf._AddRef();
}
return intf;
},
@ -485,23 +539,19 @@ var rtl = {
return rtl.getIntfG(obj,intftype.$guid);
},
queryIntfG: function(obj,guid){
return rtl.getIntfG(obj,guid,1);
},
queryIntfT: function(obj,intftype){
return rtl.queryIntfG(obj,intftype.$guid);
return rtl.getIntfG(obj,intftype.$guid,intftype);
},
queryIntfIsT: function(obj,intftype){
var i = rtl.queryIntfG(obj,intftype.$guid);
if (!i) return false;
if (i._Release) i._Release();
if (i.$kind === 'com') i._Release();
return true;
},
asIntfT: function (obj,intftype){
var i = getIntfG(obj,intftype.$guid);
var i = rtl.getIntfG(obj,intftype.$guid);
if (i!==null) return i;
rtl.raiseEInvalidCast();
},
@ -536,10 +586,10 @@ var rtl = {
},
free: function(){
//console.log('rtl.intfRefs.free...');
for (id in this){
for (var id in this){
if (this.hasOwnProperty(id)) this[id]._Release;
}
},
}
},
createIntfRefs: function(){
@ -570,6 +620,10 @@ var rtl = {
if (old!==null){
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;
},
@ -633,6 +687,14 @@ var rtl = {
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){
// type: 0 for references, "refset" for calling refSet(), a function for new type()
// src must not be null
@ -640,7 +702,7 @@ var rtl = {
if (rtl.isFunction(type)){
for (; srcpos<end; srcpos++) dst[dstpos++] = new type(src[srcpos]); // clone record
} 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 {
for (; srcpos<end; srcpos++) dst[dstpos++] = src[srcpos]; // reference
};
@ -669,7 +731,7 @@ var rtl = {
if (index < 0) index = 0;
if (count === undefined) count=srcarray.length;
var end = index+count;
if (end>scrarray.length) end = scrarray.length;
if (end>scrarray.length) end = srcarray.length;
if (index>=end) return [];
if (type===0){
return srcarray.slice(index,end);
@ -1014,7 +1076,7 @@ var rtl = {
$Class: function(name,o){ return this.$Scope(name,rtl.tTypeInfoClass,o); },
$ClassRef: function(name,o){ return this.$inherited(name,rtl.tTypeInfoClassRef,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){
@ -1022,7 +1084,7 @@ var rtl = {
var t = {
name: param[0],
typeinfo: param[1],
flags: (rtl.isNumber(param[2]) ? param[2] : 0),
flags: (rtl.isNumber(param[2]) ? param[2] : 0)
};
return t;
},

View File

@ -632,6 +632,8 @@ function(){
<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>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>
</div>
@ -1629,7 +1631,8 @@ function(){
}
</pre>
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>
<br>
Supported:
@ -1644,8 +1647,9 @@ function(){
</ul>
</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>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 ClassType "supports" an interface, if it itself or one of its
ancestors implements the interface.
@ -1663,17 +1667,15 @@ function(){
<li>IntfVar as IntfType - types must be releated</li>
<li>IntfVar as ClassType - types can be unrelated, nil returns nil,
invalid raises EInvalidCast</li>
<li>ObjVar as IntfType - mode delphi: types must be related,
objfpc: can be unrelated, nil if not found, COM: uses _AddRef</li>
<li>ObjVar as IntfType - can be unrelated, nil if not found, COM: uses _AddRef</li>
</ul>
<li>typecast:</li>
<ul>
<li>IntfType(IntfVar) - must be related</li>
<li>ClassType(IntfVar) - can be unrelated, nil if invalid</li>
<li>IntfType(ObjVar) - mode delphi: must be related,
objfpc: can be unrelated, nil if not found,
<li>IntfType(ObjVar) - nil if not found,
COM: if ObjVar has delegate uses _AddRef</li>
<li>TJSObject(intfvar)</li>
<li>TJSObject(IntfTypeOrVar)</li>
<li>jsvalue(intfvar)</li>
</ul>
<li>Assign operator:</li>
@ -1682,9 +1684,25 @@ function(){
<li>IntfVar:=IntfVar2; - IntfVar2 must be same type or a descendant</li>
<li>IntfVar:=ObjVar; - nil if unsupported</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>
<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>RTTI</li>
<li>RTTI, typeinfo(IntfType), typeinfo(IntfVar)</li>
</ul>
Not yet supported: array of intferfacetype, interface as record member.
</div>
@ -2446,6 +2464,8 @@ End.
For example you can call the class function <i>TJSString.fromCharCode()</i>, but you cannot
call <i>aJSString.fromCharCode()</i>.</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>
</div>