|
@@ -0,0 +1,5461 @@
|
|
|
+var pas = { $libimports: {}};
|
|
|
+
|
|
|
+var rtl = {
|
|
|
+
|
|
|
+ version: 20301,
|
|
|
+
|
|
|
+ quiet: false,
|
|
|
+ debug_load_units: false,
|
|
|
+ debug_rtti: false,
|
|
|
+
|
|
|
+ $res : {},
|
|
|
+
|
|
|
+ debug: function(){
|
|
|
+ if (rtl.quiet || !console || !console.log) return;
|
|
|
+ console.log(arguments);
|
|
|
+ },
|
|
|
+
|
|
|
+ error: function(s){
|
|
|
+ rtl.debug('Error: ',s);
|
|
|
+ throw s;
|
|
|
+ },
|
|
|
+
|
|
|
+ warn: function(s){
|
|
|
+ rtl.debug('Warn: ',s);
|
|
|
+ },
|
|
|
+
|
|
|
+ checkVersion: function(v){
|
|
|
+ if (rtl.version != v) throw "expected rtl version "+v+", but found "+rtl.version;
|
|
|
+ },
|
|
|
+
|
|
|
+ hiInt: Math.pow(2,53),
|
|
|
+
|
|
|
+ hasString: function(s){
|
|
|
+ return rtl.isString(s) && (s.length>0);
|
|
|
+ },
|
|
|
+
|
|
|
+ isArray: function(a) {
|
|
|
+ return Array.isArray(a);
|
|
|
+ },
|
|
|
+
|
|
|
+ isFunction: function(f){
|
|
|
+ return typeof(f)==="function";
|
|
|
+ },
|
|
|
+
|
|
|
+ isModule: function(m){
|
|
|
+ return rtl.isObject(m) && rtl.hasString(m.$name) && (pas[m.$name]===m);
|
|
|
+ },
|
|
|
+
|
|
|
+ isImplementation: function(m){
|
|
|
+ return rtl.isObject(m) && rtl.isModule(m.$module) && (m.$module.$impl===m);
|
|
|
+ },
|
|
|
+
|
|
|
+ isNumber: function(n){
|
|
|
+ return typeof(n)==="number";
|
|
|
+ },
|
|
|
+
|
|
|
+ isObject: function(o){
|
|
|
+ var s=typeof(o);
|
|
|
+ return (typeof(o)==="object") && (o!=null);
|
|
|
+ },
|
|
|
+
|
|
|
+ isString: function(s){
|
|
|
+ return typeof(s)==="string";
|
|
|
+ },
|
|
|
+
|
|
|
+ getNumber: function(n){
|
|
|
+ return typeof(n)==="number"?n:NaN;
|
|
|
+ },
|
|
|
+
|
|
|
+ getChar: function(c){
|
|
|
+ return ((typeof(c)==="string") && (c.length===1)) ? c : "";
|
|
|
+ },
|
|
|
+
|
|
|
+ getObject: function(o){
|
|
|
+ return ((typeof(o)==="object") || (typeof(o)==='function')) ? o : null;
|
|
|
+ },
|
|
|
+
|
|
|
+ isTRecord: function(type){
|
|
|
+ return (rtl.isObject(type) && type.hasOwnProperty('$new') && (typeof(type.$new)==='function'));
|
|
|
+ },
|
|
|
+
|
|
|
+ isPasClass: function(type){
|
|
|
+ return (rtl.isObject(type) && type.hasOwnProperty('$classname') && rtl.isObject(type.$module));
|
|
|
+ },
|
|
|
+
|
|
|
+ isPasClassInstance: function(type){
|
|
|
+ return (rtl.isObject(type) && rtl.isPasClass(type.$class));
|
|
|
+ },
|
|
|
+
|
|
|
+ hexStr: function(n,digits){
|
|
|
+ return ("000000000000000"+n.toString(16).toUpperCase()).slice(-digits);
|
|
|
+ },
|
|
|
+
|
|
|
+ m_loading: 0,
|
|
|
+ m_loading_intf: 1,
|
|
|
+ m_intf_loaded: 2,
|
|
|
+ m_loading_impl: 3, // loading all used unit
|
|
|
+ m_initializing: 4, // running initialization
|
|
|
+ m_initialized: 5,
|
|
|
+
|
|
|
+ module: function(module_name, intfuseslist, intfcode, impluseslist){
|
|
|
+ if (rtl.debug_load_units) rtl.debug('rtl.module name="'+module_name+'" intfuses='+intfuseslist+' impluses='+impluseslist);
|
|
|
+ if (!rtl.hasString(module_name)) rtl.error('invalid module name "'+module_name+'"');
|
|
|
+ if (!rtl.isArray(intfuseslist)) rtl.error('invalid interface useslist of "'+module_name+'"');
|
|
|
+ if (!rtl.isFunction(intfcode)) rtl.error('invalid interface code of "'+module_name+'"');
|
|
|
+ if (!(impluseslist==undefined) && !rtl.isArray(impluseslist)) rtl.error('invalid implementation useslist of "'+module_name+'"');
|
|
|
+
|
|
|
+ if (pas[module_name])
|
|
|
+ rtl.error('module "'+module_name+'" is already registered');
|
|
|
+
|
|
|
+ var r = Object.create(rtl.tSectionRTTI);
|
|
|
+ var module = r.$module = pas[module_name] = {
|
|
|
+ $name: module_name,
|
|
|
+ $intfuseslist: intfuseslist,
|
|
|
+ $impluseslist: impluseslist,
|
|
|
+ $state: rtl.m_loading,
|
|
|
+ $intfcode: intfcode,
|
|
|
+ $implcode: null,
|
|
|
+ $impl: null,
|
|
|
+ $rtti: r
|
|
|
+ };
|
|
|
+ if (impluseslist) module.$impl = {
|
|
|
+ $module: module,
|
|
|
+ $rtti: r
|
|
|
+ };
|
|
|
+ },
|
|
|
+
|
|
|
+ exitcode: 0,
|
|
|
+
|
|
|
+ run: function(module_name){
|
|
|
+ try {
|
|
|
+ if (!rtl.hasString(module_name)) module_name='program';
|
|
|
+ if (rtl.debug_load_units) rtl.debug('rtl.run module="'+module_name+'"');
|
|
|
+ rtl.initRTTI();
|
|
|
+ var module = pas[module_name];
|
|
|
+ if (!module) rtl.error('rtl.run module "'+module_name+'" missing');
|
|
|
+ rtl.loadintf(module);
|
|
|
+ rtl.loadimpl(module);
|
|
|
+ if ((module_name=='program') || (module_name=='library')){
|
|
|
+ if (rtl.debug_load_units) rtl.debug('running $main');
|
|
|
+ var r = pas[module_name].$main();
|
|
|
+ if (rtl.isNumber(r)) rtl.exitcode = r;
|
|
|
+ }
|
|
|
+ } catch(re) {
|
|
|
+ if (!rtl.showUncaughtExceptions) {
|
|
|
+ throw re
|
|
|
+ } else {
|
|
|
+ if (!rtl.handleUncaughtException(re)) {
|
|
|
+ rtl.showException(re);
|
|
|
+ rtl.exitcode = 216;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return rtl.exitcode;
|
|
|
+ },
|
|
|
+
|
|
|
+ showException : function (re) {
|
|
|
+ var errMsg = rtl.hasString(re.$classname) ? re.$classname : '';
|
|
|
+ errMsg += ((errMsg) ? ': ' : '') + (re.hasOwnProperty('fMessage') ? re.fMessage : re);
|
|
|
+ alert('Uncaught Exception : '+errMsg);
|
|
|
+ },
|
|
|
+
|
|
|
+ handleUncaughtException: function (e) {
|
|
|
+ if (rtl.onUncaughtException) {
|
|
|
+ try {
|
|
|
+ rtl.onUncaughtException(e);
|
|
|
+ return true;
|
|
|
+ } catch (ee) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ loadintf: function(module){
|
|
|
+ if (module.$state>rtl.m_loading_intf) return; // already finished
|
|
|
+ if (rtl.debug_load_units) rtl.debug('loadintf: "'+module.$name+'"');
|
|
|
+ if (module.$state===rtl.m_loading_intf)
|
|
|
+ rtl.error('unit cycle detected "'+module.$name+'"');
|
|
|
+ module.$state=rtl.m_loading_intf;
|
|
|
+ // load interfaces of interface useslist
|
|
|
+ rtl.loaduseslist(module,module.$intfuseslist,rtl.loadintf);
|
|
|
+ // run interface
|
|
|
+ if (rtl.debug_load_units) rtl.debug('loadintf: run intf of "'+module.$name+'"');
|
|
|
+ module.$intfcode(module.$intfuseslist);
|
|
|
+ // success
|
|
|
+ module.$state=rtl.m_intf_loaded;
|
|
|
+ // Note: units only used in implementations are not yet loaded (not even their interfaces)
|
|
|
+ },
|
|
|
+
|
|
|
+ loaduseslist: function(module,useslist,f){
|
|
|
+ if (useslist==undefined) return;
|
|
|
+ var len = useslist.length;
|
|
|
+ for (var i = 0; i<len; i++) {
|
|
|
+ var unitname=useslist[i];
|
|
|
+ if (rtl.debug_load_units) rtl.debug('loaduseslist of "'+module.$name+'" uses="'+unitname+'"');
|
|
|
+ if (pas[unitname]==undefined)
|
|
|
+ rtl.error('module "'+module.$name+'" misses "'+unitname+'"');
|
|
|
+ f(pas[unitname]);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ loadimpl: function(module){
|
|
|
+ if (module.$state>=rtl.m_loading_impl) return; // already processing
|
|
|
+ if (module.$state<rtl.m_intf_loaded) rtl.error('loadimpl: interface not loaded of "'+module.$name+'"');
|
|
|
+ if (rtl.debug_load_units) rtl.debug('loadimpl: load uses of "'+module.$name+'"');
|
|
|
+ module.$state=rtl.m_loading_impl;
|
|
|
+ // load interfaces of implementation useslist
|
|
|
+ rtl.loaduseslist(module,module.$impluseslist,rtl.loadintf);
|
|
|
+ // load implementation of interfaces useslist
|
|
|
+ rtl.loaduseslist(module,module.$intfuseslist,rtl.loadimpl);
|
|
|
+ // load implementation of implementation useslist
|
|
|
+ rtl.loaduseslist(module,module.$impluseslist,rtl.loadimpl);
|
|
|
+ // Note: At this point all interfaces used by this unit are loaded. If
|
|
|
+ // there are implementation uses cycles some used units might not yet be
|
|
|
+ // initialized. This is by design.
|
|
|
+ // run implementation
|
|
|
+ if (rtl.debug_load_units) rtl.debug('loadimpl: run impl of "'+module.$name+'"');
|
|
|
+ if (rtl.isFunction(module.$implcode)) module.$implcode(module.$impluseslist);
|
|
|
+ // run initialization
|
|
|
+ if (rtl.debug_load_units) rtl.debug('loadimpl: run init of "'+module.$name+'"');
|
|
|
+ module.$state=rtl.m_initializing;
|
|
|
+ if (rtl.isFunction(module.$init)) module.$init();
|
|
|
+ // unit initialized
|
|
|
+ module.$state=rtl.m_initialized;
|
|
|
+ },
|
|
|
+
|
|
|
+ createCallback: function(scope, fn){
|
|
|
+ var cb;
|
|
|
+ if (typeof(fn)==='string'){
|
|
|
+ if (!scope.hasOwnProperty('$events')) scope.$events = {};
|
|
|
+ cb = scope.$events[fn];
|
|
|
+ if (cb) return cb;
|
|
|
+ scope.$events[fn] = cb = function(){
|
|
|
+ return scope[fn].apply(scope,arguments);
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ cb = function(){
|
|
|
+ return fn.apply(scope,arguments);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ cb.scope = scope;
|
|
|
+ cb.fn = fn;
|
|
|
+ return cb;
|
|
|
+ },
|
|
|
+
|
|
|
+ createSafeCallback: function(scope, fn){
|
|
|
+ var cb;
|
|
|
+ if (typeof(fn)==='string'){
|
|
|
+ if (!scope.hasOwnProperty('$events')) scope.$events = {};
|
|
|
+ cb = scope.$events[fn];
|
|
|
+ if (cb) return cb;
|
|
|
+ scope.$events[fn] = cb = function(){
|
|
|
+ try{
|
|
|
+ return scope[fn].apply(scope,arguments);
|
|
|
+ } catch (err) {
|
|
|
+ if (!rtl.handleUncaughtException(err)) throw err;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ cb = function(){
|
|
|
+ try{
|
|
|
+ return fn.apply(scope,arguments);
|
|
|
+ } catch (err) {
|
|
|
+ if (!rtl.handleUncaughtException(err)) throw err;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ };
|
|
|
+ cb.scope = scope;
|
|
|
+ cb.fn = fn;
|
|
|
+ return cb;
|
|
|
+ },
|
|
|
+
|
|
|
+ eqCallback: function(a,b){
|
|
|
+ // can be a function or a function wrapper
|
|
|
+ if (a===b){
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ return (a!=null) && (b!=null) && (a.fn) && (a.scope===b.scope) && (a.fn===b.fn);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ initStruct: function(c,parent,name){
|
|
|
+ if ((parent.$module) && (parent.$module.$impl===parent)) parent=parent.$module;
|
|
|
+ c.$parent = parent;
|
|
|
+ if (rtl.isModule(parent)){
|
|
|
+ c.$module = parent;
|
|
|
+ c.$name = name;
|
|
|
+ } else {
|
|
|
+ c.$module = parent.$module;
|
|
|
+ c.$name = parent.$name+'.'+name;
|
|
|
+ };
|
|
|
+ return parent;
|
|
|
+ },
|
|
|
+
|
|
|
+ initClass: function(c,parent,name,initfn,rttiname){
|
|
|
+ parent[name] = c;
|
|
|
+ c.$class = c; // Note: o.$class === Object.getPrototypeOf(o)
|
|
|
+ c.$classname = rttiname?rttiname:name;
|
|
|
+ parent = rtl.initStruct(c,parent,name);
|
|
|
+ c.$fullname = parent.$name+'.'+name;
|
|
|
+ // rtti
|
|
|
+ if (rtl.debug_rtti) rtl.debug('initClass '+c.$fullname);
|
|
|
+ var t = c.$module.$rtti.$Class(c.$classname,{ "class": c });
|
|
|
+ c.$rtti = t;
|
|
|
+ if (rtl.isObject(c.$ancestor)) t.ancestor = c.$ancestor.$rtti;
|
|
|
+ if (!t.ancestor) t.ancestor = null;
|
|
|
+ // init members
|
|
|
+ initfn.call(c);
|
|
|
+ },
|
|
|
+
|
|
|
+ createClass: function(parent,name,ancestor,initfn,rttiname){
|
|
|
+ // create a normal class,
|
|
|
+ // ancestor must be null or a normal class,
|
|
|
+ // the root ancestor can be an external class
|
|
|
+ var c = null;
|
|
|
+ if (ancestor != null){
|
|
|
+ c = Object.create(ancestor);
|
|
|
+ c.$ancestor = ancestor;
|
|
|
+ // Note:
|
|
|
+ // if root is an "object" then c.$ancestor === Object.getPrototypeOf(c)
|
|
|
+ // if root is a "function" then c.$ancestor === c.__proto__, Object.getPrototypeOf(c) returns the root
|
|
|
+ } else {
|
|
|
+ c = { $ancestor: null };
|
|
|
+ c.$create = function(fn,args){
|
|
|
+ if (args == undefined) args = [];
|
|
|
+ var o = Object.create(this);
|
|
|
+ o.$init();
|
|
|
+ try{
|
|
|
+ if (typeof(fn)==="string"){
|
|
|
+ o[fn].apply(o,args);
|
|
|
+ } else {
|
|
|
+ fn.apply(o,args);
|
|
|
+ };
|
|
|
+ o.AfterConstruction();
|
|
|
+ } catch($e){
|
|
|
+ // do not call BeforeDestruction
|
|
|
+ if (o.Destroy) o.Destroy();
|
|
|
+ o.$final();
|
|
|
+ throw $e;
|
|
|
+ }
|
|
|
+ return o;
|
|
|
+ };
|
|
|
+ c.$destroy = function(fnname){
|
|
|
+ this.BeforeDestruction();
|
|
|
+ if (this[fnname]) this[fnname]();
|
|
|
+ this.$final();
|
|
|
+ };
|
|
|
+ };
|
|
|
+ rtl.initClass(c,parent,name,initfn,rttiname);
|
|
|
+ },
|
|
|
+
|
|
|
+ createClassExt: function(parent,name,ancestor,newinstancefnname,initfn,rttiname){
|
|
|
+ // Create a class using an external ancestor.
|
|
|
+ // If newinstancefnname is given, use that function to create the new object.
|
|
|
+ // If exist call BeforeDestruction and AfterConstruction.
|
|
|
+ var isFunc = rtl.isFunction(ancestor);
|
|
|
+ var c = null;
|
|
|
+ if (isFunc){
|
|
|
+ // create pascal class descendent from JS function
|
|
|
+ c = Object.create(ancestor.prototype);
|
|
|
+ c.$ancestorfunc = ancestor;
|
|
|
+ c.$ancestor = null; // no pascal ancestor
|
|
|
+ } else if (ancestor.$func){
|
|
|
+ // create pascal class descendent from a pascal class descendent of a JS function
|
|
|
+ isFunc = true;
|
|
|
+ c = Object.create(ancestor);
|
|
|
+ c.$ancestor = ancestor;
|
|
|
+ } else {
|
|
|
+ c = Object.create(ancestor);
|
|
|
+ c.$ancestor = null; // no pascal ancestor
|
|
|
+ }
|
|
|
+ c.$create = function(fn,args){
|
|
|
+ if (args == undefined) args = [];
|
|
|
+ var o = null;
|
|
|
+ if (newinstancefnname.length>0){
|
|
|
+ o = this[newinstancefnname](fn,args);
|
|
|
+ } else if(isFunc) {
|
|
|
+ o = new this.$func(args);
|
|
|
+ } else {
|
|
|
+ o = Object.create(c);
|
|
|
+ }
|
|
|
+ if (o.$init) o.$init();
|
|
|
+ try{
|
|
|
+ if (typeof(fn)==="string"){
|
|
|
+ this[fn].apply(o,args);
|
|
|
+ } else {
|
|
|
+ fn.apply(o,args);
|
|
|
+ };
|
|
|
+ if (o.AfterConstruction) o.AfterConstruction();
|
|
|
+ } catch($e){
|
|
|
+ // do not call BeforeDestruction
|
|
|
+ if (o.Destroy) o.Destroy();
|
|
|
+ if (o.$final) o.$final();
|
|
|
+ throw $e;
|
|
|
+ }
|
|
|
+ return o;
|
|
|
+ };
|
|
|
+ c.$destroy = function(fnname){
|
|
|
+ if (this.BeforeDestruction) this.BeforeDestruction();
|
|
|
+ if (this[fnname]) this[fnname]();
|
|
|
+ if (this.$final) this.$final();
|
|
|
+ };
|
|
|
+ rtl.initClass(c,parent,name,initfn,rttiname);
|
|
|
+ if (isFunc){
|
|
|
+ function f(){}
|
|
|
+ f.prototype = c;
|
|
|
+ c.$func = f;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ createHelper: function(parent,name,ancestor,initfn,rttiname){
|
|
|
+ // create a helper,
|
|
|
+ // ancestor must be null or a helper,
|
|
|
+ var c = null;
|
|
|
+ if (ancestor != null){
|
|
|
+ c = Object.create(ancestor);
|
|
|
+ c.$ancestor = ancestor;
|
|
|
+ // c.$ancestor === Object.getPrototypeOf(c)
|
|
|
+ } else {
|
|
|
+ c = { $ancestor: null };
|
|
|
+ };
|
|
|
+ parent[name] = c;
|
|
|
+ c.$class = c; // Note: o.$class === Object.getPrototypeOf(o)
|
|
|
+ c.$classname = rttiname?rttiname:name;
|
|
|
+ parent = rtl.initStruct(c,parent,name);
|
|
|
+ c.$fullname = parent.$name+'.'+name;
|
|
|
+ // rtti
|
|
|
+ var t = c.$module.$rtti.$Helper(c.$classname,{ "helper": c });
|
|
|
+ c.$rtti = t;
|
|
|
+ if (rtl.isObject(ancestor)) t.ancestor = ancestor.$rtti;
|
|
|
+ if (!t.ancestor) t.ancestor = null;
|
|
|
+ // init members
|
|
|
+ initfn.call(c);
|
|
|
+ },
|
|
|
+
|
|
|
+ tObjectDestroy: "Destroy",
|
|
|
+
|
|
|
+ free: function(obj,name){
|
|
|
+ if (obj[name]==null) return null;
|
|
|
+ obj[name].$destroy(rtl.tObjectDestroy);
|
|
|
+ obj[name]=null;
|
|
|
+ },
|
|
|
+
|
|
|
+ freeLoc: function(obj){
|
|
|
+ if (obj==null) return null;
|
|
|
+ obj.$destroy(rtl.tObjectDestroy);
|
|
|
+ return null;
|
|
|
+ },
|
|
|
+
|
|
|
+ hideProp: function(o,p,v){
|
|
|
+ Object.defineProperty(o,p, {
|
|
|
+ enumerable: false,
|
|
|
+ configurable: true,
|
|
|
+ writable: true
|
|
|
+ });
|
|
|
+ if(arguments.length>2){ o[p]=v; }
|
|
|
+ },
|
|
|
+
|
|
|
+ recNewT: function(parent,name,initfn,full){
|
|
|
+ // create new record type
|
|
|
+ var t = {};
|
|
|
+ if (parent) parent[name] = t;
|
|
|
+ var h = rtl.hideProp;
|
|
|
+ if (full){
|
|
|
+ rtl.initStruct(t,parent,name);
|
|
|
+ t.$record = t;
|
|
|
+ h(t,'$record');
|
|
|
+ h(t,'$name');
|
|
|
+ h(t,'$parent');
|
|
|
+ h(t,'$module');
|
|
|
+ h(t,'$initSpec');
|
|
|
+ }
|
|
|
+ initfn.call(t);
|
|
|
+ if (!t.$new){
|
|
|
+ t.$new = function(){ return Object.create(t); };
|
|
|
+ }
|
|
|
+ t.$clone = function(r){ return t.$new().$assign(r); };
|
|
|
+ h(t,'$new');
|
|
|
+ h(t,'$clone');
|
|
|
+ h(t,'$eq');
|
|
|
+ h(t,'$assign');
|
|
|
+ return t;
|
|
|
+ },
|
|
|
+
|
|
|
+ is: function(instance,type){
|
|
|
+ return type.isPrototypeOf(instance) || (instance===type);
|
|
|
+ },
|
|
|
+
|
|
|
+ isExt: function(instance,type,mode){
|
|
|
+ // mode===1 means instance must be a Pascal class instance
|
|
|
+ // mode===2 means instance must be a Pascal class
|
|
|
+ // Notes:
|
|
|
+ // isPrototypeOf and instanceof return false on equal
|
|
|
+ // isPrototypeOf does not work for Date.isPrototypeOf(new Date())
|
|
|
+ // so if isPrototypeOf is false test with instanceof
|
|
|
+ // instanceof needs a function on right side
|
|
|
+ if (instance == null) return false; // Note: ==null checks for undefined too
|
|
|
+ if ((typeof(type) !== 'object') && (typeof(type) !== 'function')) return false;
|
|
|
+ if (instance === type){
|
|
|
+ if (mode===1) return false;
|
|
|
+ if (mode===2) return rtl.isPasClass(instance);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (type.isPrototypeOf && type.isPrototypeOf(instance)){
|
|
|
+ if (mode===1) return rtl.isPasClassInstance(instance);
|
|
|
+ if (mode===2) return rtl.isPasClass(instance);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if ((typeof type == 'function') && (instance instanceof type)) return true;
|
|
|
+ return false;
|
|
|
+ },
|
|
|
+
|
|
|
+ Exception: null,
|
|
|
+ EInvalidCast: null,
|
|
|
+ EAbstractError: null,
|
|
|
+ ERangeError: null,
|
|
|
+ EIntOverflow: null,
|
|
|
+ EPropWriteOnly: null,
|
|
|
+
|
|
|
+ raiseE: function(typename){
|
|
|
+ var t = rtl[typename];
|
|
|
+ if (t==null){
|
|
|
+ var mod = pas.SysUtils;
|
|
|
+ if (!mod) mod = pas.sysutils;
|
|
|
+ if (mod){
|
|
|
+ t = mod[typename];
|
|
|
+ if (!t) t = mod[typename.toLowerCase()];
|
|
|
+ if (!t) t = mod['Exception'];
|
|
|
+ if (!t) t = mod['exception'];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (t){
|
|
|
+ if (t.Create){
|
|
|
+ throw t.$create("Create");
|
|
|
+ } else if (t.create){
|
|
|
+ throw t.$create("create");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (typename === "EInvalidCast") throw "invalid type cast";
|
|
|
+ if (typename === "EAbstractError") throw "Abstract method called";
|
|
|
+ if (typename === "ERangeError") throw "range error";
|
|
|
+ throw typename;
|
|
|
+ },
|
|
|
+
|
|
|
+ as: function(instance,type){
|
|
|
+ if((instance === null) || rtl.is(instance,type)) return instance;
|
|
|
+ rtl.raiseE("EInvalidCast");
|
|
|
+ },
|
|
|
+
|
|
|
+ asExt: function(instance,type,mode){
|
|
|
+ if((instance === null) || rtl.isExt(instance,type,mode)) return instance;
|
|
|
+ rtl.raiseE("EInvalidCast");
|
|
|
+ },
|
|
|
+
|
|
|
+ createInterface: function(module, name, guid, fnnames, ancestor, initfn, rttiname){
|
|
|
+ //console.log('createInterface name="'+name+'" guid="'+guid+'" names='+fnnames);
|
|
|
+ var i = ancestor?Object.create(ancestor):{};
|
|
|
+ module[name] = i;
|
|
|
+ i.$module = module;
|
|
|
+ i.$name = rttiname?rttiname:name;
|
|
|
+ i.$fullname = module.$name+'.'+i.$name;
|
|
|
+ i.$guid = guid;
|
|
|
+ i.$guidr = null;
|
|
|
+ i.$names = fnnames?fnnames:[];
|
|
|
+ if (rtl.isFunction(initfn)){
|
|
|
+ // rtti
|
|
|
+ if (rtl.debug_rtti) rtl.debug('createInterface '+i.$fullname);
|
|
|
+ var t = i.$module.$rtti.$Interface(i.$name,{ "interface": i, module: module });
|
|
|
+ i.$rtti = t;
|
|
|
+ if (ancestor) t.ancestor = ancestor.$rtti;
|
|
|
+ if (!t.ancestor) t.ancestor = null;
|
|
|
+ initfn.call(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;
|
|
|
+ var h = rtl.hexStr;
|
|
|
+ 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,TGuid.$new());
|
|
|
+ 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){
|
|
|
+ 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);
|
|
|
+ if (!aclass.hasOwnProperty('$intfmaps')) aclass.$intfmaps = {};
|
|
|
+ aclass.$intfmaps[intf.$guid] = item;
|
|
|
+ do{
|
|
|
+ var names = t.$names;
|
|
|
+ if (!names) break;
|
|
|
+ for (var i=0; i<names.length; i++){
|
|
|
+ var intfname = names[i];
|
|
|
+ var fnname = map[intfname];
|
|
|
+ if (!fnname) fnname = intfname;
|
|
|
+ //console.log('addIntf: intftype='+t.$name+' index='+i+' intfname="'+intfname+'" fnname="'+fnname+'" old='+typeof(item[intfname]));
|
|
|
+ item[intfname] = jmp(aclass[fnname]);
|
|
|
+ }
|
|
|
+ t = Object.getPrototypeOf(t);
|
|
|
+ }while(t!=null);
|
|
|
+ },
|
|
|
+
|
|
|
+ getIntfG: function (obj, guid, query){
|
|
|
+ if (!obj) return null;
|
|
|
+ //console.log('getIntfG: obj='+obj.$classname+' guid='+guid+' query='+query);
|
|
|
+ // search
|
|
|
+ var maps = obj.$intfmaps;
|
|
|
+ if (!maps) return null;
|
|
|
+ var item = maps[guid];
|
|
|
+ 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); // delegate. Note: COM contains _AddRef
|
|
|
+ // check cache
|
|
|
+ var intf = null;
|
|
|
+ if (obj.$interfaces){
|
|
|
+ intf = obj.$interfaces[guid];
|
|
|
+ //console.log('getIntfG: obj='+obj.$classname+' guid='+guid+' cache='+typeof(intf));
|
|
|
+ }
|
|
|
+ if (!intf){ // intf can be undefined!
|
|
|
+ intf = Object.create(item);
|
|
|
+ intf.$o = obj;
|
|
|
+ if (!obj.$interfaces) obj.$interfaces = {};
|
|
|
+ obj.$interfaces[guid] = intf;
|
|
|
+ }
|
|
|
+ if (typeof(query)==='object'){
|
|
|
+ // called by queryIntfT
|
|
|
+ var o = null;
|
|
|
+ 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){
|
|
|
+ // called by TObject.GetInterfaceByStr
|
|
|
+ if (intf.$kind === 'com') intf._AddRef();
|
|
|
+ }
|
|
|
+ return intf;
|
|
|
+ },
|
|
|
+
|
|
|
+ getIntfT: function(obj,intftype){
|
|
|
+ return rtl.getIntfG(obj,intftype.$guid);
|
|
|
+ },
|
|
|
+
|
|
|
+ queryIntfT: function(obj,intftype){
|
|
|
+ return rtl.getIntfG(obj,intftype.$guid,intftype);
|
|
|
+ },
|
|
|
+
|
|
|
+ queryIntfIsT: function(obj,intftype){
|
|
|
+ var i = rtl.getIntfG(obj,intftype.$guid);
|
|
|
+ if (!i) return false;
|
|
|
+ if (i.$kind === 'com') i._Release();
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+
|
|
|
+ asIntfT: function (obj,intftype){
|
|
|
+ var i = rtl.getIntfG(obj,intftype.$guid);
|
|
|
+ if (i!==null) return i;
|
|
|
+ rtl.raiseEInvalidCast();
|
|
|
+ },
|
|
|
+
|
|
|
+ intfIsIntfT: function(intf,intftype){
|
|
|
+ return (intf!==null) && rtl.queryIntfIsT(intf.$o,intftype);
|
|
|
+ },
|
|
|
+
|
|
|
+ intfAsIntfT: function (intf,intftype){
|
|
|
+ if (!intf) return null;
|
|
|
+ var i = rtl.getIntfG(intf.$o,intftype.$guid);
|
|
|
+ if (i) return i;
|
|
|
+ rtl.raiseEInvalidCast();
|
|
|
+ },
|
|
|
+
|
|
|
+ intfIsClass: function(intf,classtype){
|
|
|
+ return (intf!=null) && (rtl.is(intf.$o,classtype));
|
|
|
+ },
|
|
|
+
|
|
|
+ intfAsClass: function(intf,classtype){
|
|
|
+ if (intf==null) return null;
|
|
|
+ return rtl.as(intf.$o,classtype);
|
|
|
+ },
|
|
|
+
|
|
|
+ intfToClass: function(intf,classtype){
|
|
|
+ if ((intf!==null) && rtl.is(intf.$o,classtype)) return intf.$o;
|
|
|
+ return null;
|
|
|
+ },
|
|
|
+
|
|
|
+ // interface reference counting
|
|
|
+ intfRefs: { // base object for temporary interface variables
|
|
|
+ ref: function(id,intf){
|
|
|
+ // called for temporary interface references needing delayed release
|
|
|
+ var old = this[id];
|
|
|
+ //console.log('rtl.intfRefs.ref: id='+id+' old="'+(old?old.$name:'null')+'" intf="'+(intf?intf.$name:'null')+' $o='+(intf?intf.$o:'null'));
|
|
|
+ if (old){
|
|
|
+ // called again, e.g. in a loop
|
|
|
+ delete this[id];
|
|
|
+ old._Release(); // may fail
|
|
|
+ }
|
|
|
+ if(intf) {
|
|
|
+ this[id]=intf;
|
|
|
+ }
|
|
|
+ return intf;
|
|
|
+ },
|
|
|
+ free: function(){
|
|
|
+ //console.log('rtl.intfRefs.free...');
|
|
|
+ for (var id in this){
|
|
|
+ if (this.hasOwnProperty(id)){
|
|
|
+ var intf = this[id];
|
|
|
+ if (intf){
|
|
|
+ //console.log('rtl.intfRefs.free: id='+id+' '+intf.$name+' $o='+intf.$o.$classname);
|
|
|
+ intf._Release();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ createIntfRefs: function(){
|
|
|
+ //console.log('rtl.createIntfRefs');
|
|
|
+ return Object.create(rtl.intfRefs);
|
|
|
+ },
|
|
|
+
|
|
|
+ setIntfP: function(path,name,value,skipAddRef){
|
|
|
+ var old = path[name];
|
|
|
+ //console.log('rtl.setIntfP path='+path+' name='+name+' old="'+(old?old.$name:'null')+'" value="'+(value?value.$name:'null')+'"');
|
|
|
+ if (old === value) return;
|
|
|
+ if (old !== null){
|
|
|
+ path[name]=null;
|
|
|
+ old._Release();
|
|
|
+ }
|
|
|
+ if (value !== null){
|
|
|
+ if (!skipAddRef) value._AddRef();
|
|
|
+ path[name]=value;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ setIntfL: function(old,value,skipAddRef){
|
|
|
+ //console.log('rtl.setIntfL old="'+(old?old.$name:'null')+'" value="'+(value?value.$name:'null')+'"');
|
|
|
+ if (old !== value){
|
|
|
+ if (value!==null){
|
|
|
+ if (!skipAddRef) value._AddRef();
|
|
|
+ }
|
|
|
+ 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;
|
|
|
+ },
|
|
|
+
|
|
|
+ _AddRef: function(intf){
|
|
|
+ //if (intf) console.log('rtl._AddRef intf="'+(intf?intf.$name:'null')+'"');
|
|
|
+ if (intf) intf._AddRef();
|
|
|
+ return intf;
|
|
|
+ },
|
|
|
+
|
|
|
+ _Release: function(intf){
|
|
|
+ //if (intf) console.log('rtl._Release intf="'+(intf?intf.$name:'null')+'"');
|
|
|
+ if (intf) intf._Release();
|
|
|
+ return intf;
|
|
|
+ },
|
|
|
+
|
|
|
+ _ReleaseArray: function(a,dim){
|
|
|
+ if (!a) return null;
|
|
|
+ for (var i=0; i<a.length; i++){
|
|
|
+ if (dim<=1){
|
|
|
+ if (a[i]) a[i]._Release();
|
|
|
+ } else {
|
|
|
+ rtl._ReleaseArray(a[i],dim-1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ },
|
|
|
+
|
|
|
+ trunc: function(a){
|
|
|
+ return a<0 ? Math.ceil(a) : Math.floor(a);
|
|
|
+ },
|
|
|
+
|
|
|
+ checkMethodCall: function(obj,type){
|
|
|
+ if (rtl.isObject(obj) && rtl.is(obj,type)) return;
|
|
|
+ rtl.raiseE("EInvalidCast");
|
|
|
+ },
|
|
|
+
|
|
|
+ oc: function(i){
|
|
|
+ // overflow check integer
|
|
|
+ if ((Math.floor(i)===i) && (i>=-0x1fffffffffffff) && (i<=0x1fffffffffffff)) return i;
|
|
|
+ rtl.raiseE('EIntOverflow');
|
|
|
+ },
|
|
|
+
|
|
|
+ rc: function(i,minval,maxval){
|
|
|
+ // range check integer
|
|
|
+ if ((Math.floor(i)===i) && (i>=minval) && (i<=maxval)) return i;
|
|
|
+ rtl.raiseE('ERangeError');
|
|
|
+ },
|
|
|
+
|
|
|
+ rcc: function(c,minval,maxval){
|
|
|
+ // range check char
|
|
|
+ if ((typeof(c)==='string') && (c.length===1)){
|
|
|
+ var i = c.charCodeAt(0);
|
|
|
+ if ((i>=minval) && (i<=maxval)) return c;
|
|
|
+ }
|
|
|
+ rtl.raiseE('ERangeError');
|
|
|
+ },
|
|
|
+
|
|
|
+ rcSetCharAt: function(s,index,c){
|
|
|
+ // range check setCharAt
|
|
|
+ if ((typeof(s)!=='string') || (index<0) || (index>=s.length)) rtl.raiseE('ERangeError');
|
|
|
+ return rtl.setCharAt(s,index,c);
|
|
|
+ },
|
|
|
+
|
|
|
+ rcCharAt: function(s,index){
|
|
|
+ // range check charAt
|
|
|
+ if ((typeof(s)!=='string') || (index<0) || (index>=s.length)) rtl.raiseE('ERangeError');
|
|
|
+ return s.charAt(index);
|
|
|
+ },
|
|
|
+
|
|
|
+ rcArrR: function(arr,index){
|
|
|
+ // range check read array
|
|
|
+ if (Array.isArray(arr) && (typeof(index)==='number') && (index>=0) && (index<arr.length)){
|
|
|
+ if (arguments.length>2){
|
|
|
+ // arr,index1,index2,...
|
|
|
+ arr=arr[index];
|
|
|
+ for (var i=2; i<arguments.length; i++) arr=rtl.rcArrR(arr,arguments[i]);
|
|
|
+ return arr;
|
|
|
+ }
|
|
|
+ return arr[index];
|
|
|
+ }
|
|
|
+ rtl.raiseE('ERangeError');
|
|
|
+ },
|
|
|
+
|
|
|
+ rcArrW: function(arr,index,value){
|
|
|
+ // range check write array
|
|
|
+ // arr,index1,index2,...,value
|
|
|
+ for (var i=3; i<arguments.length; i++){
|
|
|
+ arr=rtl.rcArrR(arr,index);
|
|
|
+ index=arguments[i-1];
|
|
|
+ value=arguments[i];
|
|
|
+ }
|
|
|
+ if (Array.isArray(arr) && (typeof(index)==='number') && (index>=0) && (index<arr.length)){
|
|
|
+ return arr[index]=value;
|
|
|
+ }
|
|
|
+ rtl.raiseE('ERangeError');
|
|
|
+ },
|
|
|
+
|
|
|
+ length: function(arr){
|
|
|
+ return (arr == null) ? 0 : arr.length;
|
|
|
+ },
|
|
|
+
|
|
|
+ arrayRef: function(a){
|
|
|
+ if (a!=null) rtl.hideProp(a,'$pas2jsrefcnt',1);
|
|
|
+ return a;
|
|
|
+ },
|
|
|
+
|
|
|
+ arraySetLength: function(arr,defaultvalue,newlength){
|
|
|
+ var stack = [];
|
|
|
+ var s = 9999;
|
|
|
+ for (var i=2; i<arguments.length; i++){
|
|
|
+ var j = arguments[i];
|
|
|
+ if (j==='s'){ s = i-2; }
|
|
|
+ else {
|
|
|
+ stack.push({ dim:j+0, a:null, i:0, src:null });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ var dimmax = stack.length-1;
|
|
|
+ var depth = 0;
|
|
|
+ var lastlen = 0;
|
|
|
+ var item = null;
|
|
|
+ var a = null;
|
|
|
+ var src = arr;
|
|
|
+ var srclen = 0, oldlen = 0;
|
|
|
+ do{
|
|
|
+ if (depth>0){
|
|
|
+ item=stack[depth-1];
|
|
|
+ src = (item.src && item.src.length>item.i)?item.src[item.i]:null;
|
|
|
+ }
|
|
|
+ if (!src){
|
|
|
+ a = [];
|
|
|
+ srclen = 0;
|
|
|
+ oldlen = 0;
|
|
|
+ } else if (src.$pas2jsrefcnt>0 || depth>=s){
|
|
|
+ a = [];
|
|
|
+ srclen = src.length;
|
|
|
+ oldlen = srclen;
|
|
|
+ } else {
|
|
|
+ a = src;
|
|
|
+ srclen = 0;
|
|
|
+ oldlen = a.length;
|
|
|
+ }
|
|
|
+ lastlen = stack[depth].dim;
|
|
|
+ a.length = lastlen;
|
|
|
+ if (depth>0){
|
|
|
+ item.a[item.i]=a;
|
|
|
+ item.i++;
|
|
|
+ if ((lastlen===0) && (item.i<item.a.length)) continue;
|
|
|
+ }
|
|
|
+ if (lastlen>0){
|
|
|
+ if (depth<dimmax){
|
|
|
+ item = stack[depth];
|
|
|
+ item.a = a;
|
|
|
+ item.i = 0;
|
|
|
+ item.src = src;
|
|
|
+ depth++;
|
|
|
+ continue;
|
|
|
+ } else {
|
|
|
+ if (srclen>lastlen) srclen=lastlen;
|
|
|
+ if (rtl.isArray(defaultvalue)){
|
|
|
+ // array of dyn array
|
|
|
+ for (var i=0; i<srclen; i++) a[i]=src[i];
|
|
|
+ for (var i=oldlen; i<lastlen; i++) a[i]=[];
|
|
|
+ } else if (rtl.isObject(defaultvalue)) {
|
|
|
+ if (rtl.isTRecord(defaultvalue)){
|
|
|
+ // array of record
|
|
|
+ for (var i=0; i<srclen; i++) a[i]=defaultvalue.$clone(src[i]);
|
|
|
+ for (var i=oldlen; i<lastlen; i++) a[i]=defaultvalue.$new();
|
|
|
+ } else {
|
|
|
+ // array of set
|
|
|
+ for (var i=0; i<srclen; i++) a[i]=rtl.refSet(src[i]);
|
|
|
+ for (var i=oldlen; i<lastlen; i++) a[i]={};
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ for (var i=0; i<srclen; i++) a[i]=src[i];
|
|
|
+ for (var i=oldlen; i<lastlen; i++) a[i]=defaultvalue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // backtrack
|
|
|
+ while ((depth>0) && (stack[depth-1].i>=stack[depth-1].dim)){
|
|
|
+ depth--;
|
|
|
+ };
|
|
|
+ if (depth===0){
|
|
|
+ if (dimmax===0) return a;
|
|
|
+ return stack[0].a;
|
|
|
+ }
|
|
|
+ }while (true);
|
|
|
+ },
|
|
|
+
|
|
|
+ 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,endpos,dst,dstpos){
|
|
|
+ // type: 0 for references, "refset" for calling refSet(), a function for new type()
|
|
|
+ // src must not be null
|
|
|
+ // This function does not range check.
|
|
|
+ if(type === 'refSet') {
|
|
|
+ for (; srcpos<endpos; srcpos++) dst[dstpos++] = rtl.refSet(src[srcpos]); // ref set
|
|
|
+ } else if (type === 'slice'){
|
|
|
+ for (; srcpos<endpos; srcpos++) dst[dstpos++] = src[srcpos].slice(0); // clone static array of simple types
|
|
|
+ } else if (typeof(type)==='function'){
|
|
|
+ for (; srcpos<endpos; srcpos++) dst[dstpos++] = type(src[srcpos]); // clone function
|
|
|
+ } else if (rtl.isTRecord(type)){
|
|
|
+ for (; srcpos<endpos; srcpos++) dst[dstpos++] = type.$clone(src[srcpos]); // clone record
|
|
|
+ } else {
|
|
|
+ for (; srcpos<endpos; srcpos++) dst[dstpos++] = src[srcpos]; // reference
|
|
|
+ };
|
|
|
+ },
|
|
|
+
|
|
|
+ arrayConcat: function(type){
|
|
|
+ // type: see rtl.arrayClone
|
|
|
+ var a = [];
|
|
|
+ var l = 0;
|
|
|
+ for (var i=1; i<arguments.length; i++){
|
|
|
+ var src = arguments[i];
|
|
|
+ if (src !== null) l+=src.length;
|
|
|
+ };
|
|
|
+ a.length = l;
|
|
|
+ l=0;
|
|
|
+ for (var i=1; i<arguments.length; i++){
|
|
|
+ var src = arguments[i];
|
|
|
+ if (src === null) continue;
|
|
|
+ rtl.arrayClone(type,src,0,src.length,a,l);
|
|
|
+ l+=src.length;
|
|
|
+ };
|
|
|
+ return a;
|
|
|
+ },
|
|
|
+
|
|
|
+ arrayConcatN: function(){
|
|
|
+ var a = null;
|
|
|
+ for (var i=0; i<arguments.length; i++){
|
|
|
+ var src = arguments[i];
|
|
|
+ if (src === null) continue;
|
|
|
+ if (a===null){
|
|
|
+ a=rtl.arrayRef(src); // Note: concat(a) does not clone
|
|
|
+ } else if (a['$pas2jsrefcnt']){
|
|
|
+ a=a.concat(src); // clone a and append src
|
|
|
+ } else {
|
|
|
+ for (var i=0; i<src.length; i++){
|
|
|
+ a.push(src[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ return a;
|
|
|
+ },
|
|
|
+
|
|
|
+ arrayPush: function(type,a){
|
|
|
+ if(a===null){
|
|
|
+ a=[];
|
|
|
+ } else if (a['$pas2jsrefcnt']){
|
|
|
+ a=rtl.arrayCopy(type,a,0,a.length);
|
|
|
+ }
|
|
|
+ rtl.arrayClone(type,arguments,2,arguments.length,a,a.length);
|
|
|
+ return a;
|
|
|
+ },
|
|
|
+
|
|
|
+ arrayPushN: function(a){
|
|
|
+ if(a===null){
|
|
|
+ a=[];
|
|
|
+ } else if (a['$pas2jsrefcnt']){
|
|
|
+ a=a.concat();
|
|
|
+ }
|
|
|
+ for (var i=1; i<arguments.length; i++){
|
|
|
+ a.push(arguments[i]);
|
|
|
+ }
|
|
|
+ return a;
|
|
|
+ },
|
|
|
+
|
|
|
+ arrayCopy: function(type, srcarray, index, count){
|
|
|
+ // type: see rtl.arrayClone
|
|
|
+ // if count is missing, use srcarray.length
|
|
|
+ if (srcarray === null) return [];
|
|
|
+ if (index < 0) index = 0;
|
|
|
+ if (count === undefined) count=srcarray.length;
|
|
|
+ var end = index+count;
|
|
|
+ if (end>srcarray.length) end = srcarray.length;
|
|
|
+ if (index>=end) return [];
|
|
|
+ if (type===0){
|
|
|
+ return srcarray.slice(index,end);
|
|
|
+ } else {
|
|
|
+ var a = [];
|
|
|
+ a.length = end-index;
|
|
|
+ rtl.arrayClone(type,srcarray,index,end,a,0);
|
|
|
+ return a;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ arrayInsert: function(item, arr, index){
|
|
|
+ if (arr){
|
|
|
+ arr.splice(index,0,item);
|
|
|
+ return arr;
|
|
|
+ } else {
|
|
|
+ return [item];
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ setCharAt: function(s,index,c){
|
|
|
+ return s.substr(0,index)+c+s.substr(index+1);
|
|
|
+ },
|
|
|
+
|
|
|
+ getResStr: function(mod,name){
|
|
|
+ var rs = mod.$resourcestrings[name];
|
|
|
+ return rs.current?rs.current:rs.org;
|
|
|
+ },
|
|
|
+
|
|
|
+ createSet: function(){
|
|
|
+ var s = {};
|
|
|
+ for (var i=0; i<arguments.length; i++){
|
|
|
+ if (arguments[i]!=null){
|
|
|
+ s[arguments[i]]=true;
|
|
|
+ } else {
|
|
|
+ var first=arguments[i+=1];
|
|
|
+ var last=arguments[i+=1];
|
|
|
+ for(var j=first; j<=last; j++) s[j]=true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return s;
|
|
|
+ },
|
|
|
+
|
|
|
+ cloneSet: function(s){
|
|
|
+ var r = {};
|
|
|
+ for (var key in s) r[key]=true;
|
|
|
+ return r;
|
|
|
+ },
|
|
|
+
|
|
|
+ refSet: function(s){
|
|
|
+ rtl.hideProp(s,'$shared',true);
|
|
|
+ return s;
|
|
|
+ },
|
|
|
+
|
|
|
+ includeSet: function(s,enumvalue){
|
|
|
+ if (s.$shared) s = rtl.cloneSet(s);
|
|
|
+ s[enumvalue] = true;
|
|
|
+ return s;
|
|
|
+ },
|
|
|
+
|
|
|
+ excludeSet: function(s,enumvalue){
|
|
|
+ if (s.$shared) s = rtl.cloneSet(s);
|
|
|
+ delete s[enumvalue];
|
|
|
+ return s;
|
|
|
+ },
|
|
|
+
|
|
|
+ diffSet: function(s,t){
|
|
|
+ var r = {};
|
|
|
+ for (var key in s) if (!t[key]) r[key]=true;
|
|
|
+ return r;
|
|
|
+ },
|
|
|
+
|
|
|
+ unionSet: function(s,t){
|
|
|
+ var r = {};
|
|
|
+ for (var key in s) r[key]=true;
|
|
|
+ for (var key in t) r[key]=true;
|
|
|
+ return r;
|
|
|
+ },
|
|
|
+
|
|
|
+ intersectSet: function(s,t){
|
|
|
+ var r = {};
|
|
|
+ for (var key in s) if (t[key]) r[key]=true;
|
|
|
+ return r;
|
|
|
+ },
|
|
|
+
|
|
|
+ symDiffSet: function(s,t){
|
|
|
+ var r = {};
|
|
|
+ for (var key in s) if (!t[key]) r[key]=true;
|
|
|
+ for (var key in t) if (!s[key]) r[key]=true;
|
|
|
+ return r;
|
|
|
+ },
|
|
|
+
|
|
|
+ eqSet: function(s,t){
|
|
|
+ for (var key in s) if (!t[key]) return false;
|
|
|
+ for (var key in t) if (!s[key]) return false;
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+
|
|
|
+ neSet: function(s,t){
|
|
|
+ return !rtl.eqSet(s,t);
|
|
|
+ },
|
|
|
+
|
|
|
+ leSet: function(s,t){
|
|
|
+ for (var key in s) if (!t[key]) return false;
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+
|
|
|
+ geSet: function(s,t){
|
|
|
+ for (var key in t) if (!s[key]) return false;
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+
|
|
|
+ strSetLength: function(s,newlen){
|
|
|
+ var oldlen = s.length;
|
|
|
+ if (oldlen > newlen){
|
|
|
+ return s.substring(0,newlen);
|
|
|
+ } else if (s.repeat){
|
|
|
+ // Note: repeat needs ECMAScript6!
|
|
|
+ return s+' '.repeat(newlen-oldlen);
|
|
|
+ } else {
|
|
|
+ while (oldlen<newlen){
|
|
|
+ s+=' ';
|
|
|
+ oldlen++;
|
|
|
+ };
|
|
|
+ return s;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ spaceLeft: function(s,width){
|
|
|
+ var l=s.length;
|
|
|
+ if (l>=width) return s;
|
|
|
+ if (s.repeat){
|
|
|
+ // Note: repeat needs ECMAScript6!
|
|
|
+ return ' '.repeat(width-l) + s;
|
|
|
+ } else {
|
|
|
+ while (l<width){
|
|
|
+ s=' '+s;
|
|
|
+ l++;
|
|
|
+ };
|
|
|
+ return s;
|
|
|
+ };
|
|
|
+ },
|
|
|
+
|
|
|
+ floatToStr: function(d,w,p){
|
|
|
+ // input 1-3 arguments: double, width, precision
|
|
|
+ if (arguments.length>2){
|
|
|
+ return rtl.spaceLeft(d.toFixed(p),w);
|
|
|
+ } else {
|
|
|
+ // exponent width
|
|
|
+ var pad = "";
|
|
|
+ var ad = Math.abs(d);
|
|
|
+ if (((ad>1) && (ad<1.0e+10)) || ((ad>1.e-10) && (ad<1))) {
|
|
|
+ pad='00';
|
|
|
+ } else if ((ad>1) && (ad<1.0e+100) || (ad<1.e-10)) {
|
|
|
+ pad='0';
|
|
|
+ }
|
|
|
+ if (arguments.length<2) {
|
|
|
+ w=24;
|
|
|
+ } else if (w<9) {
|
|
|
+ w=9;
|
|
|
+ }
|
|
|
+ var p = w-8;
|
|
|
+ var s=(d>0 ? " " : "" ) + d.toExponential(p);
|
|
|
+ s=s.replace(/e(.)/,'E$1'+pad);
|
|
|
+ return rtl.spaceLeft(s,w);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ valEnum: function(s, enumType, setCodeFn){
|
|
|
+ s = s.toLowerCase();
|
|
|
+ for (var key in enumType){
|
|
|
+ if((typeof(key)==='string') && (key.toLowerCase()===s)){
|
|
|
+ setCodeFn(0);
|
|
|
+ return enumType[key];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ setCodeFn(1);
|
|
|
+ return 0;
|
|
|
+ },
|
|
|
+
|
|
|
+ lw: function(l){
|
|
|
+ // fix longword bitwise operation
|
|
|
+ return l<0?l+0x100000000:l;
|
|
|
+ },
|
|
|
+
|
|
|
+ and: function(a,b){
|
|
|
+ var hi = 0x80000000;
|
|
|
+ var low = 0x7fffffff;
|
|
|
+ var h = (a / hi) & (b / hi);
|
|
|
+ var l = (a & low) & (b & low);
|
|
|
+ return h*hi + l;
|
|
|
+ },
|
|
|
+
|
|
|
+ or: function(a,b){
|
|
|
+ var hi = 0x80000000;
|
|
|
+ var low = 0x7fffffff;
|
|
|
+ var h = (a / hi) | (b / hi);
|
|
|
+ var l = (a & low) | (b & low);
|
|
|
+ return h*hi + l;
|
|
|
+ },
|
|
|
+
|
|
|
+ xor: function(a,b){
|
|
|
+ var hi = 0x80000000;
|
|
|
+ var low = 0x7fffffff;
|
|
|
+ var h = (a / hi) ^ (b / hi);
|
|
|
+ var l = (a & low) ^ (b & low);
|
|
|
+ return h*hi + l;
|
|
|
+ },
|
|
|
+
|
|
|
+ shr: function(a,b){
|
|
|
+ if (a<0) a += rtl.hiInt;
|
|
|
+ if (a<0x80000000) return a >> b;
|
|
|
+ if (b<=0) return a;
|
|
|
+ if (b>54) return 0;
|
|
|
+ return Math.floor(a / Math.pow(2,b));
|
|
|
+ },
|
|
|
+
|
|
|
+ shl: function(a,b){
|
|
|
+ if (a<0) a += rtl.hiInt;
|
|
|
+ if (b<=0) return a;
|
|
|
+ if (b>54) return 0;
|
|
|
+ var r = a * Math.pow(2,b);
|
|
|
+ if (r <= rtl.hiInt) return r;
|
|
|
+ return r % rtl.hiInt;
|
|
|
+ },
|
|
|
+
|
|
|
+ initRTTI: function(){
|
|
|
+ if (rtl.debug_rtti) rtl.debug('initRTTI');
|
|
|
+
|
|
|
+ // base types
|
|
|
+ rtl.tTypeInfo = { name: "tTypeInfo", kind: 0, $module: null, attr: null };
|
|
|
+ function newBaseTI(name,kind,ancestor){
|
|
|
+ if (!ancestor) ancestor = rtl.tTypeInfo;
|
|
|
+ if (rtl.debug_rtti) rtl.debug('initRTTI.newBaseTI "'+name+'" '+kind+' ("'+ancestor.name+'")');
|
|
|
+ var t = Object.create(ancestor);
|
|
|
+ t.name = name;
|
|
|
+ t.kind = kind;
|
|
|
+ rtl[name] = t;
|
|
|
+ return t;
|
|
|
+ };
|
|
|
+ function newBaseInt(name,minvalue,maxvalue,ordtype){
|
|
|
+ var t = newBaseTI(name,1 /* tkInteger */,rtl.tTypeInfoInteger);
|
|
|
+ t.minvalue = minvalue;
|
|
|
+ t.maxvalue = maxvalue;
|
|
|
+ t.ordtype = ordtype;
|
|
|
+ return t;
|
|
|
+ };
|
|
|
+ newBaseTI("tTypeInfoInteger",1 /* tkInteger */);
|
|
|
+ newBaseInt("shortint",-0x80,0x7f,0);
|
|
|
+ newBaseInt("byte",0,0xff,1);
|
|
|
+ newBaseInt("smallint",-0x8000,0x7fff,2);
|
|
|
+ newBaseInt("word",0,0xffff,3);
|
|
|
+ newBaseInt("longint",-0x80000000,0x7fffffff,4);
|
|
|
+ newBaseInt("longword",0,0xffffffff,5);
|
|
|
+ newBaseInt("nativeint",-0x10000000000000,0xfffffffffffff,6);
|
|
|
+ newBaseInt("nativeuint",0,0xfffffffffffff,7);
|
|
|
+ newBaseTI("char",2 /* tkChar */);
|
|
|
+ newBaseTI("string",3 /* tkString */);
|
|
|
+ newBaseTI("tTypeInfoEnum",4 /* tkEnumeration */,rtl.tTypeInfoInteger);
|
|
|
+ newBaseTI("tTypeInfoSet",5 /* tkSet */);
|
|
|
+ newBaseTI("double",6 /* tkDouble */);
|
|
|
+ newBaseTI("boolean",7 /* tkBool */);
|
|
|
+ newBaseTI("tTypeInfoProcVar",8 /* tkProcVar */);
|
|
|
+ newBaseTI("tTypeInfoMethodVar",9 /* tkMethod */,rtl.tTypeInfoProcVar);
|
|
|
+ newBaseTI("tTypeInfoArray",10 /* tkArray */);
|
|
|
+ newBaseTI("tTypeInfoDynArray",11 /* tkDynArray */);
|
|
|
+ newBaseTI("tTypeInfoPointer",15 /* tkPointer */);
|
|
|
+ var t = newBaseTI("pointer",15 /* tkPointer */,rtl.tTypeInfoPointer);
|
|
|
+ t.reftype = null;
|
|
|
+ newBaseTI("jsvalue",16 /* tkJSValue */);
|
|
|
+ newBaseTI("tTypeInfoRefToProcVar",17 /* tkRefToProcVar */,rtl.tTypeInfoProcVar);
|
|
|
+
|
|
|
+ // member kinds
|
|
|
+ rtl.tTypeMember = { attr: null };
|
|
|
+ function newMember(name,kind){
|
|
|
+ var m = Object.create(rtl.tTypeMember);
|
|
|
+ m.name = name;
|
|
|
+ m.kind = kind;
|
|
|
+ rtl[name] = m;
|
|
|
+ };
|
|
|
+ newMember("tTypeMemberField",1); // tmkField
|
|
|
+ newMember("tTypeMemberMethod",2); // tmkMethod
|
|
|
+ newMember("tTypeMemberProperty",3); // tmkProperty
|
|
|
+
|
|
|
+ // base object for storing members: a simple object
|
|
|
+ rtl.tTypeMembers = {};
|
|
|
+
|
|
|
+ // tTypeInfoStruct - base object for tTypeInfoClass, tTypeInfoRecord, tTypeInfoInterface
|
|
|
+ var tis = newBaseTI("tTypeInfoStruct",0);
|
|
|
+ tis.$addMember = function(name,ancestor,options){
|
|
|
+ if (rtl.debug_rtti){
|
|
|
+ if (!rtl.hasString(name) || (name.charAt()==='$')) throw 'invalid member "'+name+'", this="'+this.name+'"';
|
|
|
+ if (!rtl.is(ancestor,rtl.tTypeMember)) throw 'invalid ancestor "'+ancestor+':'+ancestor.name+'", "'+this.name+'.'+name+'"';
|
|
|
+ if ((options!=undefined) && (typeof(options)!='object')) throw 'invalid options "'+options+'", "'+this.name+'.'+name+'"';
|
|
|
+ };
|
|
|
+ var t = Object.create(ancestor);
|
|
|
+ t.name = name;
|
|
|
+ this.members[name] = t;
|
|
|
+ this.names.push(name);
|
|
|
+ if (rtl.isObject(options)){
|
|
|
+ for (var key in options) if (options.hasOwnProperty(key)) t[key] = options[key];
|
|
|
+ };
|
|
|
+ return t;
|
|
|
+ };
|
|
|
+ tis.addField = function(name,type,options){
|
|
|
+ var t = this.$addMember(name,rtl.tTypeMemberField,options);
|
|
|
+ if (rtl.debug_rtti){
|
|
|
+ if (!rtl.is(type,rtl.tTypeInfo)) throw 'invalid type "'+type+'", "'+this.name+'.'+name+'"';
|
|
|
+ };
|
|
|
+ t.typeinfo = type;
|
|
|
+ this.fields.push(name);
|
|
|
+ return t;
|
|
|
+ };
|
|
|
+ tis.addFields = function(){
|
|
|
+ var i=0;
|
|
|
+ while(i<arguments.length){
|
|
|
+ var name = arguments[i++];
|
|
|
+ var type = arguments[i++];
|
|
|
+ if ((i<arguments.length) && (typeof(arguments[i])==='object')){
|
|
|
+ this.addField(name,type,arguments[i++]);
|
|
|
+ } else {
|
|
|
+ this.addField(name,type);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ };
|
|
|
+ tis.addMethod = function(name,methodkind,params,result,flags,options){
|
|
|
+ var t = this.$addMember(name,rtl.tTypeMemberMethod,options);
|
|
|
+ t.methodkind = methodkind;
|
|
|
+ t.procsig = rtl.newTIProcSig(params,result,flags);
|
|
|
+ this.methods.push(name);
|
|
|
+ return t;
|
|
|
+ };
|
|
|
+ tis.addProperty = function(name,flags,result,getter,setter,options){
|
|
|
+ var t = this.$addMember(name,rtl.tTypeMemberProperty,options);
|
|
|
+ t.flags = flags;
|
|
|
+ t.typeinfo = result;
|
|
|
+ t.getter = getter;
|
|
|
+ t.setter = setter;
|
|
|
+ // Note: in options: params, stored, defaultvalue
|
|
|
+ t.params = rtl.isArray(t.params) ? rtl.newTIParams(t.params) : null;
|
|
|
+ this.properties.push(name);
|
|
|
+ if (!rtl.isString(t.stored)) t.stored = "";
|
|
|
+ return t;
|
|
|
+ };
|
|
|
+ tis.getField = function(index){
|
|
|
+ return this.members[this.fields[index]];
|
|
|
+ };
|
|
|
+ tis.getMethod = function(index){
|
|
|
+ return this.members[this.methods[index]];
|
|
|
+ };
|
|
|
+ tis.getProperty = function(index){
|
|
|
+ return this.members[this.properties[index]];
|
|
|
+ };
|
|
|
+
|
|
|
+ newBaseTI("tTypeInfoRecord",12 /* tkRecord */,rtl.tTypeInfoStruct);
|
|
|
+ newBaseTI("tTypeInfoClass",13 /* tkClass */,rtl.tTypeInfoStruct);
|
|
|
+ newBaseTI("tTypeInfoClassRef",14 /* tkClassRef */);
|
|
|
+ newBaseTI("tTypeInfoInterface",18 /* tkInterface */,rtl.tTypeInfoStruct);
|
|
|
+ newBaseTI("tTypeInfoHelper",19 /* tkHelper */,rtl.tTypeInfoStruct);
|
|
|
+ newBaseTI("tTypeInfoExtClass",20 /* tkExtClass */,rtl.tTypeInfoClass);
|
|
|
+ },
|
|
|
+
|
|
|
+ tSectionRTTI: {
|
|
|
+ $module: null,
|
|
|
+ $inherited: function(name,ancestor,o){
|
|
|
+ if (rtl.debug_rtti){
|
|
|
+ rtl.debug('tSectionRTTI.newTI "'+(this.$module?this.$module.$name:"(no module)")
|
|
|
+ +'"."'+name+'" ('+ancestor.name+') '+(o?'init':'forward'));
|
|
|
+ };
|
|
|
+ var t = this[name];
|
|
|
+ if (t){
|
|
|
+ if (!t.$forward) throw 'duplicate type "'+name+'"';
|
|
|
+ if (!ancestor.isPrototypeOf(t)) throw 'typeinfo ancestor mismatch "'+name+'" ancestor="'+ancestor.name+'" t.name="'+t.name+'"';
|
|
|
+ } else {
|
|
|
+ t = Object.create(ancestor);
|
|
|
+ t.name = name;
|
|
|
+ t.$module = this.$module;
|
|
|
+ this[name] = t;
|
|
|
+ }
|
|
|
+ if (o){
|
|
|
+ delete t.$forward;
|
|
|
+ for (var key in o) if (o.hasOwnProperty(key)) t[key]=o[key];
|
|
|
+ } else {
|
|
|
+ t.$forward = true;
|
|
|
+ }
|
|
|
+ return t;
|
|
|
+ },
|
|
|
+ $Scope: function(name,ancestor,o){
|
|
|
+ var t=this.$inherited(name,ancestor,o);
|
|
|
+ t.members = {};
|
|
|
+ t.names = [];
|
|
|
+ t.fields = [];
|
|
|
+ t.methods = [];
|
|
|
+ t.properties = [];
|
|
|
+ return t;
|
|
|
+ },
|
|
|
+ $TI: function(name,kind,o){ var t=this.$inherited(name,rtl.tTypeInfo,o); t.kind = kind; return t; },
|
|
|
+ $Int: function(name,o){ return this.$inherited(name,rtl.tTypeInfoInteger,o); },
|
|
|
+ $Enum: function(name,o){ return this.$inherited(name,rtl.tTypeInfoEnum,o); },
|
|
|
+ $Set: function(name,o){ return this.$inherited(name,rtl.tTypeInfoSet,o); },
|
|
|
+ $StaticArray: function(name,o){ return this.$inherited(name,rtl.tTypeInfoArray,o); },
|
|
|
+ $DynArray: function(name,o){ return this.$inherited(name,rtl.tTypeInfoDynArray,o); },
|
|
|
+ $ProcVar: function(name,o){ return this.$inherited(name,rtl.tTypeInfoProcVar,o); },
|
|
|
+ $RefToProcVar: function(name,o){ return this.$inherited(name,rtl.tTypeInfoRefToProcVar,o); },
|
|
|
+ $MethodVar: function(name,o){ return this.$inherited(name,rtl.tTypeInfoMethodVar,o); },
|
|
|
+ $Record: function(name,o){ return this.$Scope(name,rtl.tTypeInfoRecord,o); },
|
|
|
+ $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); },
|
|
|
+ $Helper: function(name,o){ return this.$Scope(name,rtl.tTypeInfoHelper,o); },
|
|
|
+ $ExtClass: function(name,o){ return this.$Scope(name,rtl.tTypeInfoExtClass,o); }
|
|
|
+ },
|
|
|
+
|
|
|
+ newTIParam: function(param){
|
|
|
+ // param is an array, 0=name, 1=type, 2=optional flags
|
|
|
+ var t = {
|
|
|
+ name: param[0],
|
|
|
+ typeinfo: param[1],
|
|
|
+ flags: (rtl.isNumber(param[2]) ? param[2] : 0)
|
|
|
+ };
|
|
|
+ return t;
|
|
|
+ },
|
|
|
+
|
|
|
+ newTIParams: function(list){
|
|
|
+ // list: optional array of [paramname,typeinfo,optional flags]
|
|
|
+ var params = [];
|
|
|
+ if (rtl.isArray(list)){
|
|
|
+ for (var i=0; i<list.length; i++) params.push(rtl.newTIParam(list[i]));
|
|
|
+ };
|
|
|
+ return params;
|
|
|
+ },
|
|
|
+
|
|
|
+ newTIProcSig: function(params,result,flags){
|
|
|
+ var s = {
|
|
|
+ params: rtl.newTIParams(params),
|
|
|
+ resulttype: result?result:null,
|
|
|
+ flags: flags?flags:0
|
|
|
+ };
|
|
|
+ return s;
|
|
|
+ },
|
|
|
+
|
|
|
+ addResource: function(aRes){
|
|
|
+ rtl.$res[aRes.name]=aRes;
|
|
|
+ },
|
|
|
+
|
|
|
+ getResource: function(aName){
|
|
|
+ var res = rtl.$res[aName];
|
|
|
+ if (res !== undefined) {
|
|
|
+ return res;
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ getResourceList: function(){
|
|
|
+ return Object.keys(rtl.$res);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+rtl.module("System",[],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ this.sLineBreak = "\n";
|
|
|
+ this.TTextLineBreakStyle = {"0": "tlbsLF", tlbsLF: 0, "1": "tlbsCRLF", tlbsCRLF: 1, "2": "tlbsCR", tlbsCR: 2};
|
|
|
+ rtl.createClass(this,"TObject",null,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ };
|
|
|
+ this.Create = function () {
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ this.Destroy = function () {
|
|
|
+ };
|
|
|
+ this.Free = function () {
|
|
|
+ this.$destroy("Destroy");
|
|
|
+ };
|
|
|
+ this.FieldAddress = function (aName) {
|
|
|
+ var Result = null;
|
|
|
+ Result = null;
|
|
|
+ if (aName === "") return Result;
|
|
|
+ var aClass = this.$class;
|
|
|
+ var ClassTI = null;
|
|
|
+ var myName = aName.toLowerCase();
|
|
|
+ var MemberTI = null;
|
|
|
+ while (aClass !== null) {
|
|
|
+ ClassTI = aClass.$rtti;
|
|
|
+ for (var i = 0, $end2 = ClassTI.fields.length - 1; i <= $end2; i++) {
|
|
|
+ MemberTI = ClassTI.getField(i);
|
|
|
+ if (MemberTI.name.toLowerCase() === myName) {
|
|
|
+ return MemberTI;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ aClass = aClass.$ancestor ? aClass.$ancestor : null;
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.AfterConstruction = function () {
|
|
|
+ };
|
|
|
+ this.BeforeDestruction = function () {
|
|
|
+ };
|
|
|
+ });
|
|
|
+ this.vtInteger = 0;
|
|
|
+ this.vtExtended = 3;
|
|
|
+ this.vtWideChar = 9;
|
|
|
+ this.vtCurrency = 12;
|
|
|
+ this.vtUnicodeString = 18;
|
|
|
+ this.vtNativeInt = 19;
|
|
|
+ rtl.recNewT(this,"TVarRec",function () {
|
|
|
+ this.VType = 0;
|
|
|
+ this.VJSValue = undefined;
|
|
|
+ this.$eq = function (b) {
|
|
|
+ return (this.VType === b.VType) && (this.VJSValue === b.VJSValue) && (this.VJSValue === b.VJSValue) && (this.VJSValue === b.VJSValue) && (this.VJSValue === b.VJSValue) && (this.VJSValue === b.VJSValue) && (this.VJSValue === b.VJSValue) && (this.VJSValue === b.VJSValue);
|
|
|
+ };
|
|
|
+ this.$assign = function (s) {
|
|
|
+ this.VType = s.VType;
|
|
|
+ this.VJSValue = s.VJSValue;
|
|
|
+ this.VJSValue = s.VJSValue;
|
|
|
+ this.VJSValue = s.VJSValue;
|
|
|
+ this.VJSValue = s.VJSValue;
|
|
|
+ this.VJSValue = s.VJSValue;
|
|
|
+ this.VJSValue = s.VJSValue;
|
|
|
+ this.VJSValue = s.VJSValue;
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ this.VarRecs = function () {
|
|
|
+ var Result = [];
|
|
|
+ var i = 0;
|
|
|
+ var v = null;
|
|
|
+ Result = [];
|
|
|
+ while (i < arguments.length) {
|
|
|
+ v = $mod.TVarRec.$new();
|
|
|
+ v.VType = rtl.trunc(arguments[i]);
|
|
|
+ i += 1;
|
|
|
+ v.VJSValue = arguments[i];
|
|
|
+ i += 1;
|
|
|
+ Result.push($mod.TVarRec.$clone(v));
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Trunc = function (A) {
|
|
|
+ if (!Math.trunc) {
|
|
|
+ Math.trunc = function(v) {
|
|
|
+ v = +v;
|
|
|
+ if (!isFinite(v)) return v;
|
|
|
+ return (v - v % 1) || (v < 0 ? -0 : v === 0 ? v : 0);
|
|
|
+ };
|
|
|
+ }
|
|
|
+ $mod.Trunc = Math.trunc;
|
|
|
+ return Math.trunc(A);
|
|
|
+ };
|
|
|
+ this.DefaultTextLineBreakStyle = 0;
|
|
|
+ this.Int = function (A) {
|
|
|
+ var Result = 0.0;
|
|
|
+ Result = $mod.Trunc(A);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Copy = function (S, Index, Size) {
|
|
|
+ if (Index<1) Index = 1;
|
|
|
+ return (Size>0) ? S.substring(Index-1,Index+Size-1) : "";
|
|
|
+ };
|
|
|
+ this.Copy$1 = function (S, Index) {
|
|
|
+ if (Index<1) Index = 1;
|
|
|
+ return S.substr(Index-1);
|
|
|
+ };
|
|
|
+ this.Delete = function (S, Index, Size) {
|
|
|
+ var h = "";
|
|
|
+ if ((Index < 1) || (Index > S.get().length) || (Size <= 0)) return;
|
|
|
+ h = S.get();
|
|
|
+ S.set($mod.Copy(h,1,Index - 1) + $mod.Copy$1(h,Index + Size));
|
|
|
+ };
|
|
|
+ this.Pos = function (Search, InString) {
|
|
|
+ return InString.indexOf(Search)+1;
|
|
|
+ };
|
|
|
+ this.Insert = function (Insertion, Target, Index) {
|
|
|
+ var t = "";
|
|
|
+ if (Insertion === "") return;
|
|
|
+ t = Target.get();
|
|
|
+ if (Index < 1) {
|
|
|
+ Target.set(Insertion + t)}
|
|
|
+ else if (Index > t.length) {
|
|
|
+ Target.set(t + Insertion)}
|
|
|
+ else Target.set($mod.Copy(t,1,Index - 1) + Insertion + $mod.Copy(t,Index,t.length));
|
|
|
+ };
|
|
|
+ this.upcase = function (c) {
|
|
|
+ return c.toUpperCase();
|
|
|
+ };
|
|
|
+ this.val = function (S, NI, Code) {
|
|
|
+ NI.set($impl.valint(S,-9007199254740991,9007199254740991,Code));
|
|
|
+ };
|
|
|
+ this.StringOfChar = function (c, l) {
|
|
|
+ var Result = "";
|
|
|
+ var i = 0;
|
|
|
+ if ((l>0) && c.repeat) return c.repeat(l);
|
|
|
+ Result = "";
|
|
|
+ for (var $l = 1, $end = l; $l <= $end; $l++) {
|
|
|
+ i = $l;
|
|
|
+ Result = Result + c;
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Writeln = function () {
|
|
|
+ var i = 0;
|
|
|
+ var l = 0;
|
|
|
+ var s = "";
|
|
|
+ l = arguments.length - 1;
|
|
|
+ if ($impl.WriteCallBack != null) {
|
|
|
+ for (var $l = 0, $end = l; $l <= $end; $l++) {
|
|
|
+ i = $l;
|
|
|
+ $impl.WriteCallBack(arguments[i],i === l);
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ s = $impl.WriteBuf;
|
|
|
+ for (var $l1 = 0, $end1 = l; $l1 <= $end1; $l1++) {
|
|
|
+ i = $l1;
|
|
|
+ s = s + ("" + arguments[i]);
|
|
|
+ };
|
|
|
+ console.log(s);
|
|
|
+ $impl.WriteBuf = "";
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.Assigned = function (V) {
|
|
|
+ return (V!=undefined) && (V!=null) && (!rtl.isArray(V) || (V.length > 0));
|
|
|
+ };
|
|
|
+ $mod.$implcode = function () {
|
|
|
+ $impl.WriteBuf = "";
|
|
|
+ $impl.WriteCallBack = null;
|
|
|
+ $impl.valint = function (S, MinVal, MaxVal, Code) {
|
|
|
+ var Result = 0;
|
|
|
+ var x = 0.0;
|
|
|
+ if (S === "") {
|
|
|
+ Code.set(1);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ x = Number(S);
|
|
|
+ if (isNaN(x)) {
|
|
|
+ var $tmp = $mod.Copy(S,1,1);
|
|
|
+ if ($tmp === "$") {
|
|
|
+ x = Number("0x" + $mod.Copy$1(S,2))}
|
|
|
+ else if ($tmp === "&") {
|
|
|
+ x = Number("0o" + $mod.Copy$1(S,2))}
|
|
|
+ else if ($tmp === "%") {
|
|
|
+ x = Number("0b" + $mod.Copy$1(S,2))}
|
|
|
+ else {
|
|
|
+ Code.set(1);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ if (isNaN(x) || (x !== $mod.Int(x))) {
|
|
|
+ Code.set(1)}
|
|
|
+ else if ((x < MinVal) || (x > MaxVal)) {
|
|
|
+ Code.set(2)}
|
|
|
+ else {
|
|
|
+ Result = $mod.Trunc(x);
|
|
|
+ Code.set(0);
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ $mod.$init = function () {
|
|
|
+ rtl.exitcode = 0;
|
|
|
+ };
|
|
|
+},[]);
|
|
|
+rtl.module("RTLConsts",["System"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ $mod.$resourcestrings = {SArgumentMissing: {org: 'Missing argument in format "%s"'}, SInvalidFormat: {org: 'Invalid format specifier : "%s"'}, SInvalidArgIndex: {org: 'Invalid argument index in format: "%s"'}, SListCapacityError: {org: "List capacity (%s) exceeded."}, SListCountError: {org: "List count (%s) out of bounds."}, SListIndexError: {org: "List index (%s) out of bounds"}, SSortedListError: {org: "Operation not allowed on sorted list"}, SDuplicateString: {org: "String list does not allow duplicates"}, SErrFindNeedsSortedList: {org: "Cannot use find on unsorted list"}, SInvalidName: {org: 'Invalid component name: "%s"'}, SDuplicateName: {org: 'Duplicate component name: "%s"'}};
|
|
|
+});
|
|
|
+rtl.module("Types",["System"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ this.TDuplicates = {"0": "dupIgnore", dupIgnore: 0, "1": "dupAccept", dupAccept: 1, "2": "dupError", dupError: 2};
|
|
|
+});
|
|
|
+rtl.module("JS",["System","Types"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ rtl.createClass(this,"EJS",pas.System.TObject,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.System.TObject.$init.call(this);
|
|
|
+ this.FMessage = "";
|
|
|
+ };
|
|
|
+ this.Create$1 = function (Msg) {
|
|
|
+ this.FMessage = Msg;
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ this.AsIntNumber = function (v) {
|
|
|
+ return Number(v);
|
|
|
+ };
|
|
|
+ this.New = function (aElements) {
|
|
|
+ var Result = null;
|
|
|
+ var L = 0;
|
|
|
+ var I = 0;
|
|
|
+ var S = "";
|
|
|
+ L = rtl.length(aElements);
|
|
|
+ if ((L % 2) === 1) throw $mod.EJS.$create("Create$1",["Number of arguments must be even"]);
|
|
|
+ I = 0;
|
|
|
+ while (I < L) {
|
|
|
+ if (!rtl.isString(aElements[I])) {
|
|
|
+ S = String(I);
|
|
|
+ throw $mod.EJS.$create("Create$1",["Argument " + S + " must be a string."]);
|
|
|
+ };
|
|
|
+ I += 2;
|
|
|
+ };
|
|
|
+ I = 0;
|
|
|
+ Result = new Object();
|
|
|
+ while (I < L) {
|
|
|
+ S = "" + aElements[I];
|
|
|
+ Result[S] = aElements[I + 1];
|
|
|
+ I += 2;
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.isBoolean = function (v) {
|
|
|
+ return typeof(v) == 'boolean';
|
|
|
+ };
|
|
|
+});
|
|
|
+rtl.module("SysUtils",["System","RTLConsts","JS"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ this.FreeAndNil = function (Obj) {
|
|
|
+ var o = null;
|
|
|
+ o = Obj.get();
|
|
|
+ if (o === null) return;
|
|
|
+ Obj.set(null);
|
|
|
+ o.$destroy("Destroy");
|
|
|
+ };
|
|
|
+ rtl.recNewT(this,"TFormatSettings",function () {
|
|
|
+ this.CurrencyDecimals = 0;
|
|
|
+ this.CurrencyFormat = 0;
|
|
|
+ this.CurrencyString = "";
|
|
|
+ this.DateSeparator = "";
|
|
|
+ this.DecimalSeparator = "";
|
|
|
+ this.LongDateFormat = "";
|
|
|
+ this.LongTimeFormat = "";
|
|
|
+ this.NegCurrFormat = 0;
|
|
|
+ this.ShortDateFormat = "";
|
|
|
+ this.ShortTimeFormat = "";
|
|
|
+ this.ThousandSeparator = "";
|
|
|
+ this.TimeAMString = "";
|
|
|
+ this.TimePMString = "";
|
|
|
+ this.TimeSeparator = "";
|
|
|
+ this.TwoDigitYearCenturyWindow = 0;
|
|
|
+ this.InitLocaleHandler = null;
|
|
|
+ this.$new = function () {
|
|
|
+ var r = Object.create(this);
|
|
|
+ r.DateTimeToStrFormat = rtl.arraySetLength(null,"",2);
|
|
|
+ r.LongDayNames = rtl.arraySetLength(null,"",7);
|
|
|
+ r.LongMonthNames = rtl.arraySetLength(null,"",12);
|
|
|
+ r.ShortDayNames = rtl.arraySetLength(null,"",7);
|
|
|
+ r.ShortMonthNames = rtl.arraySetLength(null,"",12);
|
|
|
+ return r;
|
|
|
+ };
|
|
|
+ this.$eq = function (b) {
|
|
|
+ return (this.CurrencyDecimals === b.CurrencyDecimals) && (this.CurrencyFormat === b.CurrencyFormat) && (this.CurrencyString === b.CurrencyString) && (this.DateSeparator === b.DateSeparator) && rtl.arrayEq(this.DateTimeToStrFormat,b.DateTimeToStrFormat) && (this.DecimalSeparator === b.DecimalSeparator) && (this.LongDateFormat === b.LongDateFormat) && rtl.arrayEq(this.LongDayNames,b.LongDayNames) && rtl.arrayEq(this.LongMonthNames,b.LongMonthNames) && (this.LongTimeFormat === b.LongTimeFormat) && (this.NegCurrFormat === b.NegCurrFormat) && (this.ShortDateFormat === b.ShortDateFormat) && rtl.arrayEq(this.ShortDayNames,b.ShortDayNames) && rtl.arrayEq(this.ShortMonthNames,b.ShortMonthNames) && (this.ShortTimeFormat === b.ShortTimeFormat) && (this.ThousandSeparator === b.ThousandSeparator) && (this.TimeAMString === b.TimeAMString) && (this.TimePMString === b.TimePMString) && (this.TimeSeparator === b.TimeSeparator) && (this.TwoDigitYearCenturyWindow === b.TwoDigitYearCenturyWindow);
|
|
|
+ };
|
|
|
+ this.$assign = function (s) {
|
|
|
+ this.CurrencyDecimals = s.CurrencyDecimals;
|
|
|
+ this.CurrencyFormat = s.CurrencyFormat;
|
|
|
+ this.CurrencyString = s.CurrencyString;
|
|
|
+ this.DateSeparator = s.DateSeparator;
|
|
|
+ this.DateTimeToStrFormat = s.DateTimeToStrFormat.slice(0);
|
|
|
+ this.DecimalSeparator = s.DecimalSeparator;
|
|
|
+ this.LongDateFormat = s.LongDateFormat;
|
|
|
+ this.LongDayNames = s.LongDayNames.slice(0);
|
|
|
+ this.LongMonthNames = s.LongMonthNames.slice(0);
|
|
|
+ this.LongTimeFormat = s.LongTimeFormat;
|
|
|
+ this.NegCurrFormat = s.NegCurrFormat;
|
|
|
+ this.ShortDateFormat = s.ShortDateFormat;
|
|
|
+ this.ShortDayNames = s.ShortDayNames.slice(0);
|
|
|
+ this.ShortMonthNames = s.ShortMonthNames.slice(0);
|
|
|
+ this.ShortTimeFormat = s.ShortTimeFormat;
|
|
|
+ this.ThousandSeparator = s.ThousandSeparator;
|
|
|
+ this.TimeAMString = s.TimeAMString;
|
|
|
+ this.TimePMString = s.TimePMString;
|
|
|
+ this.TimeSeparator = s.TimeSeparator;
|
|
|
+ this.TwoDigitYearCenturyWindow = s.TwoDigitYearCenturyWindow;
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ this.GetJSLocale = function () {
|
|
|
+ return Intl.DateTimeFormat().resolvedOptions().locale;
|
|
|
+ };
|
|
|
+ this.Create = function () {
|
|
|
+ var Result = $mod.TFormatSettings.$new();
|
|
|
+ Result.$assign($mod.TFormatSettings.Create$1($mod.TFormatSettings.GetJSLocale()));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Create$1 = function (ALocale) {
|
|
|
+ var Result = $mod.TFormatSettings.$new();
|
|
|
+ Result.LongDayNames = $impl.DefaultLongDayNames.slice(0);
|
|
|
+ Result.ShortDayNames = $impl.DefaultShortDayNames.slice(0);
|
|
|
+ Result.ShortMonthNames = $impl.DefaultShortMonthNames.slice(0);
|
|
|
+ Result.LongMonthNames = $impl.DefaultLongMonthNames.slice(0);
|
|
|
+ Result.DateTimeToStrFormat[0] = "c";
|
|
|
+ Result.DateTimeToStrFormat[1] = "f";
|
|
|
+ Result.DateSeparator = "-";
|
|
|
+ Result.TimeSeparator = ":";
|
|
|
+ Result.ShortDateFormat = "yyyy-mm-dd";
|
|
|
+ Result.LongDateFormat = "ddd, yyyy-mm-dd";
|
|
|
+ Result.ShortTimeFormat = "hh:nn";
|
|
|
+ Result.LongTimeFormat = "hh:nn:ss";
|
|
|
+ Result.DecimalSeparator = ".";
|
|
|
+ Result.ThousandSeparator = ",";
|
|
|
+ Result.TimeAMString = "AM";
|
|
|
+ Result.TimePMString = "PM";
|
|
|
+ Result.TwoDigitYearCenturyWindow = 50;
|
|
|
+ Result.CurrencyFormat = 0;
|
|
|
+ Result.NegCurrFormat = 0;
|
|
|
+ Result.CurrencyDecimals = 2;
|
|
|
+ Result.CurrencyString = "$";
|
|
|
+ if ($mod.TFormatSettings.InitLocaleHandler != null) $mod.TFormatSettings.InitLocaleHandler($mod.UpperCase(ALocale),$mod.TFormatSettings.$clone(Result));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ },true);
|
|
|
+ rtl.createClass(this,"Exception",pas.System.TObject,function () {
|
|
|
+ this.LogMessageOnCreate = false;
|
|
|
+ this.$init = function () {
|
|
|
+ pas.System.TObject.$init.call(this);
|
|
|
+ this.fMessage = "";
|
|
|
+ this.FNodeJSError = null;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.FNodeJSError = undefined;
|
|
|
+ pas.System.TObject.$final.call(this);
|
|
|
+ };
|
|
|
+ this.Create$1 = function (Msg) {
|
|
|
+ this.fMessage = Msg;
|
|
|
+ this.FNodeJSError = new Error();
|
|
|
+ if (this.LogMessageOnCreate) pas.System.Writeln("Created exception ",this.$classname," with message: ",Msg);
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ this.CreateFmt = function (Msg, Args) {
|
|
|
+ this.Create$1($mod.Format(Msg,Args));
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"EExternal",this.Exception,function () {
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"EConvertError",this.Exception,function () {
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"EExternalException",this.EExternal,function () {
|
|
|
+ });
|
|
|
+ this.TrimLeft = function (S) {
|
|
|
+ return S.replace(/^[\s\uFEFF\xA0\x00-\x1f]+/,'');
|
|
|
+ };
|
|
|
+ this.UpperCase = function (s) {
|
|
|
+ return s.toUpperCase();
|
|
|
+ };
|
|
|
+ this.LowerCase = function (s) {
|
|
|
+ return s.toLowerCase();
|
|
|
+ };
|
|
|
+ this.CompareStr = function (s1, s2) {
|
|
|
+ var l1 = s1.length;
|
|
|
+ var l2 = s2.length;
|
|
|
+ if (l1<=l2){
|
|
|
+ var s = s2.substr(0,l1);
|
|
|
+ if (s1<s){ return -1;
|
|
|
+ } else if (s1>s){ return 1;
|
|
|
+ } else { return l1<l2 ? -1 : 0; };
|
|
|
+ } else {
|
|
|
+ var s = s1.substr(0,l2);
|
|
|
+ if (s<s2){ return -1;
|
|
|
+ } else { return 1; };
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.CompareText = function (s1, s2) {
|
|
|
+ var l1 = s1.toLowerCase();
|
|
|
+ var l2 = s2.toLowerCase();
|
|
|
+ if (l1>l2){ return 1;
|
|
|
+ } else if (l1<l2){ return -1;
|
|
|
+ } else { return 0; };
|
|
|
+ };
|
|
|
+ this.Format = function (Fmt, Args) {
|
|
|
+ var Result = "";
|
|
|
+ Result = $mod.Format$1(Fmt,Args,$mod.FormatSettings);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Format$1 = function (Fmt, Args, aSettings) {
|
|
|
+ var Result = "";
|
|
|
+ var ChPos = 0;
|
|
|
+ var OldPos = 0;
|
|
|
+ var ArgPos = 0;
|
|
|
+ var DoArg = 0;
|
|
|
+ var Len = 0;
|
|
|
+ var Hs = "";
|
|
|
+ var ToAdd = "";
|
|
|
+ var Index = 0;
|
|
|
+ var Width = 0;
|
|
|
+ var Prec = 0;
|
|
|
+ var Left = false;
|
|
|
+ var Fchar = "";
|
|
|
+ var vq = 0;
|
|
|
+ function ReadFormat() {
|
|
|
+ var Result = "";
|
|
|
+ var Value = 0;
|
|
|
+ function ReadInteger() {
|
|
|
+ var Code = 0;
|
|
|
+ var ArgN = 0;
|
|
|
+ if (Value !== -1) return;
|
|
|
+ OldPos = ChPos;
|
|
|
+ while ((ChPos <= Len) && (Fmt.charAt(ChPos - 1) <= "9") && (Fmt.charAt(ChPos - 1) >= "0")) ChPos += 1;
|
|
|
+ if (ChPos > Len) $impl.DoFormatError(1,Fmt);
|
|
|
+ if (Fmt.charAt(ChPos - 1) === "*") {
|
|
|
+ if (Index === 255) {
|
|
|
+ ArgN = ArgPos}
|
|
|
+ else {
|
|
|
+ ArgN = Index;
|
|
|
+ Index += 1;
|
|
|
+ };
|
|
|
+ if ((ChPos > OldPos) || (ArgN > (rtl.length(Args) - 1))) $impl.DoFormatError(1,Fmt);
|
|
|
+ ArgPos = ArgN + 1;
|
|
|
+ var $tmp = Args[ArgN].VType;
|
|
|
+ if ($tmp === 0) {
|
|
|
+ Value = Args[ArgN].VJSValue}
|
|
|
+ else if ($tmp === 19) {
|
|
|
+ Value = Args[ArgN].VJSValue}
|
|
|
+ else {
|
|
|
+ $impl.DoFormatError(1,Fmt);
|
|
|
+ };
|
|
|
+ ChPos += 1;
|
|
|
+ } else {
|
|
|
+ if (OldPos < ChPos) {
|
|
|
+ pas.System.val(pas.System.Copy(Fmt,OldPos,ChPos - OldPos),{get: function () {
|
|
|
+ return Value;
|
|
|
+ }, set: function (v) {
|
|
|
+ Value = v;
|
|
|
+ }},{get: function () {
|
|
|
+ return Code;
|
|
|
+ }, set: function (v) {
|
|
|
+ Code = v;
|
|
|
+ }});
|
|
|
+ if (Code > 0) $impl.DoFormatError(1,Fmt);
|
|
|
+ } else Value = -1;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ function ReadIndex() {
|
|
|
+ if (Fmt.charAt(ChPos - 1) !== ":") {
|
|
|
+ ReadInteger()}
|
|
|
+ else Value = 0;
|
|
|
+ if (Fmt.charAt(ChPos - 1) === ":") {
|
|
|
+ if (Value === -1) $impl.DoFormatError(2,Fmt);
|
|
|
+ Index = Value;
|
|
|
+ Value = -1;
|
|
|
+ ChPos += 1;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ function ReadLeft() {
|
|
|
+ if (Fmt.charAt(ChPos - 1) === "-") {
|
|
|
+ Left = true;
|
|
|
+ ChPos += 1;
|
|
|
+ } else Left = false;
|
|
|
+ };
|
|
|
+ function ReadWidth() {
|
|
|
+ ReadInteger();
|
|
|
+ if (Value !== -1) {
|
|
|
+ Width = Value;
|
|
|
+ Value = -1;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ function ReadPrec() {
|
|
|
+ if (Fmt.charAt(ChPos - 1) === ".") {
|
|
|
+ ChPos += 1;
|
|
|
+ ReadInteger();
|
|
|
+ if (Value === -1) Value = 0;
|
|
|
+ Prec = Value;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ Index = 255;
|
|
|
+ Width = -1;
|
|
|
+ Prec = -1;
|
|
|
+ Value = -1;
|
|
|
+ ChPos += 1;
|
|
|
+ if (Fmt.charAt(ChPos - 1) === "%") {
|
|
|
+ Result = "%";
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ ReadIndex();
|
|
|
+ ReadLeft();
|
|
|
+ ReadWidth();
|
|
|
+ ReadPrec();
|
|
|
+ Result = pas.System.upcase(Fmt.charAt(ChPos - 1));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ function Checkarg(AT, err) {
|
|
|
+ var Result = false;
|
|
|
+ Result = false;
|
|
|
+ if (Index === 255) {
|
|
|
+ DoArg = ArgPos}
|
|
|
+ else DoArg = Index;
|
|
|
+ ArgPos = DoArg + 1;
|
|
|
+ if ((DoArg > (rtl.length(Args) - 1)) || (Args[DoArg].VType !== AT)) {
|
|
|
+ if (err) $impl.DoFormatError(3,Fmt);
|
|
|
+ ArgPos -= 1;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ Result = true;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ Result = "";
|
|
|
+ Len = Fmt.length;
|
|
|
+ ChPos = 1;
|
|
|
+ OldPos = 1;
|
|
|
+ ArgPos = 0;
|
|
|
+ while (ChPos <= Len) {
|
|
|
+ while ((ChPos <= Len) && (Fmt.charAt(ChPos - 1) !== "%")) ChPos += 1;
|
|
|
+ if (ChPos > OldPos) Result = Result + pas.System.Copy(Fmt,OldPos,ChPos - OldPos);
|
|
|
+ if (ChPos < Len) {
|
|
|
+ Fchar = ReadFormat();
|
|
|
+ var $tmp = Fchar;
|
|
|
+ if ($tmp === "D") {
|
|
|
+ if (Checkarg(0,false)) {
|
|
|
+ ToAdd = $mod.IntToStr(Args[DoArg].VJSValue)}
|
|
|
+ else if (Checkarg(19,true)) ToAdd = $mod.IntToStr(Args[DoArg].VJSValue);
|
|
|
+ Width = Math.abs(Width);
|
|
|
+ Index = Prec - ToAdd.length;
|
|
|
+ if (ToAdd.charAt(0) !== "-") {
|
|
|
+ ToAdd = pas.System.StringOfChar("0",Index) + ToAdd}
|
|
|
+ else pas.System.Insert(pas.System.StringOfChar("0",Index + 1),{get: function () {
|
|
|
+ return ToAdd;
|
|
|
+ }, set: function (v) {
|
|
|
+ ToAdd = v;
|
|
|
+ }},2);
|
|
|
+ } else if ($tmp === "U") {
|
|
|
+ if (Checkarg(0,false)) {
|
|
|
+ ToAdd = $mod.IntToStr(Args[DoArg].VJSValue >>> 0)}
|
|
|
+ else if (Checkarg(19,true)) ToAdd = $mod.IntToStr(Args[DoArg].VJSValue);
|
|
|
+ Width = Math.abs(Width);
|
|
|
+ Index = Prec - ToAdd.length;
|
|
|
+ ToAdd = pas.System.StringOfChar("0",Index) + ToAdd;
|
|
|
+ } else if ($tmp === "E") {
|
|
|
+ if (Checkarg(12,false)) {
|
|
|
+ ToAdd = $mod.FloatToStrF$1(Args[DoArg].VJSValue / 10000,2,3,Prec,aSettings)}
|
|
|
+ else if (Checkarg(3,true)) ToAdd = $mod.FloatToStrF$1(Args[DoArg].VJSValue,2,3,Prec,aSettings);
|
|
|
+ } else if ($tmp === "F") {
|
|
|
+ if (Checkarg(12,false)) {
|
|
|
+ ToAdd = $mod.FloatToStrF$1(Args[DoArg].VJSValue / 10000,0,9999,Prec,aSettings)}
|
|
|
+ else if (Checkarg(3,true)) ToAdd = $mod.FloatToStrF$1(Args[DoArg].VJSValue,0,9999,Prec,aSettings);
|
|
|
+ } else if ($tmp === "G") {
|
|
|
+ if (Checkarg(12,false)) {
|
|
|
+ ToAdd = $mod.FloatToStrF$1(Args[DoArg].VJSValue / 10000,1,Prec,3,aSettings)}
|
|
|
+ else if (Checkarg(3,true)) ToAdd = $mod.FloatToStrF$1(Args[DoArg].VJSValue,1,Prec,3,aSettings);
|
|
|
+ } else if ($tmp === "N") {
|
|
|
+ if (Checkarg(12,false)) {
|
|
|
+ ToAdd = $mod.FloatToStrF$1(Args[DoArg].VJSValue / 10000,3,9999,Prec,aSettings)}
|
|
|
+ else if (Checkarg(3,true)) ToAdd = $mod.FloatToStrF$1(Args[DoArg].VJSValue,3,9999,Prec,aSettings);
|
|
|
+ } else if ($tmp === "M") {
|
|
|
+ if (Checkarg(12,false)) {
|
|
|
+ ToAdd = $mod.FloatToStrF$1(Args[DoArg].VJSValue / 10000,4,9999,Prec,aSettings)}
|
|
|
+ else if (Checkarg(3,true)) ToAdd = $mod.FloatToStrF$1(Args[DoArg].VJSValue,4,9999,Prec,aSettings);
|
|
|
+ } else if ($tmp === "S") {
|
|
|
+ if (Checkarg(18,false)) {
|
|
|
+ Hs = Args[DoArg].VJSValue}
|
|
|
+ else if (Checkarg(9,true)) Hs = Args[DoArg].VJSValue;
|
|
|
+ Index = Hs.length;
|
|
|
+ if ((Prec !== -1) && (Index > Prec)) Index = Prec;
|
|
|
+ ToAdd = pas.System.Copy(Hs,1,Index);
|
|
|
+ } else if ($tmp === "P") {
|
|
|
+ if (Checkarg(0,false)) {
|
|
|
+ ToAdd = $mod.IntToHex(Args[DoArg].VJSValue,8)}
|
|
|
+ else if (Checkarg(0,true)) ToAdd = $mod.IntToHex(Args[DoArg].VJSValue,16);
|
|
|
+ } else if ($tmp === "X") {
|
|
|
+ if (Checkarg(0,false)) {
|
|
|
+ vq = Args[DoArg].VJSValue;
|
|
|
+ Index = 16;
|
|
|
+ } else if (Checkarg(19,true)) {
|
|
|
+ vq = Args[DoArg].VJSValue;
|
|
|
+ Index = 31;
|
|
|
+ };
|
|
|
+ if (Prec > Index) {
|
|
|
+ ToAdd = $mod.IntToHex(vq,Index)}
|
|
|
+ else {
|
|
|
+ Index = 1;
|
|
|
+ while ((rtl.shl(1,Index * 4) <= vq) && (Index < 16)) Index += 1;
|
|
|
+ if (Index > Prec) Prec = Index;
|
|
|
+ ToAdd = $mod.IntToHex(vq,Prec);
|
|
|
+ };
|
|
|
+ } else if ($tmp === "%") ToAdd = "%";
|
|
|
+ if (Width !== -1) if (ToAdd.length < Width) if (!Left) {
|
|
|
+ ToAdd = pas.System.StringOfChar(" ",Width - ToAdd.length) + ToAdd}
|
|
|
+ else ToAdd = ToAdd + pas.System.StringOfChar(" ",Width - ToAdd.length);
|
|
|
+ Result = Result + ToAdd;
|
|
|
+ };
|
|
|
+ ChPos += 1;
|
|
|
+ OldPos = ChPos;
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ var Alpha = rtl.createSet(null,65,90,null,97,122,95);
|
|
|
+ var AlphaNum = rtl.unionSet(Alpha,rtl.createSet(null,48,57));
|
|
|
+ var Dot = ".";
|
|
|
+ this.IsValidIdent = function (Ident, AllowDots, StrictDots) {
|
|
|
+ var Result = false;
|
|
|
+ var First = false;
|
|
|
+ var I = 0;
|
|
|
+ var Len = 0;
|
|
|
+ Len = Ident.length;
|
|
|
+ if (Len < 1) return false;
|
|
|
+ First = true;
|
|
|
+ Result = false;
|
|
|
+ I = 1;
|
|
|
+ while (I <= Len) {
|
|
|
+ if (First) {
|
|
|
+ if (!(Ident.charCodeAt(I - 1) in Alpha)) return Result;
|
|
|
+ First = false;
|
|
|
+ } else if (AllowDots && (Ident.charAt(I - 1) === Dot)) {
|
|
|
+ if (StrictDots) {
|
|
|
+ if (I >= Len) return Result;
|
|
|
+ First = true;
|
|
|
+ };
|
|
|
+ } else if (!(Ident.charCodeAt(I - 1) in AlphaNum)) return Result;
|
|
|
+ I = I + 1;
|
|
|
+ };
|
|
|
+ Result = true;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.IntToStr = function (Value) {
|
|
|
+ var Result = "";
|
|
|
+ Result = "" + Value;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.IntToHex = function (Value, Digits) {
|
|
|
+ var Result = "";
|
|
|
+ Result = "";
|
|
|
+ if (Value < 0) if (Value<0) Value = 0xFFFFFFFF + Value + 1;
|
|
|
+ Result=Value.toString(16);
|
|
|
+ Result = $mod.UpperCase(Result);
|
|
|
+ while (Result.length < Digits) Result = "0" + Result;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.TFloatFormat = {"0": "ffFixed", ffFixed: 0, "1": "ffGeneral", ffGeneral: 1, "2": "ffExponent", ffExponent: 2, "3": "ffNumber", ffNumber: 3, "4": "ffCurrency", ffCurrency: 4};
|
|
|
+ this.FloatToStrF$1 = function (Value, format, Precision, Digits, aSettings) {
|
|
|
+ var Result = "";
|
|
|
+ var TS = "";
|
|
|
+ var DS = "";
|
|
|
+ DS = aSettings.DecimalSeparator;
|
|
|
+ TS = aSettings.ThousandSeparator;
|
|
|
+ var $tmp = format;
|
|
|
+ if ($tmp === 1) {
|
|
|
+ Result = $impl.FormatGeneralFloat(Value,Precision,DS)}
|
|
|
+ else if ($tmp === 2) {
|
|
|
+ Result = $impl.FormatExponentFloat(Value,Precision,Digits,DS)}
|
|
|
+ else if ($tmp === 0) {
|
|
|
+ Result = $impl.FormatFixedFloat(Value,Digits,DS)}
|
|
|
+ else if ($tmp === 3) {
|
|
|
+ Result = $impl.FormatNumberFloat(Value,Digits,DS,TS)}
|
|
|
+ else if ($tmp === 4) Result = $impl.FormatNumberCurrency(Value * 10000,Digits,aSettings);
|
|
|
+ if ((format !== 4) && (Result.length > 1) && (Result.charAt(0) === "-")) $impl.RemoveLeadingNegativeSign({get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},DS,TS);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.OnGetEnvironmentVariable = null;
|
|
|
+ this.OnGetEnvironmentString = null;
|
|
|
+ this.OnGetEnvironmentVariableCount = null;
|
|
|
+ this.GetEnvironmentVariableCount = function () {
|
|
|
+ var Result = 0;
|
|
|
+ if ($mod.OnGetEnvironmentVariableCount != null) {
|
|
|
+ Result = $mod.OnGetEnvironmentVariableCount()}
|
|
|
+ else Result = 0;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetEnvironmentString = function (Index) {
|
|
|
+ var Result = "";
|
|
|
+ if ($mod.OnGetEnvironmentString != null) {
|
|
|
+ Result = $mod.OnGetEnvironmentString(Index)}
|
|
|
+ else Result = "";
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.TimeSeparator = "";
|
|
|
+ this.DateSeparator = "";
|
|
|
+ this.ShortDateFormat = "";
|
|
|
+ this.LongDateFormat = "";
|
|
|
+ this.ShortTimeFormat = "";
|
|
|
+ this.LongTimeFormat = "";
|
|
|
+ this.DecimalSeparator = "";
|
|
|
+ this.ThousandSeparator = "";
|
|
|
+ this.TimeAMString = "";
|
|
|
+ this.TimePMString = "";
|
|
|
+ this.ShortMonthNames = rtl.arraySetLength(null,"",12);
|
|
|
+ this.LongMonthNames = rtl.arraySetLength(null,"",12);
|
|
|
+ this.ShortDayNames = rtl.arraySetLength(null,"",7);
|
|
|
+ this.LongDayNames = rtl.arraySetLength(null,"",7);
|
|
|
+ this.FormatSettings = this.TFormatSettings.$new();
|
|
|
+ this.CurrencyFormat = 0;
|
|
|
+ this.NegCurrFormat = 0;
|
|
|
+ this.CurrencyDecimals = 0;
|
|
|
+ this.CurrencyString = "";
|
|
|
+ $mod.$implcode = function () {
|
|
|
+ $impl.DefaultShortMonthNames = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
|
|
+ $impl.DefaultLongMonthNames = ["January","February","March","April","May","June","July","August","September","October","November","December"];
|
|
|
+ $impl.DefaultShortDayNames = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
|
|
|
+ $impl.DefaultLongDayNames = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
|
|
|
+ $impl.feInvalidFormat = 1;
|
|
|
+ $impl.feMissingArgument = 2;
|
|
|
+ $impl.feInvalidArgIndex = 3;
|
|
|
+ $impl.DoFormatError = function (ErrCode, fmt) {
|
|
|
+ var $tmp = ErrCode;
|
|
|
+ if ($tmp === 1) {
|
|
|
+ throw $mod.EConvertError.$create("CreateFmt",[rtl.getResStr(pas.RTLConsts,"SInvalidFormat"),pas.System.VarRecs(18,fmt)])}
|
|
|
+ else if ($tmp === 2) {
|
|
|
+ throw $mod.EConvertError.$create("CreateFmt",[rtl.getResStr(pas.RTLConsts,"SArgumentMissing"),pas.System.VarRecs(18,fmt)])}
|
|
|
+ else if ($tmp === 3) throw $mod.EConvertError.$create("CreateFmt",[rtl.getResStr(pas.RTLConsts,"SInvalidArgIndex"),pas.System.VarRecs(18,fmt)]);
|
|
|
+ };
|
|
|
+ $impl.maxdigits = 15;
|
|
|
+ $impl.ReplaceDecimalSep = function (S, DS) {
|
|
|
+ var Result = "";
|
|
|
+ var P = 0;
|
|
|
+ P = pas.System.Pos(".",S);
|
|
|
+ if (P > 0) {
|
|
|
+ Result = pas.System.Copy(S,1,P - 1) + DS + pas.System.Copy(S,P + 1,S.length - P)}
|
|
|
+ else Result = S;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ $impl.FormatGeneralFloat = function (Value, Precision, DS) {
|
|
|
+ var Result = "";
|
|
|
+ var P = 0;
|
|
|
+ var PE = 0;
|
|
|
+ var Q = 0;
|
|
|
+ var Exponent = 0;
|
|
|
+ if ((Precision === -1) || (Precision > 15)) Precision = 15;
|
|
|
+ Result = rtl.floatToStr(Value,Precision + 7);
|
|
|
+ Result = $mod.TrimLeft(Result);
|
|
|
+ P = pas.System.Pos(".",Result);
|
|
|
+ if (P === 0) return Result;
|
|
|
+ PE = pas.System.Pos("E",Result);
|
|
|
+ if (PE === 0) {
|
|
|
+ Result = $impl.ReplaceDecimalSep(Result,DS);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ Q = PE + 2;
|
|
|
+ Exponent = 0;
|
|
|
+ while (Q <= Result.length) {
|
|
|
+ Exponent = ((Exponent * 10) + Result.charCodeAt(Q - 1)) - 48;
|
|
|
+ Q += 1;
|
|
|
+ };
|
|
|
+ if (Result.charAt((PE + 1) - 1) === "-") Exponent = -Exponent;
|
|
|
+ if (((P + Exponent) < PE) && (Exponent > -6)) {
|
|
|
+ Result = rtl.strSetLength(Result,PE - 1);
|
|
|
+ if (Exponent >= 0) {
|
|
|
+ for (var $l = 0, $end = Exponent - 1; $l <= $end; $l++) {
|
|
|
+ Q = $l;
|
|
|
+ Result = rtl.setCharAt(Result,P - 1,Result.charAt((P + 1) - 1));
|
|
|
+ P += 1;
|
|
|
+ };
|
|
|
+ Result = rtl.setCharAt(Result,P - 1,".");
|
|
|
+ P = 1;
|
|
|
+ if (Result.charAt(P - 1) === "-") P += 1;
|
|
|
+ while ((Result.charAt(P - 1) === "0") && (P < Result.length) && (pas.System.Copy(Result,P + 1,DS.length) !== DS)) pas.System.Delete({get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},P,1);
|
|
|
+ } else {
|
|
|
+ pas.System.Insert(pas.System.Copy("00000",1,-Exponent),{get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},P - 1);
|
|
|
+ Result = rtl.setCharAt(Result,P - Exponent - 1,Result.charAt(P - Exponent - 1 - 1));
|
|
|
+ Result = rtl.setCharAt(Result,P - 1,".");
|
|
|
+ if (Exponent !== -1) Result = rtl.setCharAt(Result,P - Exponent - 1 - 1,"0");
|
|
|
+ };
|
|
|
+ Q = Result.length;
|
|
|
+ while ((Q > 0) && (Result.charAt(Q - 1) === "0")) Q -= 1;
|
|
|
+ if (Result.charAt(Q - 1) === ".") Q -= 1;
|
|
|
+ if ((Q === 0) || ((Q === 1) && (Result.charAt(0) === "-"))) {
|
|
|
+ Result = "0"}
|
|
|
+ else Result = rtl.strSetLength(Result,Q);
|
|
|
+ } else {
|
|
|
+ while (Result.charAt(PE - 1 - 1) === "0") {
|
|
|
+ pas.System.Delete({get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},PE - 1,1);
|
|
|
+ PE -= 1;
|
|
|
+ };
|
|
|
+ if (Result.charAt(PE - 1 - 1) === DS) {
|
|
|
+ pas.System.Delete({get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},PE - 1,1);
|
|
|
+ PE -= 1;
|
|
|
+ };
|
|
|
+ if (Result.charAt((PE + 1) - 1) === "+") {
|
|
|
+ pas.System.Delete({get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},PE + 1,1)}
|
|
|
+ else PE += 1;
|
|
|
+ while (Result.charAt((PE + 1) - 1) === "0") pas.System.Delete({get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},PE + 1,1);
|
|
|
+ };
|
|
|
+ Result = $impl.ReplaceDecimalSep(Result,DS);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ $impl.FormatExponentFloat = function (Value, Precision, Digits, DS) {
|
|
|
+ var Result = "";
|
|
|
+ var P = 0;
|
|
|
+ DS = $mod.FormatSettings.DecimalSeparator;
|
|
|
+ if ((Precision === -1) || (Precision > 15)) Precision = 15;
|
|
|
+ Result = rtl.floatToStr(Value,Precision + 7);
|
|
|
+ while (Result.charAt(0) === " ") pas.System.Delete({get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},1,1);
|
|
|
+ P = pas.System.Pos("E",Result);
|
|
|
+ if (P === 0) {
|
|
|
+ Result = $impl.ReplaceDecimalSep(Result,DS);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ P += 2;
|
|
|
+ if (Digits > 4) Digits = 4;
|
|
|
+ Digits = (Result.length - P - Digits) + 1;
|
|
|
+ if (Digits < 0) {
|
|
|
+ pas.System.Insert(pas.System.Copy("0000",1,-Digits),{get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},P)}
|
|
|
+ else while ((Digits > 0) && (Result.charAt(P - 1) === "0")) {
|
|
|
+ pas.System.Delete({get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},P,1);
|
|
|
+ if (P > Result.length) {
|
|
|
+ pas.System.Delete({get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},P - 2,2);
|
|
|
+ break;
|
|
|
+ };
|
|
|
+ Digits -= 1;
|
|
|
+ };
|
|
|
+ Result = $impl.ReplaceDecimalSep(Result,DS);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ $impl.FormatFixedFloat = function (Value, Digits, DS) {
|
|
|
+ var Result = "";
|
|
|
+ if (Digits === -1) {
|
|
|
+ Digits = 2}
|
|
|
+ else if (Digits > 18) Digits = 18;
|
|
|
+ Result = rtl.floatToStr(Value,0,Digits);
|
|
|
+ if ((Result !== "") && (Result.charAt(0) === " ")) pas.System.Delete({get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},1,1);
|
|
|
+ Result = $impl.ReplaceDecimalSep(Result,DS);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ $impl.FormatNumberFloat = function (Value, Digits, DS, TS) {
|
|
|
+ var Result = "";
|
|
|
+ var P = 0;
|
|
|
+ if (Digits === -1) {
|
|
|
+ Digits = 2}
|
|
|
+ else if (Digits > 15) Digits = 15;
|
|
|
+ Result = rtl.floatToStr(Value,0,Digits);
|
|
|
+ if ((Result !== "") && (Result.charAt(0) === " ")) pas.System.Delete({get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},1,1);
|
|
|
+ P = pas.System.Pos(".",Result);
|
|
|
+ if (P <= 0) P = Result.length + 1;
|
|
|
+ Result = $impl.ReplaceDecimalSep(Result,DS);
|
|
|
+ P -= 3;
|
|
|
+ if ((TS !== "") && (TS !== "\x00")) while (P > 1) {
|
|
|
+ if (Result.charAt(P - 1 - 1) !== "-") pas.System.Insert(TS,{get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},P);
|
|
|
+ P -= 3;
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ $impl.RemoveLeadingNegativeSign = function (AValue, DS, aThousandSeparator) {
|
|
|
+ var Result = false;
|
|
|
+ var i = 0;
|
|
|
+ var TS = "";
|
|
|
+ var StartPos = 0;
|
|
|
+ Result = false;
|
|
|
+ StartPos = 2;
|
|
|
+ TS = aThousandSeparator;
|
|
|
+ for (var $l = StartPos, $end = AValue.get().length; $l <= $end; $l++) {
|
|
|
+ i = $l;
|
|
|
+ Result = (AValue.get().charCodeAt(i - 1) in rtl.createSet(48,DS.charCodeAt(),69,43)) || (AValue.get().charAt(i - 1) === TS);
|
|
|
+ if (!Result) break;
|
|
|
+ };
|
|
|
+ if (Result && (AValue.get().charAt(0) === "-")) pas.System.Delete(AValue,1,1);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ $impl.FormatNumberCurrency = function (Value, Digits, aSettings) {
|
|
|
+ var Result = "";
|
|
|
+ var Negative = false;
|
|
|
+ var P = 0;
|
|
|
+ var CS = "";
|
|
|
+ var DS = "";
|
|
|
+ var TS = "";
|
|
|
+ DS = aSettings.DecimalSeparator;
|
|
|
+ TS = aSettings.ThousandSeparator;
|
|
|
+ CS = aSettings.CurrencyString;
|
|
|
+ if (Digits === -1) {
|
|
|
+ Digits = aSettings.CurrencyDecimals}
|
|
|
+ else if (Digits > 18) Digits = 18;
|
|
|
+ Result = rtl.floatToStr(Value / 10000,0,Digits);
|
|
|
+ Negative = Result.charAt(0) === "-";
|
|
|
+ if (Negative) pas.System.Delete({get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},1,1);
|
|
|
+ P = pas.System.Pos(".",Result);
|
|
|
+ if (TS !== "") {
|
|
|
+ if (P !== 0) {
|
|
|
+ Result = $impl.ReplaceDecimalSep(Result,DS)}
|
|
|
+ else P = Result.length + 1;
|
|
|
+ P -= 3;
|
|
|
+ while (P > 1) {
|
|
|
+ pas.System.Insert(TS,{get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},P);
|
|
|
+ P -= 3;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ if (Negative) $impl.RemoveLeadingNegativeSign({get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }},DS,TS);
|
|
|
+ if (!Negative) {
|
|
|
+ var $tmp = aSettings.CurrencyFormat;
|
|
|
+ if ($tmp === 0) {
|
|
|
+ Result = CS + Result}
|
|
|
+ else if ($tmp === 1) {
|
|
|
+ Result = Result + CS}
|
|
|
+ else if ($tmp === 2) {
|
|
|
+ Result = CS + " " + Result}
|
|
|
+ else if ($tmp === 3) Result = Result + " " + CS;
|
|
|
+ } else {
|
|
|
+ var $tmp1 = aSettings.NegCurrFormat;
|
|
|
+ if ($tmp1 === 0) {
|
|
|
+ Result = "(" + CS + Result + ")"}
|
|
|
+ else if ($tmp1 === 1) {
|
|
|
+ Result = "-" + CS + Result}
|
|
|
+ else if ($tmp1 === 2) {
|
|
|
+ Result = CS + "-" + Result}
|
|
|
+ else if ($tmp1 === 3) {
|
|
|
+ Result = CS + Result + "-"}
|
|
|
+ else if ($tmp1 === 4) {
|
|
|
+ Result = "(" + Result + CS + ")"}
|
|
|
+ else if ($tmp1 === 5) {
|
|
|
+ Result = "-" + Result + CS}
|
|
|
+ else if ($tmp1 === 6) {
|
|
|
+ Result = Result + "-" + CS}
|
|
|
+ else if ($tmp1 === 7) {
|
|
|
+ Result = Result + CS + "-"}
|
|
|
+ else if ($tmp1 === 8) {
|
|
|
+ Result = "-" + Result + " " + CS}
|
|
|
+ else if ($tmp1 === 9) {
|
|
|
+ Result = "-" + CS + " " + Result}
|
|
|
+ else if ($tmp1 === 10) {
|
|
|
+ Result = Result + " " + CS + "-"}
|
|
|
+ else if ($tmp1 === 11) {
|
|
|
+ Result = CS + " " + Result + "-"}
|
|
|
+ else if ($tmp1 === 12) {
|
|
|
+ Result = CS + " " + "-" + Result}
|
|
|
+ else if ($tmp1 === 13) {
|
|
|
+ Result = Result + "-" + " " + CS}
|
|
|
+ else if ($tmp1 === 14) {
|
|
|
+ Result = "(" + CS + " " + Result + ")"}
|
|
|
+ else if ($tmp1 === 15) Result = "(" + Result + " " + CS + ")";
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ $impl.InitGlobalFormatSettings = function () {
|
|
|
+ $mod.FormatSettings.$assign($mod.TFormatSettings.Create());
|
|
|
+ $mod.TimeSeparator = $mod.FormatSettings.TimeSeparator;
|
|
|
+ $mod.DateSeparator = $mod.FormatSettings.DateSeparator;
|
|
|
+ $mod.ShortDateFormat = $mod.FormatSettings.ShortDateFormat;
|
|
|
+ $mod.LongDateFormat = $mod.FormatSettings.LongDateFormat;
|
|
|
+ $mod.ShortTimeFormat = $mod.FormatSettings.ShortTimeFormat;
|
|
|
+ $mod.LongTimeFormat = $mod.FormatSettings.LongTimeFormat;
|
|
|
+ $mod.DecimalSeparator = $mod.FormatSettings.DecimalSeparator;
|
|
|
+ $mod.ThousandSeparator = $mod.FormatSettings.ThousandSeparator;
|
|
|
+ $mod.TimeAMString = $mod.FormatSettings.TimeAMString;
|
|
|
+ $mod.TimePMString = $mod.FormatSettings.TimePMString;
|
|
|
+ $mod.CurrencyFormat = $mod.FormatSettings.CurrencyFormat;
|
|
|
+ $mod.NegCurrFormat = $mod.FormatSettings.NegCurrFormat;
|
|
|
+ $mod.CurrencyDecimals = $mod.FormatSettings.CurrencyDecimals;
|
|
|
+ $mod.CurrencyString = $mod.FormatSettings.CurrencyString;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ $mod.$init = function () {
|
|
|
+ (function () {
|
|
|
+ $impl.InitGlobalFormatSettings();
|
|
|
+ })();
|
|
|
+ $mod.ShortMonthNames = $impl.DefaultShortMonthNames.slice(0);
|
|
|
+ $mod.LongMonthNames = $impl.DefaultLongMonthNames.slice(0);
|
|
|
+ $mod.ShortDayNames = $impl.DefaultShortDayNames.slice(0);
|
|
|
+ $mod.LongDayNames = $impl.DefaultLongDayNames.slice(0);
|
|
|
+ };
|
|
|
+},[]);
|
|
|
+rtl.module("Classes",["System","RTLConsts","Types","SysUtils","JS"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ rtl.createClass(this,"EListError",pas.SysUtils.Exception,function () {
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"EStringListError",this.EListError,function () {
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"EComponentError",pas.SysUtils.Exception,function () {
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"TFPList",pas.System.TObject,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.System.TObject.$init.call(this);
|
|
|
+ this.FList = [];
|
|
|
+ this.FCount = 0;
|
|
|
+ this.FCapacity = 0;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.FList = undefined;
|
|
|
+ pas.System.TObject.$final.call(this);
|
|
|
+ };
|
|
|
+ this.Get = function (Index) {
|
|
|
+ var Result = undefined;
|
|
|
+ if ((Index < 0) || (Index >= this.FCount)) this.RaiseIndexError(Index);
|
|
|
+ Result = this.FList[Index];
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SetCapacity = function (NewCapacity) {
|
|
|
+ if (NewCapacity < this.FCount) this.$class.Error(rtl.getResStr(pas.RTLConsts,"SListCapacityError"),"" + NewCapacity);
|
|
|
+ if (NewCapacity === this.FCapacity) return;
|
|
|
+ this.FList = rtl.arraySetLength(this.FList,undefined,NewCapacity);
|
|
|
+ this.FCapacity = NewCapacity;
|
|
|
+ };
|
|
|
+ this.SetCount = function (NewCount) {
|
|
|
+ if (NewCount < 0) this.$class.Error(rtl.getResStr(pas.RTLConsts,"SListCountError"),"" + NewCount);
|
|
|
+ if (NewCount > this.FCount) {
|
|
|
+ if (NewCount > this.FCapacity) this.SetCapacity(NewCount);
|
|
|
+ };
|
|
|
+ this.FCount = NewCount;
|
|
|
+ };
|
|
|
+ this.RaiseIndexError = function (Index) {
|
|
|
+ this.$class.Error(rtl.getResStr(pas.RTLConsts,"SListIndexError"),"" + Index);
|
|
|
+ };
|
|
|
+ this.Destroy = function () {
|
|
|
+ this.Clear();
|
|
|
+ pas.System.TObject.Destroy.call(this);
|
|
|
+ };
|
|
|
+ this.Add = function (Item) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FCount === this.FCapacity) this.Expand();
|
|
|
+ this.FList[this.FCount] = Item;
|
|
|
+ Result = this.FCount;
|
|
|
+ this.FCount += 1;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Clear = function () {
|
|
|
+ if (rtl.length(this.FList) > 0) {
|
|
|
+ this.SetCount(0);
|
|
|
+ this.SetCapacity(0);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.Delete = function (Index) {
|
|
|
+ if ((Index < 0) || (Index >= this.FCount)) this.$class.Error(rtl.getResStr(pas.RTLConsts,"SListIndexError"),"" + Index);
|
|
|
+ this.FCount = this.FCount - 1;
|
|
|
+ this.FList.splice(Index,1);
|
|
|
+ this.FCapacity -= 1;
|
|
|
+ };
|
|
|
+ this.Error = function (Msg, Data) {
|
|
|
+ throw $mod.EListError.$create("CreateFmt",[Msg,pas.System.VarRecs(18,Data)]);
|
|
|
+ };
|
|
|
+ this.Expand = function () {
|
|
|
+ var Result = null;
|
|
|
+ var IncSize = 0;
|
|
|
+ if (this.FCount < this.FCapacity) return this;
|
|
|
+ IncSize = 4;
|
|
|
+ if (this.FCapacity > 3) IncSize = IncSize + 4;
|
|
|
+ if (this.FCapacity > 8) IncSize = IncSize + 8;
|
|
|
+ if (this.FCapacity > 127) IncSize += this.FCapacity >>> 2;
|
|
|
+ this.SetCapacity(this.FCapacity + IncSize);
|
|
|
+ Result = this;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.IndexOf = function (Item) {
|
|
|
+ var Result = 0;
|
|
|
+ var C = 0;
|
|
|
+ Result = 0;
|
|
|
+ C = this.FCount;
|
|
|
+ while ((Result < C) && (this.FList[Result] != Item)) Result += 1;
|
|
|
+ if (Result >= C) Result = -1;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Last = function () {
|
|
|
+ var Result = undefined;
|
|
|
+ if (this.FCount === 0) {
|
|
|
+ Result = null}
|
|
|
+ else Result = this.Get(this.FCount - 1);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Remove = function (Item) {
|
|
|
+ var Result = 0;
|
|
|
+ Result = this.IndexOf(Item);
|
|
|
+ if (Result !== -1) this.Delete(Result);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"TPersistent",pas.System.TObject,function () {
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"TStrings",this.TPersistent,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ $mod.TPersistent.$init.call(this);
|
|
|
+ this.FSpecialCharsInited = false;
|
|
|
+ this.FAlwaysQuote = false;
|
|
|
+ this.FQuoteChar = "";
|
|
|
+ this.FDelimiter = "";
|
|
|
+ this.FNameValueSeparator = "";
|
|
|
+ this.FUpdateCount = 0;
|
|
|
+ this.FLBS = 0;
|
|
|
+ this.FSkipLastLineBreak = false;
|
|
|
+ this.FLineBreak = "";
|
|
|
+ };
|
|
|
+ this.GetSkipLastLineBreak = function () {
|
|
|
+ var Result = false;
|
|
|
+ this.CheckSpecialChars();
|
|
|
+ Result = this.FSkipLastLineBreak;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Error = function (Msg, Data) {
|
|
|
+ throw $mod.EStringListError.$create("CreateFmt",[Msg,pas.System.VarRecs(18,pas.SysUtils.IntToStr(Data))]);
|
|
|
+ };
|
|
|
+ this.GetCapacity = function () {
|
|
|
+ var Result = 0;
|
|
|
+ Result = this.GetCount();
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetTextStr = function () {
|
|
|
+ var Result = "";
|
|
|
+ var I = 0;
|
|
|
+ var S = "";
|
|
|
+ var NL = "";
|
|
|
+ this.CheckSpecialChars();
|
|
|
+ if (this.FLineBreak !== pas.System.sLineBreak) {
|
|
|
+ NL = this.FLineBreak}
|
|
|
+ else {
|
|
|
+ var $tmp = this.FLBS;
|
|
|
+ if ($tmp === 0) {
|
|
|
+ NL = "\n"}
|
|
|
+ else if ($tmp === 1) {
|
|
|
+ NL = "\r\n"}
|
|
|
+ else if ($tmp === 2) NL = "\r";
|
|
|
+ };
|
|
|
+ Result = "";
|
|
|
+ for (var $l = 0, $end = this.GetCount() - 1; $l <= $end; $l++) {
|
|
|
+ I = $l;
|
|
|
+ S = this.Get(I);
|
|
|
+ Result = Result + S;
|
|
|
+ if ((I < (this.GetCount() - 1)) || !this.GetSkipLastLineBreak()) Result = Result + NL;
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.CheckSpecialChars = function () {
|
|
|
+ if (!this.FSpecialCharsInited) {
|
|
|
+ this.FQuoteChar = '"';
|
|
|
+ this.FDelimiter = ",";
|
|
|
+ this.FNameValueSeparator = "=";
|
|
|
+ this.FLBS = pas.System.DefaultTextLineBreakStyle;
|
|
|
+ this.FSpecialCharsInited = true;
|
|
|
+ this.FLineBreak = pas.System.sLineBreak;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.Create$1 = function () {
|
|
|
+ pas.System.TObject.Create.call(this);
|
|
|
+ this.FAlwaysQuote = false;
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ this.Destroy = function () {
|
|
|
+ pas.System.TObject.Destroy.call(this);
|
|
|
+ };
|
|
|
+ this.Add = function (S) {
|
|
|
+ var Result = 0;
|
|
|
+ Result = this.GetCount();
|
|
|
+ this.Insert(this.GetCount(),S);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.recNewT(this,"TStringItem",function () {
|
|
|
+ this.FString = "";
|
|
|
+ this.FObject = null;
|
|
|
+ this.$eq = function (b) {
|
|
|
+ return (this.FString === b.FString) && (this.FObject === b.FObject);
|
|
|
+ };
|
|
|
+ this.$assign = function (s) {
|
|
|
+ this.FString = s.FString;
|
|
|
+ this.FObject = s.FObject;
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ this.TStringsSortStyle = {"0": "sslNone", sslNone: 0, "1": "sslUser", sslUser: 1, "2": "sslAuto", sslAuto: 2};
|
|
|
+ rtl.createClass(this,"TStringList",this.TStrings,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ $mod.TStrings.$init.call(this);
|
|
|
+ this.FList = [];
|
|
|
+ this.FCount = 0;
|
|
|
+ this.FOnChange = null;
|
|
|
+ this.FOnChanging = null;
|
|
|
+ this.FDuplicates = 0;
|
|
|
+ this.FCaseSensitive = false;
|
|
|
+ this.FOwnsObjects = false;
|
|
|
+ this.FSortStyle = 0;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.FList = undefined;
|
|
|
+ this.FOnChange = undefined;
|
|
|
+ this.FOnChanging = undefined;
|
|
|
+ $mod.TStrings.$final.call(this);
|
|
|
+ };
|
|
|
+ this.GetSorted = function () {
|
|
|
+ var Result = false;
|
|
|
+ Result = this.FSortStyle in rtl.createSet(1,2);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Grow = function () {
|
|
|
+ var NC = 0;
|
|
|
+ NC = this.GetCapacity();
|
|
|
+ if (NC >= 256) {
|
|
|
+ NC = NC + rtl.trunc(NC / 4)}
|
|
|
+ else if (NC === 0) {
|
|
|
+ NC = 4}
|
|
|
+ else NC = NC * 4;
|
|
|
+ this.SetCapacity(NC);
|
|
|
+ };
|
|
|
+ this.InternalClear = function (FromIndex, ClearOnly) {
|
|
|
+ var I = 0;
|
|
|
+ if (FromIndex < this.FCount) {
|
|
|
+ if (this.FOwnsObjects) {
|
|
|
+ for (var $l = FromIndex, $end = this.FCount - 1; $l <= $end; $l++) {
|
|
|
+ I = $l;
|
|
|
+ this.FList[I].FString = "";
|
|
|
+ pas.SysUtils.FreeAndNil({p: this.FList[I], get: function () {
|
|
|
+ return this.p.FObject;
|
|
|
+ }, set: function (v) {
|
|
|
+ this.p.FObject = v;
|
|
|
+ }});
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ for (var $l1 = FromIndex, $end1 = this.FCount - 1; $l1 <= $end1; $l1++) {
|
|
|
+ I = $l1;
|
|
|
+ this.FList[I].FString = "";
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.FCount = FromIndex;
|
|
|
+ };
|
|
|
+ if (!ClearOnly) this.SetCapacity(0);
|
|
|
+ };
|
|
|
+ this.CheckIndex = function (AIndex) {
|
|
|
+ if ((AIndex < 0) || (AIndex >= this.FCount)) this.Error(rtl.getResStr(pas.RTLConsts,"SListIndexError"),AIndex);
|
|
|
+ };
|
|
|
+ this.Changed = function () {
|
|
|
+ if (this.FUpdateCount === 0) {
|
|
|
+ if (this.FOnChange != null) this.FOnChange(this);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.Changing = function () {
|
|
|
+ if (this.FUpdateCount === 0) if (this.FOnChanging != null) this.FOnChanging(this);
|
|
|
+ };
|
|
|
+ this.Get = function (Index) {
|
|
|
+ var Result = "";
|
|
|
+ this.CheckIndex(Index);
|
|
|
+ Result = this.FList[Index].FString;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetCapacity = function () {
|
|
|
+ var Result = 0;
|
|
|
+ Result = rtl.length(this.FList);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetCount = function () {
|
|
|
+ var Result = 0;
|
|
|
+ Result = this.FCount;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SetCapacity = function (NewCapacity) {
|
|
|
+ if (NewCapacity < 0) this.Error(rtl.getResStr(pas.RTLConsts,"SListCapacityError"),NewCapacity);
|
|
|
+ if (NewCapacity !== this.GetCapacity()) this.FList = rtl.arraySetLength(this.FList,$mod.TStringItem,NewCapacity);
|
|
|
+ };
|
|
|
+ this.InsertItem = function (Index, S) {
|
|
|
+ this.InsertItem$1(Index,S,null);
|
|
|
+ };
|
|
|
+ this.InsertItem$1 = function (Index, S, O) {
|
|
|
+ var It = $mod.TStringItem.$new();
|
|
|
+ this.Changing();
|
|
|
+ if (this.FCount === this.GetCapacity()) this.Grow();
|
|
|
+ It.FString = S;
|
|
|
+ It.FObject = O;
|
|
|
+ this.FList.splice(Index,0,It);
|
|
|
+ this.FCount += 1;
|
|
|
+ this.Changed();
|
|
|
+ };
|
|
|
+ this.DoCompareText = function (s1, s2) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FCaseSensitive) {
|
|
|
+ Result = pas.SysUtils.CompareStr(s1,s2)}
|
|
|
+ else Result = pas.SysUtils.CompareText(s1,s2);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Destroy = function () {
|
|
|
+ this.InternalClear(0,false);
|
|
|
+ $mod.TStrings.Destroy.call(this);
|
|
|
+ };
|
|
|
+ this.Add = function (S) {
|
|
|
+ var Result = 0;
|
|
|
+ if (!(this.FSortStyle === 2)) {
|
|
|
+ Result = this.FCount}
|
|
|
+ else if (this.Find(S,{get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }})) {
|
|
|
+ var $tmp = this.FDuplicates;
|
|
|
+ if ($tmp === 0) {
|
|
|
+ return Result}
|
|
|
+ else if ($tmp === 2) this.Error(rtl.getResStr(pas.RTLConsts,"SDuplicateString"),0);
|
|
|
+ };
|
|
|
+ this.InsertItem(Result,S);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Find = function (S, Index) {
|
|
|
+ var Result = false;
|
|
|
+ var L = 0;
|
|
|
+ var R = 0;
|
|
|
+ var I = 0;
|
|
|
+ var CompareRes = 0;
|
|
|
+ Result = false;
|
|
|
+ Index.set(-1);
|
|
|
+ if (!this.GetSorted()) throw $mod.EListError.$create("Create$1",[rtl.getResStr(pas.RTLConsts,"SErrFindNeedsSortedList")]);
|
|
|
+ L = 0;
|
|
|
+ R = this.GetCount() - 1;
|
|
|
+ while (L <= R) {
|
|
|
+ I = L + rtl.trunc((R - L) / 2);
|
|
|
+ CompareRes = this.DoCompareText(S,this.FList[I].FString);
|
|
|
+ if (CompareRes > 0) {
|
|
|
+ L = I + 1}
|
|
|
+ else {
|
|
|
+ R = I - 1;
|
|
|
+ if (CompareRes === 0) {
|
|
|
+ Result = true;
|
|
|
+ if (this.FDuplicates !== 1) L = I;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ };
|
|
|
+ Index.set(L);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Insert = function (Index, S) {
|
|
|
+ if (this.FSortStyle === 2) {
|
|
|
+ this.Error(rtl.getResStr(pas.RTLConsts,"SSortedListError"),0)}
|
|
|
+ else {
|
|
|
+ if ((Index < 0) || (Index > this.FCount)) this.Error(rtl.getResStr(pas.RTLConsts,"SListIndexError"),Index);
|
|
|
+ this.InsertItem(Index,S);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ });
|
|
|
+ this.TOperation = {"0": "opInsert", opInsert: 0, "1": "opRemove", opRemove: 1};
|
|
|
+ this.TComponentStateItem = {"0": "csLoading", csLoading: 0, "1": "csReading", csReading: 1, "2": "csWriting", csWriting: 2, "3": "csDestroying", csDestroying: 3, "4": "csDesigning", csDesigning: 4, "5": "csAncestor", csAncestor: 5, "6": "csUpdating", csUpdating: 6, "7": "csFixups", csFixups: 7, "8": "csFreeNotification", csFreeNotification: 8, "9": "csInline", csInline: 9, "10": "csDesignInstance", csDesignInstance: 10};
|
|
|
+ this.TComponentStyleItem = {"0": "csInheritable", csInheritable: 0, "1": "csCheckPropAvail", csCheckPropAvail: 1, "2": "csSubComponent", csSubComponent: 2, "3": "csTransient", csTransient: 3};
|
|
|
+ rtl.createClass(this,"TComponent",this.TPersistent,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ $mod.TPersistent.$init.call(this);
|
|
|
+ this.FOwner = null;
|
|
|
+ this.FName = "";
|
|
|
+ this.FTag = 0;
|
|
|
+ this.FComponents = null;
|
|
|
+ this.FFreeNotifies = null;
|
|
|
+ this.FComponentState = {};
|
|
|
+ this.FComponentStyle = {};
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.FOwner = undefined;
|
|
|
+ this.FComponents = undefined;
|
|
|
+ this.FFreeNotifies = undefined;
|
|
|
+ this.FComponentState = undefined;
|
|
|
+ this.FComponentStyle = undefined;
|
|
|
+ $mod.TPersistent.$final.call(this);
|
|
|
+ };
|
|
|
+ this.Insert = function (AComponent) {
|
|
|
+ if (!(this.FComponents != null)) this.FComponents = $mod.TFPList.$create("Create");
|
|
|
+ this.FComponents.Add(AComponent);
|
|
|
+ AComponent.FOwner = this;
|
|
|
+ };
|
|
|
+ this.Remove = function (AComponent) {
|
|
|
+ AComponent.FOwner = null;
|
|
|
+ if (this.FComponents != null) {
|
|
|
+ this.FComponents.Remove(AComponent);
|
|
|
+ if (this.FComponents.FCount === 0) {
|
|
|
+ this.FComponents.$destroy("Destroy");
|
|
|
+ this.FComponents = null;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.RemoveNotification = function (AComponent) {
|
|
|
+ if (this.FFreeNotifies !== null) {
|
|
|
+ this.FFreeNotifies.Remove(AComponent);
|
|
|
+ if (this.FFreeNotifies.FCount === 0) {
|
|
|
+ this.FFreeNotifies.$destroy("Destroy");
|
|
|
+ this.FFreeNotifies = null;
|
|
|
+ this.FComponentState = rtl.excludeSet(this.FComponentState,8);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.SetReference = function (Enable) {
|
|
|
+ var aField = null;
|
|
|
+ var aValue = null;
|
|
|
+ var aOwner = null;
|
|
|
+ if (this.FName === "") return;
|
|
|
+ if (this.FOwner != null) {
|
|
|
+ aOwner = this.FOwner;
|
|
|
+ aField = this.FOwner.$class.FieldAddress(this.FName);
|
|
|
+ if (aField != null) {
|
|
|
+ if (Enable) {
|
|
|
+ aValue = this}
|
|
|
+ else aValue = null;
|
|
|
+ aOwner["" + aField["name"]] = aValue;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.ChangeName = function (NewName) {
|
|
|
+ this.FName = NewName;
|
|
|
+ };
|
|
|
+ this.Notification = function (AComponent, Operation) {
|
|
|
+ var C = 0;
|
|
|
+ if (Operation === 1) this.RemoveFreeNotification(AComponent);
|
|
|
+ if (!(this.FComponents != null)) return;
|
|
|
+ C = this.FComponents.FCount - 1;
|
|
|
+ while (C >= 0) {
|
|
|
+ rtl.getObject(this.FComponents.Get(C)).Notification(AComponent,Operation);
|
|
|
+ C -= 1;
|
|
|
+ if (C >= this.FComponents.FCount) C = this.FComponents.FCount - 1;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.SetDesigning = function (Value, SetChildren) {
|
|
|
+ var Runner = 0;
|
|
|
+ if (Value) {
|
|
|
+ this.FComponentState = rtl.includeSet(this.FComponentState,4)}
|
|
|
+ else this.FComponentState = rtl.excludeSet(this.FComponentState,4);
|
|
|
+ if ((this.FComponents != null) && SetChildren) for (var $l = 0, $end = this.FComponents.FCount - 1; $l <= $end; $l++) {
|
|
|
+ Runner = $l;
|
|
|
+ rtl.getObject(this.FComponents.Get(Runner)).SetDesigning(Value,true);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.SetName = function (NewName) {
|
|
|
+ if (this.FName === NewName) return;
|
|
|
+ if ((NewName !== "") && !pas.SysUtils.IsValidIdent(NewName,false,false)) throw $mod.EComponentError.$create("CreateFmt",[rtl.getResStr(pas.RTLConsts,"SInvalidName"),pas.System.VarRecs(18,NewName)]);
|
|
|
+ if (this.FOwner != null) {
|
|
|
+ this.FOwner.ValidateRename(this,this.FName,NewName)}
|
|
|
+ else this.ValidateRename(null,this.FName,NewName);
|
|
|
+ this.SetReference(false);
|
|
|
+ this.ChangeName(NewName);
|
|
|
+ this.SetReference(true);
|
|
|
+ };
|
|
|
+ this.ValidateRename = function (AComponent, CurName, NewName) {
|
|
|
+ if ((AComponent !== null) && (pas.SysUtils.CompareText(CurName,NewName) !== 0) && (AComponent.FOwner === this) && (this.FindComponent(NewName) !== null)) throw $mod.EComponentError.$create("CreateFmt",[rtl.getResStr(pas.RTLConsts,"SDuplicateName"),pas.System.VarRecs(18,NewName)]);
|
|
|
+ if ((4 in this.FComponentState) && (this.FOwner !== null)) this.FOwner.ValidateRename(AComponent,CurName,NewName);
|
|
|
+ };
|
|
|
+ this.ValidateContainer = function (AComponent) {
|
|
|
+ AComponent.ValidateInsert(this);
|
|
|
+ };
|
|
|
+ this.ValidateInsert = function (AComponent) {
|
|
|
+ if (AComponent === null) ;
|
|
|
+ };
|
|
|
+ this.Create$1 = function (AOwner) {
|
|
|
+ this.FComponentStyle = rtl.createSet(0);
|
|
|
+ if (AOwner != null) AOwner.InsertComponent(this);
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ this.Destroy = function () {
|
|
|
+ var I = 0;
|
|
|
+ var C = null;
|
|
|
+ this.Destroying();
|
|
|
+ if (this.FFreeNotifies != null) {
|
|
|
+ I = this.FFreeNotifies.FCount - 1;
|
|
|
+ while (I >= 0) {
|
|
|
+ C = rtl.getObject(this.FFreeNotifies.Get(I));
|
|
|
+ this.FFreeNotifies.Delete(I);
|
|
|
+ C.Notification(this,1);
|
|
|
+ if (this.FFreeNotifies === null) {
|
|
|
+ I = 0}
|
|
|
+ else if (I > this.FFreeNotifies.FCount) I = this.FFreeNotifies.FCount;
|
|
|
+ I -= 1;
|
|
|
+ };
|
|
|
+ pas.SysUtils.FreeAndNil({p: this, get: function () {
|
|
|
+ return this.p.FFreeNotifies;
|
|
|
+ }, set: function (v) {
|
|
|
+ this.p.FFreeNotifies = v;
|
|
|
+ }});
|
|
|
+ };
|
|
|
+ this.DestroyComponents();
|
|
|
+ if (this.FOwner !== null) this.FOwner.RemoveComponent(this);
|
|
|
+ pas.System.TObject.Destroy.call(this);
|
|
|
+ };
|
|
|
+ this.BeforeDestruction = function () {
|
|
|
+ if (!(3 in this.FComponentState)) this.Destroying();
|
|
|
+ };
|
|
|
+ this.DestroyComponents = function () {
|
|
|
+ var acomponent = null;
|
|
|
+ while (this.FComponents != null) {
|
|
|
+ acomponent = rtl.getObject(this.FComponents.Last());
|
|
|
+ this.Remove(acomponent);
|
|
|
+ acomponent.$destroy("Destroy");
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.Destroying = function () {
|
|
|
+ var Runner = 0;
|
|
|
+ if (3 in this.FComponentState) return;
|
|
|
+ this.FComponentState = rtl.includeSet(this.FComponentState,3);
|
|
|
+ if (this.FComponents != null) for (var $l = 0, $end = this.FComponents.FCount - 1; $l <= $end; $l++) {
|
|
|
+ Runner = $l;
|
|
|
+ rtl.getObject(this.FComponents.Get(Runner)).Destroying();
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.FindComponent = function (AName) {
|
|
|
+ var Result = null;
|
|
|
+ var I = 0;
|
|
|
+ Result = null;
|
|
|
+ if ((AName === "") || !(this.FComponents != null)) return Result;
|
|
|
+ for (var $l = 0, $end = this.FComponents.FCount - 1; $l <= $end; $l++) {
|
|
|
+ I = $l;
|
|
|
+ if (pas.SysUtils.CompareText(rtl.getObject(this.FComponents.Get(I)).FName,AName) === 0) {
|
|
|
+ Result = rtl.getObject(this.FComponents.Get(I));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.RemoveFreeNotification = function (AComponent) {
|
|
|
+ this.RemoveNotification(AComponent);
|
|
|
+ AComponent.RemoveNotification(this);
|
|
|
+ };
|
|
|
+ this.InsertComponent = function (AComponent) {
|
|
|
+ AComponent.ValidateContainer(this);
|
|
|
+ this.ValidateRename(AComponent,"",AComponent.FName);
|
|
|
+ if (AComponent.FOwner !== null) AComponent.FOwner.RemoveComponent(AComponent);
|
|
|
+ this.Insert(AComponent);
|
|
|
+ if (4 in this.FComponentState) AComponent.SetDesigning(true,true);
|
|
|
+ this.Notification(AComponent,0);
|
|
|
+ };
|
|
|
+ this.RemoveComponent = function (AComponent) {
|
|
|
+ this.Notification(AComponent,1);
|
|
|
+ this.Remove(AComponent);
|
|
|
+ AComponent.SetDesigning(false,true);
|
|
|
+ this.ValidateRename(AComponent,AComponent.FName,"");
|
|
|
+ };
|
|
|
+ var $r = this.$rtti;
|
|
|
+ $r.addProperty("Name",6,rtl.string,"FName","SetName");
|
|
|
+ $r.addProperty("Tag",0,rtl.nativeint,"FTag","FTag",{Default: 0});
|
|
|
+ });
|
|
|
+ $mod.$implcode = function () {
|
|
|
+ $impl.ClassList = null;
|
|
|
+ };
|
|
|
+ $mod.$init = function () {
|
|
|
+ $impl.ClassList = new Object();
|
|
|
+ };
|
|
|
+},[]);
|
|
|
+rtl.module("CustApp",["System","Classes","SysUtils","Types","JS"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ rtl.createClass(this,"TCustomApplication",pas.Classes.TComponent,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.Classes.TComponent.$init.call(this);
|
|
|
+ this.FExceptObjectJS = undefined;
|
|
|
+ this.FTerminated = false;
|
|
|
+ this.FOptionChar = "";
|
|
|
+ this.FCaseSensitiveOptions = false;
|
|
|
+ this.FStopOnException = false;
|
|
|
+ this.FExceptionExitCode = 0;
|
|
|
+ this.FExceptObject = null;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.FExceptObject = undefined;
|
|
|
+ pas.Classes.TComponent.$final.call(this);
|
|
|
+ };
|
|
|
+ this.Create$1 = function (AOwner) {
|
|
|
+ pas.Classes.TComponent.Create$1.call(this,AOwner);
|
|
|
+ this.FOptionChar = "-";
|
|
|
+ this.FCaseSensitiveOptions = true;
|
|
|
+ this.FStopOnException = false;
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ this.HandleException = function (Sender) {
|
|
|
+ var E = null;
|
|
|
+ var Tmp = null;
|
|
|
+ Tmp = null;
|
|
|
+ E = this.FExceptObject;
|
|
|
+ if ((E === null) && pas.System.Assigned(this.FExceptObjectJS)) {
|
|
|
+ if (rtl.isExt(this.FExceptObjectJS,Error,1)) {
|
|
|
+ Tmp = pas.SysUtils.EExternalException.$create("Create$1",[this.FExceptObjectJS.message])}
|
|
|
+ else if (rtl.isExt(this.FExceptObjectJS,Object,1) && this.FExceptObjectJS.hasOwnProperty("message")) {
|
|
|
+ Tmp = pas.SysUtils.EExternalException.$create("Create$1",["" + this.FExceptObjectJS["message"]])}
|
|
|
+ else Tmp = pas.SysUtils.EExternalException.$create("Create$1",[JSON.stringify(this.FExceptObjectJS)]);
|
|
|
+ E = Tmp;
|
|
|
+ };
|
|
|
+ try {
|
|
|
+ this.ShowException(E);
|
|
|
+ if (this.FStopOnException) this.Terminate$1(this.FExceptionExitCode);
|
|
|
+ } finally {
|
|
|
+ Tmp = rtl.freeLoc(Tmp);
|
|
|
+ };
|
|
|
+ if (Sender === null) ;
|
|
|
+ };
|
|
|
+ this.Run = function () {
|
|
|
+ do {
|
|
|
+ this.FExceptObject = null;
|
|
|
+ this.FExceptObjectJS = null;
|
|
|
+ try {
|
|
|
+ this.DoRun();
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ this.FExceptObject = E;
|
|
|
+ this.FExceptObjectJS = E;
|
|
|
+ this.HandleException(this);
|
|
|
+ } else {
|
|
|
+ this.FExceptObject = null;
|
|
|
+ this.FExceptObjectJS = $e;
|
|
|
+ this.HandleException(this);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ break;
|
|
|
+ } while (!this.FTerminated);
|
|
|
+ };
|
|
|
+ this.Terminate$1 = function (AExitCode) {
|
|
|
+ this.FTerminated = true;
|
|
|
+ rtl.exitcode = AExitCode;
|
|
|
+ };
|
|
|
+ });
|
|
|
+});
|
|
|
+rtl.module("weborworker",["System","JS","Types"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+});
|
|
|
+rtl.module("webworker",["System","JS","weborworker"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+});
|
|
|
+rtl.module("webassembly",["System","JS"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ rtl.recNewT(this,"TJSWebAssemblyMemoryDescriptor",function () {
|
|
|
+ this.initial = 0;
|
|
|
+ this.maximum = 0;
|
|
|
+ this.shared = false;
|
|
|
+ this.$eq = function (b) {
|
|
|
+ return (this.initial === b.initial) && (this.maximum === b.maximum) && (this.shared === b.shared);
|
|
|
+ };
|
|
|
+ this.$assign = function (s) {
|
|
|
+ this.initial = s.initial;
|
|
|
+ this.maximum = s.maximum;
|
|
|
+ this.shared = s.shared;
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.recNewT(this,"TJSWebAssemblyTableDescriptor",function () {
|
|
|
+ this.element = "";
|
|
|
+ this.initial = 0;
|
|
|
+ this.maximum = 0;
|
|
|
+ this.$eq = function (b) {
|
|
|
+ return (this.element === b.element) && (this.initial === b.initial) && (this.maximum === b.maximum);
|
|
|
+ };
|
|
|
+ this.$assign = function (s) {
|
|
|
+ this.element = s.element;
|
|
|
+ this.initial = s.initial;
|
|
|
+ this.maximum = s.maximum;
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ });
|
|
|
+});
|
|
|
+rtl.module("wasitypes",["System","JS"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ this.WASI_ESUCCESS = 0;
|
|
|
+ this.WASI_EBADF = 8;
|
|
|
+ this.WASI_EINVAL = 28;
|
|
|
+ this.WASI_ENOMEM = 48;
|
|
|
+ this.WASI_ENOSYS = 52;
|
|
|
+ this.WASI_CLOCK_MONOTONIC = 0;
|
|
|
+ this.WASI_CLOCK_PROCESS_CPUTIME_ID = 1;
|
|
|
+ this.WASI_CLOCK_REALTIME = 2;
|
|
|
+ this.WASI_CLOCK_THREAD_CPUTIME_ID = 3;
|
|
|
+ this.WASI_STDIN_FILENO = 0;
|
|
|
+ this.WASI_STDOUT_FILENO = 1;
|
|
|
+ this.WASI_STDERR_FILENO = 2;
|
|
|
+ this.__WASI_ERRNO_SUCCESS = 0;
|
|
|
+ this.__WASI_ERRNO_2BIG = 1;
|
|
|
+ this.__WASI_WHENCE_SET = 0;
|
|
|
+ this.__WASI_WHENCE_CUR = 1;
|
|
|
+ this.__WASI_WHENCE_END = 2;
|
|
|
+ this.__WASI_FILETYPE_UNKNOWN = 0;
|
|
|
+ this.__WASI_FILETYPE_BLOCK_DEVICE = 1;
|
|
|
+ this.__WASI_FILETYPE_CHARACTER_DEVICE = 2;
|
|
|
+ this.__WASI_FILETYPE_DIRECTORY = 3;
|
|
|
+ this.__WASI_FILETYPE_REGULAR_FILE = 4;
|
|
|
+ this.__WASI_FILETYPE_SOCKET_STREAM = 6;
|
|
|
+ this.__WASI_FILETYPE_SYMBOLIC_LINK = 7;
|
|
|
+ this.__WASI_FSTFLAGS_ATIM = 1;
|
|
|
+ this.__WASI_FSTFLAGS_ATIM_NOW = 2;
|
|
|
+ this.__WASI_FSTFLAGS_MTIM = 4;
|
|
|
+ this.__WASI_FSTFLAGS_MTIM_NOW = 8;
|
|
|
+ rtl.recNewT(this,"__wasi_filestat_t",function () {
|
|
|
+ this.dev = 0;
|
|
|
+ this.ino = 0;
|
|
|
+ this.filetype = 0;
|
|
|
+ this.nlink = 0;
|
|
|
+ this.size = 0;
|
|
|
+ this.atim = 0;
|
|
|
+ this.mtim = 0;
|
|
|
+ this.ctim = 0;
|
|
|
+ this.$eq = function (b) {
|
|
|
+ return (this.dev === b.dev) && (this.ino === b.ino) && (this.filetype === b.filetype) && (this.nlink === b.nlink) && (this.size === b.size) && (this.atim === b.atim) && (this.mtim === b.mtim) && (this.ctim === b.ctim);
|
|
|
+ };
|
|
|
+ this.$assign = function (s) {
|
|
|
+ this.dev = s.dev;
|
|
|
+ this.ino = s.ino;
|
|
|
+ this.filetype = s.filetype;
|
|
|
+ this.nlink = s.nlink;
|
|
|
+ this.size = s.size;
|
|
|
+ this.atim = s.atim;
|
|
|
+ this.mtim = s.mtim;
|
|
|
+ this.ctim = s.ctim;
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ this.TDirentType = {"0": "dtUnknown", dtUnknown: 0, "1": "dtFile", dtFile: 1, "2": "dtDirectory", dtDirectory: 2, "3": "dtSymlink", dtSymlink: 3, "4": "dtSocket", dtSocket: 4, "5": "dtBlockDevice", dtBlockDevice: 5, "6": "dtCharacterDevice", dtCharacterDevice: 6, "7": "dtFIFO", dtFIFO: 7};
|
|
|
+ rtl.recNewT(this,"TWasiFSDirent",function () {
|
|
|
+ this.ino = 0;
|
|
|
+ this.name = "";
|
|
|
+ this.EntryType = 0;
|
|
|
+ this.next = 0;
|
|
|
+ this.$eq = function (b) {
|
|
|
+ return (this.ino === b.ino) && (this.name === b.name) && (this.EntryType === b.EntryType) && (this.next === b.next);
|
|
|
+ };
|
|
|
+ this.$assign = function (s) {
|
|
|
+ this.ino = s.ino;
|
|
|
+ this.name = s.name;
|
|
|
+ this.EntryType = s.EntryType;
|
|
|
+ this.next = s.next;
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ this.TSeekWhence = {"0": "swBeginning", swBeginning: 0, "1": "swCurrent", swCurrent: 1, "2": "swEnd", swEnd: 2};
|
|
|
+ this.TSetTimesFlag = {"0": "stfatime", stfatime: 0, "1": "stfaTimeNow", stfaTimeNow: 1, "2": "stfmTime", stfmTime: 2, "3": "stfmTimeNow", stfmTimeNow: 3};
|
|
|
+ rtl.createInterface(this,"IWASIFS","{7DDF5E3C-4C18-30AC-806F-592E720CBE00}",["MkDirAt","RmDirAt","StatAt","StatFD","UTimesAt","UTimes","LinkAt","SymLinkAt","RenameAt","UnLinkAt","OpenAt","ReadLinkAt","Close","Write","Sync","DataSync","Seek","Read","ReadDir","GetPrestat"],null);
|
|
|
+ this.DirentMap = [0,4,3,7,6,1,2,0];
|
|
|
+});
|
|
|
+rtl.module("wasienv",["System","SysUtils","Classes","JS","webassembly","Types","wasitypes"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ this.SizeInt8 = 1;
|
|
|
+ this.SizeInt32 = 4;
|
|
|
+ this.SizeInt64 = 8;
|
|
|
+ this.SizeUInt8 = 1;
|
|
|
+ this.SizeUInt32 = 4;
|
|
|
+ this.SizeUInt64 = 8;
|
|
|
+ rtl.createClass(this,"EWasiError",pas.SysUtils.Exception,function () {
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"EWasiFSError",pas.SysUtils.Exception,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.SysUtils.Exception.$init.call(this);
|
|
|
+ this.FErrorcode = 0;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"TPas2JSWASIEnvironment",pas.System.TObject,function () {
|
|
|
+ this.UTF8TextDecoder = null;
|
|
|
+ this.UTF8TextEncoder = null;
|
|
|
+ this.$init = function () {
|
|
|
+ pas.System.TObject.$init.call(this);
|
|
|
+ this.FArguments = null;
|
|
|
+ this.FEnvironment = null;
|
|
|
+ this.FExitCode = 0;
|
|
|
+ this.FImportObject = null;
|
|
|
+ this.Finstance = null;
|
|
|
+ this.FIsLittleEndian = false;
|
|
|
+ this.FLogAPI = false;
|
|
|
+ this.FModuleInstanceExports = null;
|
|
|
+ this.FOnGetConsoleInputBuffer = null;
|
|
|
+ this.FOnGetConsoleInputString = null;
|
|
|
+ this.FOnStdErrorWrite = null;
|
|
|
+ this.FOnStdOutputWrite = null;
|
|
|
+ this.FImportExtensions = null;
|
|
|
+ this.FWasiFS = null;
|
|
|
+ this.FWASIImportName = "";
|
|
|
+ this.FMemory = null;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.FArguments = undefined;
|
|
|
+ this.FEnvironment = undefined;
|
|
|
+ this.FImportObject = undefined;
|
|
|
+ this.Finstance = undefined;
|
|
|
+ this.FModuleInstanceExports = undefined;
|
|
|
+ this.FOnGetConsoleInputBuffer = undefined;
|
|
|
+ this.FOnGetConsoleInputString = undefined;
|
|
|
+ this.FOnStdErrorWrite = undefined;
|
|
|
+ this.FOnStdOutputWrite = undefined;
|
|
|
+ this.FImportExtensions = undefined;
|
|
|
+ this.FWasiFS = undefined;
|
|
|
+ this.FMemory = undefined;
|
|
|
+ pas.System.TObject.$final.call(this);
|
|
|
+ };
|
|
|
+ this.DoRead = function (fd, iovs, iovsLen, atPos, nread) {
|
|
|
+ var $Self = this;
|
|
|
+ var Result = 0;
|
|
|
+ var view = null;
|
|
|
+ var avail = 0;
|
|
|
+ var bytesRead = 0;
|
|
|
+ var ReadBuffer = null;
|
|
|
+ var WasiBuffers = [];
|
|
|
+ var TotalBufSize = 0;
|
|
|
+ function readv(element, index, anArray) {
|
|
|
+ var Result = false;
|
|
|
+ var b = 0;
|
|
|
+ b = 0;
|
|
|
+ while ((b < element.byteLength) && (bytesRead < avail)) {
|
|
|
+ element[b] = ReadBuffer[bytesRead];
|
|
|
+ b += 1;
|
|
|
+ bytesRead += 1;
|
|
|
+ };
|
|
|
+ Result = true;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ TotalBufSize = 0;
|
|
|
+ bytesRead = 0;
|
|
|
+ view = this.getModuleMemoryDataView();
|
|
|
+ WasiBuffers = this.getiovs(view,iovs,iovsLen);
|
|
|
+ TotalBufSize = this.GetTotalIOVsLen(rtl.arrayRef(WasiBuffers));
|
|
|
+ if (fd === 0) {
|
|
|
+ ReadBuffer = this.GetConsoleInputBuffer(TotalBufSize);
|
|
|
+ avail = ReadBuffer.byteLength;
|
|
|
+ } else if (this.FWasiFS != null) {
|
|
|
+ try {
|
|
|
+ ReadBuffer = new Uint8Array(new ArrayBuffer(TotalBufSize));
|
|
|
+ Result = this.FWasiFS.Read(fd,ReadBuffer,atPos,{get: function () {
|
|
|
+ return avail;
|
|
|
+ }, set: function (v) {
|
|
|
+ avail = v;
|
|
|
+ }});
|
|
|
+ if (Result !== 0) return Result;
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ }}
|
|
|
+ else {
|
|
|
+ ReadBuffer = this.GetFileBuffer(fd,TotalBufSize);
|
|
|
+ avail = ReadBuffer.byteLength;
|
|
|
+ };
|
|
|
+ if (avail > 0) WasiBuffers.forEach(readv);
|
|
|
+ view.setUint32(nread,bytesRead,this.FIsLittleEndian);
|
|
|
+ Result = 0;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetConsoleInputBuffer = function (aMaxSize) {
|
|
|
+ var Result = null;
|
|
|
+ var S = "";
|
|
|
+ Result = null;
|
|
|
+ if (this.FOnGetConsoleInputBuffer != null) {
|
|
|
+ this.FOnGetConsoleInputBuffer(this,{get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }})}
|
|
|
+ else if (this.FOnGetConsoleInputString != null) {
|
|
|
+ S = "";
|
|
|
+ this.FOnGetConsoleInputString(this,{get: function () {
|
|
|
+ return S;
|
|
|
+ }, set: function (v) {
|
|
|
+ S = v;
|
|
|
+ }});
|
|
|
+ S = pas.System.Copy(S,1,aMaxSize);
|
|
|
+ Result = $impl.toUTF8Array(S);
|
|
|
+ } else Result = new Uint8Array(0);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetFileBuffer = function (FD, aMaxLen) {
|
|
|
+ var Result = null;
|
|
|
+ Result = new Uint8Array(0);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetImportObject = function () {
|
|
|
+ var Result = null;
|
|
|
+ if (!(this.FImportObject != null)) {
|
|
|
+ this.FImportObject = new Object();
|
|
|
+ this.GetImports(this.FImportObject);
|
|
|
+ };
|
|
|
+ Result = this.FImportObject;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.getiovs = function (view, iovs, iovsLen) {
|
|
|
+ var Result = [];
|
|
|
+ var I = 0;
|
|
|
+ var ArrayBuf = null;
|
|
|
+ var Ptr = 0;
|
|
|
+ var Buf = 0;
|
|
|
+ var BufLen = 0;
|
|
|
+ Result = rtl.arraySetLength(Result,null,iovsLen);
|
|
|
+ Ptr = iovs;
|
|
|
+ for (var $l = 0, $end = iovsLen - 1; $l <= $end; $l++) {
|
|
|
+ I = $l;
|
|
|
+ Buf = view.getUint32(Ptr,this.FIsLittleEndian);
|
|
|
+ BufLen = view.getUint32(Ptr + 4,this.FIsLittleEndian);
|
|
|
+ ArrayBuf = new Uint8Array(this.GetMemory().buffer,Buf,BufLen);
|
|
|
+ Result[I] = ArrayBuf;
|
|
|
+ Ptr += 8;
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetTotalIOVsLen = function (iovs) {
|
|
|
+ var $Self = this;
|
|
|
+ var Result = 0;
|
|
|
+ var BufLen = 0;
|
|
|
+ function calclen(element, index, anArray) {
|
|
|
+ var Result = false;
|
|
|
+ BufLen = BufLen + element.byteLength;
|
|
|
+ Result = true;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ iovs.forEach(calclen);
|
|
|
+ Result = BufLen;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetIOVsAsBytes = function (iovs, iovsLen) {
|
|
|
+ var $Self = this;
|
|
|
+ var Result = null;
|
|
|
+ var view = null;
|
|
|
+ var buflen = 0;
|
|
|
+ var Written = 0;
|
|
|
+ var bufferBytes = null;
|
|
|
+ var Buffers = [];
|
|
|
+ var Buf = null;
|
|
|
+ function writev(element, index, anArray) {
|
|
|
+ var Result = false;
|
|
|
+ Buf.set(element,Written);
|
|
|
+ Written += element.byteLength;
|
|
|
+ Result = true;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ view = this.getModuleMemoryDataView();
|
|
|
+ Written = 0;
|
|
|
+ buflen = 0;
|
|
|
+ Buffers = this.getiovs(view,iovs,iovsLen);
|
|
|
+ buflen = this.GetTotalIOVsLen(rtl.arrayRef(Buffers));
|
|
|
+ bufferBytes = new ArrayBuffer(buflen);
|
|
|
+ Buf = new Uint8Array(bufferBytes);
|
|
|
+ Buffers.forEach(writev);
|
|
|
+ Result = Buf;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetMemory = function () {
|
|
|
+ var Result = null;
|
|
|
+ Result = this.FModuleInstanceExports.memory;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SetInstance = function (AValue) {
|
|
|
+ if (this.Finstance === AValue) return;
|
|
|
+ this.Finstance = AValue;
|
|
|
+ this.FModuleInstanceExports = this.Finstance.exports;
|
|
|
+ if (!(this.FMemory != null) && (this.FModuleInstanceExports.memory != null)) this.FMemory = this.FModuleInstanceExports.memory;
|
|
|
+ };
|
|
|
+ this.WriteFileStatToMem = function (BufPtr, Info) {
|
|
|
+ var Loc = 0;
|
|
|
+ Loc = BufPtr;
|
|
|
+ Loc = this.SetMemInfoInt64(Loc,Info.dev);
|
|
|
+ Loc = this.SetMemInfoUInt64(Loc,Info.ino);
|
|
|
+ Loc = this.SetMemInfoUInt64(Loc,Info.filetype);
|
|
|
+ Loc = this.SetMemInfoUInt64(Loc,Info.nlink);
|
|
|
+ Loc = this.SetMemInfoUInt64(Loc,Info.size);
|
|
|
+ Loc = this.SetMemInfoUInt64(Loc,Info.atim * 1000 * 1000);
|
|
|
+ Loc = this.SetMemInfoUInt64(Loc,Info.mtim * 1000 * 1000);
|
|
|
+ Loc = this.SetMemInfoUInt64(Loc,Info.ctim * 1000 * 1000);
|
|
|
+ };
|
|
|
+ this.ErrorToCode = function (E) {
|
|
|
+ var Result = 0;
|
|
|
+ var EW = null;
|
|
|
+ if ($mod.EWasiFSError.isPrototypeOf(E)) {
|
|
|
+ Result = EW.FErrorcode}
|
|
|
+ else Result = 0;
|
|
|
+ if (Result === 0) Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.DoLog$1 = function (Fmt, Args) {
|
|
|
+ pas.System.Writeln(pas.SysUtils.Format(Fmt,Args));
|
|
|
+ };
|
|
|
+ this.setBigUint64 = function (View, byteOffset, value, littleEndian) {
|
|
|
+ var LowWord = 0;
|
|
|
+ var HighWord = 0;
|
|
|
+ LowWord = value;
|
|
|
+ HighWord = Math.floor(value / 4294967296);
|
|
|
+ if (littleEndian) {
|
|
|
+ View.setUint32(byteOffset + 0,LowWord,littleEndian);
|
|
|
+ View.setUint32(byteOffset + 4,HighWord,littleEndian);
|
|
|
+ } else {
|
|
|
+ View.setUint32(byteOffset + 4,LowWord,littleEndian);
|
|
|
+ View.setUint32(byteOffset + 0,HighWord,littleEndian);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.setBigInt64 = function (View, byteOffset, value, littleEndian) {
|
|
|
+ var LowWord = 0;
|
|
|
+ var HighWord = 0;
|
|
|
+ LowWord = value;
|
|
|
+ HighWord = Math.floor(value / 4294967296);
|
|
|
+ if (littleEndian) {
|
|
|
+ View.setInt32(byteOffset + 0,LowWord,littleEndian);
|
|
|
+ View.setInt32(byteOffset + 4,HighWord,littleEndian);
|
|
|
+ } else {
|
|
|
+ View.setInt32(byteOffset + 4,LowWord,littleEndian);
|
|
|
+ View.setInt32(byteOffset + 0,HighWord,littleEndian);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.DoConsoleWrite = function (IsStdErr, aBytes) {
|
|
|
+ var $Self = this;
|
|
|
+ function TryConvert() {
|
|
|
+ var Result = "";
|
|
|
+ Result = "";
|
|
|
+ Result=String.fromCharCode.apply(null, aBytes);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ var S = "";
|
|
|
+ var Evt = null;
|
|
|
+ try {
|
|
|
+ S = this.UTF8TextDecoder.decode(aBytes);
|
|
|
+ } catch ($e) {
|
|
|
+ S = TryConvert();
|
|
|
+ };
|
|
|
+ if (IsStdErr) {
|
|
|
+ Evt = this.FOnStdErrorWrite}
|
|
|
+ else Evt = this.FOnStdOutputWrite;
|
|
|
+ if (Evt != null) Evt($Self,S);
|
|
|
+ };
|
|
|
+ this.GetImports = function (aImports) {
|
|
|
+ aImports["args_get"] = rtl.createCallback(this,"args_get");
|
|
|
+ aImports["args_sizes_get"] = rtl.createCallback(this,"args_sizes_get");
|
|
|
+ aImports["clock_res_get"] = rtl.createCallback(this,"clock_res_get");
|
|
|
+ aImports["clock_time_get"] = rtl.createCallback(this,"clock_time_get");
|
|
|
+ aImports["environ_get"] = rtl.createCallback(this,"environ_get");
|
|
|
+ aImports["environ_sizes_get"] = rtl.createCallback(this,"environ_sizes_get");
|
|
|
+ aImports["fd_advise"] = rtl.createCallback(this,"fd_advise");
|
|
|
+ aImports["fd_allocate"] = rtl.createCallback(this,"fd_allocate");
|
|
|
+ aImports["fd_close"] = rtl.createCallback(this,"fd_close");
|
|
|
+ aImports["fd_datasync"] = rtl.createCallback(this,"fd_datasync");
|
|
|
+ aImports["fd_fdstat_get"] = rtl.createCallback(this,"fd_fdstat_get");
|
|
|
+ aImports["fd_fdstat_set_flags"] = rtl.createCallback(this,"fd_fdstat_set_flags");
|
|
|
+ aImports["fd_fdstat_set_rights"] = rtl.createCallback(this,"fd_fdstat_set_rights");
|
|
|
+ aImports["fd_filestat_get"] = rtl.createCallback(this,"fd_filestat_get");
|
|
|
+ aImports["fd_filestat_set_size"] = rtl.createCallback(this,"fd_filestat_set_size");
|
|
|
+ aImports["fd_filestat_set_times"] = rtl.createCallback(this,"fd_filestat_set_times");
|
|
|
+ aImports["fd_pread"] = rtl.createCallback(this,"fd_pread");
|
|
|
+ aImports["fd_prestat_dir_name"] = rtl.createCallback(this,"fd_prestat_dir_name");
|
|
|
+ aImports["fd_prestat_get"] = rtl.createCallback(this,"fd_prestat_get");
|
|
|
+ aImports["fd_pwrite"] = rtl.createCallback(this,"fd_pwrite");
|
|
|
+ aImports["fd_read"] = rtl.createCallback(this,"fd_read");
|
|
|
+ aImports["fd_readdir"] = rtl.createCallback(this,"fd_readdir");
|
|
|
+ aImports["fd_renumber"] = rtl.createCallback(this,"fd_renumber");
|
|
|
+ aImports["fd_seek"] = rtl.createCallback(this,"fd_seek");
|
|
|
+ aImports["fd_sync"] = rtl.createCallback(this,"fd_sync");
|
|
|
+ aImports["fd_tell"] = rtl.createCallback(this,"fd_tell");
|
|
|
+ aImports["fd_write"] = rtl.createCallback(this,"fd_write");
|
|
|
+ aImports["path_create_directory"] = rtl.createCallback(this,"path_create_directory");
|
|
|
+ aImports["path_filestat_get"] = rtl.createCallback(this,"path_filestat_get");
|
|
|
+ aImports["path_filestat_set_times"] = rtl.createCallback(this,"path_filestat_set_times");
|
|
|
+ aImports["path_link"] = rtl.createCallback(this,"path_link");
|
|
|
+ aImports["path_open"] = rtl.createCallback(this,"path_open");
|
|
|
+ aImports["path_readlink"] = rtl.createCallback(this,"path_readlink");
|
|
|
+ aImports["path_remove_directory"] = rtl.createCallback(this,"path_remove_directory");
|
|
|
+ aImports["path_rename"] = rtl.createCallback(this,"path_rename");
|
|
|
+ aImports["path_symlink"] = rtl.createCallback(this,"path_symlink");
|
|
|
+ aImports["path_unlink_file"] = rtl.createCallback(this,"path_unlink_file");
|
|
|
+ aImports["poll_oneoff"] = rtl.createCallback(this,"poll_oneoff");
|
|
|
+ aImports["proc_exit"] = rtl.createCallback(this,"proc_exit");
|
|
|
+ aImports["proc_raise"] = rtl.createCallback(this,"proc_raise");
|
|
|
+ aImports["random_get"] = rtl.createCallback(this,"random_get");
|
|
|
+ aImports["sched_yield"] = rtl.createCallback(this,"sched_yield");
|
|
|
+ aImports["sock_recv"] = rtl.createCallback(this,"sock_recv");
|
|
|
+ aImports["sock_send"] = rtl.createCallback(this,"sock_send");
|
|
|
+ aImports["sock_shutdown"] = rtl.createCallback(this,"sock_shutdown");
|
|
|
+ };
|
|
|
+ this.GetTime = function (aClockID) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.GetTime(%d)",pas.System.VarRecs(19,aClockID));
|
|
|
+ Result = -1;
|
|
|
+ var $tmp = aClockID;
|
|
|
+ if ($tmp === 0) {
|
|
|
+ Result = Date.now()}
|
|
|
+ else if ($tmp === 2) {
|
|
|
+ Result = Date.now()}
|
|
|
+ else if (($tmp === 1) || ($tmp === 3)) Result = Date.now();
|
|
|
+ Result = Result * 1000000;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.getModuleMemoryDataView = function () {
|
|
|
+ var Result = null;
|
|
|
+ Result = new DataView(this.GetMemory().buffer);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.AddExtension = function (aExtension) {
|
|
|
+ if (!(this.FImportExtensions != null)) this.FImportExtensions = pas.Classes.TFPList.$create("Create");
|
|
|
+ this.FImportExtensions.Add(aExtension);
|
|
|
+ };
|
|
|
+ this.RemoveExtension = function (aExtension) {
|
|
|
+ if (this.FImportExtensions != null) this.FImportExtensions.Remove(aExtension);
|
|
|
+ };
|
|
|
+ this.args_get = function (argv, argvBuf) {
|
|
|
+ var Result = 0;
|
|
|
+ var Ptr = 0;
|
|
|
+ var PtrV = 0;
|
|
|
+ var S = "";
|
|
|
+ var i = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.args_get([%x],[%x])",pas.System.VarRecs(0,argv,0,argvBuf));
|
|
|
+ Ptr = argvBuf;
|
|
|
+ PtrV = argv;
|
|
|
+ for (var $l = 0, $end = this.FArguments.GetCount() - 1; $l <= $end; $l++) {
|
|
|
+ i = $l;
|
|
|
+ S = this.FArguments.Get(i);
|
|
|
+ PtrV = this.SetMemInfoUInt32(PtrV,Ptr);
|
|
|
+ Ptr = Ptr + this.SetUTF8StringInMem(Ptr,S.length,S);
|
|
|
+ Ptr = this.SetMemInfoUInt8(Ptr,0);
|
|
|
+ };
|
|
|
+ Result = 0;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.args_sizes_get = function (argc, argvBufSize) {
|
|
|
+ var Result = 0;
|
|
|
+ var View = null;
|
|
|
+ var Size = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.args_sizes_get([%x],[%x])",pas.System.VarRecs(0,argc,0,argvBufSize));
|
|
|
+ View = this.getModuleMemoryDataView();
|
|
|
+ View.setUint32(argc,this.FArguments.GetCount(),this.FIsLittleEndian);
|
|
|
+ Size = 0;
|
|
|
+ if (this.FArguments.GetCount() > 0) Size = this.FArguments.GetTextStr().length + 1;
|
|
|
+ View.setUint32(argvBufSize,Size,this.FIsLittleEndian);
|
|
|
+ Result = 0;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.clock_res_get = function (clockId, resolution) {
|
|
|
+ var Result = 0;
|
|
|
+ var view = null;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.clock_res_get(%d,%d)",pas.System.VarRecs(19,clockId,19,resolution));
|
|
|
+ view = this.getModuleMemoryDataView();
|
|
|
+ this.$class.setBigUint64(view,resolution,0,this.FIsLittleEndian);
|
|
|
+ Result = 0;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.clock_time_get = function (clockId, precision, time) {
|
|
|
+ var Result = 0;
|
|
|
+ var view = null;
|
|
|
+ var n = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.clock_time_get(%d,%d,[%x])",pas.System.VarRecs(19,clockId,19,precision,0,time));
|
|
|
+ view = this.getModuleMemoryDataView();
|
|
|
+ n = this.GetTime(clockId);
|
|
|
+ if (n === -1) {
|
|
|
+ Result = 28}
|
|
|
+ else {
|
|
|
+ this.$class.setBigUint64(view,time,n,this.FIsLittleEndian);
|
|
|
+ Result = 0;
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.environ_get = function (environ, environBuf) {
|
|
|
+ var Result = 0;
|
|
|
+ var S = "";
|
|
|
+ var I = 0;
|
|
|
+ var PtrV = 0;
|
|
|
+ var Ptr = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.environ_get([%x],[%x])",pas.System.VarRecs(0,environ,0,environBuf));
|
|
|
+ Ptr = environBuf;
|
|
|
+ PtrV = environ;
|
|
|
+ for (var $l = 0, $end = this.FEnvironment.GetCount() - 1; $l <= $end; $l++) {
|
|
|
+ I = $l;
|
|
|
+ S = this.FEnvironment.Get(I);
|
|
|
+ PtrV = this.SetMemInfoUInt32(PtrV,Ptr);
|
|
|
+ Ptr = Ptr + this.SetUTF8StringInMem(Ptr,S.length,S);
|
|
|
+ Ptr = this.SetMemInfoUInt8(Ptr,0);
|
|
|
+ };
|
|
|
+ Result = 0;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.environ_sizes_get = function (environCount, environBufSize) {
|
|
|
+ var Result = 0;
|
|
|
+ var View = null;
|
|
|
+ var Size = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.environ_sizes_get([%x],[%x])",pas.System.VarRecs(0,environCount,0,environBufSize));
|
|
|
+ View = this.getModuleMemoryDataView();
|
|
|
+ View.setUint32(environCount,this.FEnvironment.GetCount(),this.FIsLittleEndian);
|
|
|
+ Size = 0;
|
|
|
+ if (this.FEnvironment.GetCount() > 0) Size = this.FEnvironment.GetTextStr().length + 1;
|
|
|
+ View.setUint32(environBufSize,Size,this.FIsLittleEndian);
|
|
|
+ Result = 0;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_advise = function (fd, offset, len, advice) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_advise(%d,%d,%d,%d)",pas.System.VarRecs(19,fd,19,offset,19,len,19,advice));
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.fd_advise");
|
|
|
+ Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_allocate = function (fd, offset, len) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_allocate(%d,%d,%d)",pas.System.VarRecs(19,fd,19,offset,19,len));
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.fd_allocate");
|
|
|
+ Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_close = function (fd) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_close(%d)",pas.System.VarRecs(19,fd));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.Close(fd);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_datasync = function (fd) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_datasync(%d)",pas.System.VarRecs(19,fd));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.DataSync(fd);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_fdstat_get = function (fd, bufPtr) {
|
|
|
+ var Result = 0;
|
|
|
+ var View = null;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_fdstat_get(%d,%d)",pas.System.VarRecs(19,fd,0,bufPtr));
|
|
|
+ View = this.getModuleMemoryDataView();
|
|
|
+ View.setUint8(bufPtr,fd);
|
|
|
+ View.setUint16(bufPtr + 2,0,this.FIsLittleEndian);
|
|
|
+ View.setUint16(bufPtr + 4,0,this.FIsLittleEndian);
|
|
|
+ this.$class.setBigUint64(View,bufPtr + 8,0,this.FIsLittleEndian);
|
|
|
+ this.$class.setBigUint64(View,bufPtr + 8 + 8,0,this.FIsLittleEndian);
|
|
|
+ Result = 0;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_fdstat_set_flags = function (fd, flags) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_fdstat_set_flags(%d,%d)",pas.System.VarRecs(19,fd,19,flags));
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.fd_fdstat_set_flags");
|
|
|
+ Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_fdstat_set_rights = function (fd, fsRightsBase, fsRightsInheriting) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_fdstat_set_rights(%d,%d,%d)",pas.System.VarRecs(19,fd,19,fsRightsBase,19,fsRightsInheriting));
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.fd_fdstat_set_rights");
|
|
|
+ Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_filestat_get = function (fd, bufPtr) {
|
|
|
+ var Result = 0;
|
|
|
+ var Info = pas.wasitypes.__wasi_filestat_t.$new();
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_filestat_get(%d,[%x])",pas.System.VarRecs(19,fd,0,bufPtr));
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.fd_filestat_get");
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.StatFD(fd,Info);
|
|
|
+ if (Result === 0) this.WriteFileStatToMem(bufPtr,pas.wasitypes.__wasi_filestat_t.$clone(Info));
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_filestat_set_size = function (fd, stSize) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_filestat_set_size(%d,%d)",pas.System.VarRecs(19,fd,19,stSize));
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.fd_filestat_set_size");
|
|
|
+ Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_filestat_set_times = function (fd, stAtim, stMtim, fstflags) {
|
|
|
+ var $Self = this;
|
|
|
+ var Result = 0;
|
|
|
+ var Flags = {};
|
|
|
+ function MaybeFlag(src, Flag) {
|
|
|
+ if ((fstflags & src) === src) Flags = rtl.includeSet(Flags,Flag);
|
|
|
+ };
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_filestat_set_times(%d,%d,%d)",pas.System.VarRecs(19,fd,19,stAtim,19,stMtim,19,fstflags));
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.fd_filestat_set_times");
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ MaybeFlag(1,0);
|
|
|
+ MaybeFlag(2,1);
|
|
|
+ MaybeFlag(4,2);
|
|
|
+ MaybeFlag(8,3);
|
|
|
+ Result = this.FWasiFS.UTimes(fd,new Date(stAtim),new Date(stMtim),rtl.refSet(Flags));
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_pread = function (fd, iovs, iovsLen, offset, nread) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_pread(%d,[%x],%d,%d,[%x])",pas.System.VarRecs(19,fd,0,iovs,19,iovsLen,19,offset,0,nread));
|
|
|
+ Result = this.DoRead(fd,iovs,iovsLen,offset,nread);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_prestat_dir_name = function (fd, pathPtr, pathLen) {
|
|
|
+ var Result = 0;
|
|
|
+ var S = "";
|
|
|
+ var Len = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_prestat_dir_name(%d,[%d],%d)",pas.System.VarRecs(19,fd,0,pathPtr,19,pathLen));
|
|
|
+ if (this.FWasiFS != null) {
|
|
|
+ S = this.FWasiFS.GetPrestat(fd);
|
|
|
+ if (S !== "") {
|
|
|
+ Len = S.length;
|
|
|
+ if (Len > pathLen) Len = pathLen;
|
|
|
+ this.SetUTF8StringInMem(pathPtr,Len,S);
|
|
|
+ Result = 0;
|
|
|
+ } else Result = 8;
|
|
|
+ } else {
|
|
|
+ if (fd === 3) {
|
|
|
+ this.SetUTF8StringInMem(pathPtr,1,"/");
|
|
|
+ Result = 0;
|
|
|
+ } else Result = 8;
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_prestat_get = function (fd, bufPtr) {
|
|
|
+ var Result = 0;
|
|
|
+ var S = "";
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_prestat_get(%d,[%d])",pas.System.VarRecs(19,fd,0,bufPtr));
|
|
|
+ if (this.FWasiFS != null) {
|
|
|
+ S = this.FWasiFS.GetPrestat(fd);
|
|
|
+ if (S !== "") {
|
|
|
+ this.SetMemInfoInt32(bufPtr,0);
|
|
|
+ this.SetMemInfoInt32(bufPtr + 4,S.length);
|
|
|
+ Result = 0;
|
|
|
+ } else Result = 8;
|
|
|
+ } else {
|
|
|
+ if (fd === 3) {
|
|
|
+ this.SetMemInfoInt32(bufPtr,0);
|
|
|
+ this.SetMemInfoInt32(bufPtr + 4,1);
|
|
|
+ Result = 0;
|
|
|
+ };
|
|
|
+ Result = 8;
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_pwrite = function (fd, iovs, iovsLen, offset, nwritten) {
|
|
|
+ var Result = 0;
|
|
|
+ var view = null;
|
|
|
+ var Buf = null;
|
|
|
+ var written = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_prite(%d,[%d],%d,%d,[%d])",pas.System.VarRecs(19,fd,19,iovs,19,iovsLen,19,offset,19,nwritten));
|
|
|
+ if ((fd === 1) || (fd === 2)) {
|
|
|
+ Buf = this.GetIOVsAsBytes(iovs,iovsLen);
|
|
|
+ written = Buf.byteLength;
|
|
|
+ this.DoConsoleWrite(fd === 2,Buf);
|
|
|
+ view.setUint32(nwritten,written,this.FIsLittleEndian);
|
|
|
+ Result = 0;
|
|
|
+ } else if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else {
|
|
|
+ Buf = this.GetIOVsAsBytes(iovs,iovsLen);
|
|
|
+ Result = this.FWasiFS.Write(fd,Buf,-1,{get: function () {
|
|
|
+ return written;
|
|
|
+ }, set: function (v) {
|
|
|
+ written = v;
|
|
|
+ }});
|
|
|
+ if (Result === 0) view.setUint32(nwritten,written,this.FIsLittleEndian);
|
|
|
+ };
|
|
|
+ Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_read = function (fd, iovs, iovsLen, nread) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_read(%d,[%x],%d,[%x])",pas.System.VarRecs(19,fd,0,iovs,19,iovsLen,0,nread));
|
|
|
+ Result = this.DoRead(fd,iovs,iovsLen,-1,nread);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_readdir = function (fd, bufPtr, bufLen, cookie, bufusedPtr) {
|
|
|
+ var Result = 0;
|
|
|
+ var Dirent = pas.wasitypes.TWasiFSDirent.$new();
|
|
|
+ var NameArray = null;
|
|
|
+ var NameLen = 0;
|
|
|
+ var Ptr = 0;
|
|
|
+ var Res = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_readdir(%d,[%x],%d,%d,[%x])",pas.System.VarRecs(19,fd,0,bufPtr,19,bufLen,19,cookie,0,bufusedPtr));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Res = this.FWasiFS.ReadDir(fd,pas.JS.AsIntNumber(cookie),Dirent);
|
|
|
+ Result = 0;
|
|
|
+ Ptr = bufPtr;
|
|
|
+ while (((Ptr - bufPtr) < bufLen) && (Res === 0)) {
|
|
|
+ NameArray = this.UTF8TextEncoder.encode(Dirent.name);
|
|
|
+ NameLen = NameArray.byteLength;
|
|
|
+ Ptr = this.SetMemInfoUInt64(Ptr,Dirent.next);
|
|
|
+ Ptr = this.SetMemInfoUInt64(Ptr,Dirent.ino);
|
|
|
+ Ptr = this.SetMemInfoInt32(Ptr,NameLen);
|
|
|
+ Ptr = this.SetMemInfoInt32(Ptr,pas.wasitypes.DirentMap[Dirent.EntryType]);
|
|
|
+ if (this.SetUTF8StringInMem(Ptr,bufLen - 18,Dirent.name) !== -1) {
|
|
|
+ Ptr = Ptr + NameLen;
|
|
|
+ cookie = Dirent.next;
|
|
|
+ Res = this.FWasiFS.ReadDir(fd,pas.JS.AsIntNumber(cookie),Dirent);
|
|
|
+ } else Res = 48;
|
|
|
+ };
|
|
|
+ this.SetMemInfoInt32(bufusedPtr,Ptr - bufPtr);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_renumber = function (afrom, ato) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_renumber(%d,%d)",pas.System.VarRecs(19,afrom,19,ato));
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.fd_renumber");
|
|
|
+ Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_seek = function (fd, offset, whence, newOffsetPtr) {
|
|
|
+ var Result = 0;
|
|
|
+ var lWhence = 0;
|
|
|
+ var NewPos = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_seek(%d,%d,%d,[%x])",pas.System.VarRecs(19,fd,19,offset,19,whence,0,newOffsetPtr));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ lWhence = 0;
|
|
|
+ var $tmp = whence;
|
|
|
+ if ($tmp === 1) {
|
|
|
+ lWhence = 1}
|
|
|
+ else if ($tmp === 2) {
|
|
|
+ lWhence = 2}
|
|
|
+ else if ($tmp === 0) {
|
|
|
+ lWhence = 0}
|
|
|
+ else {
|
|
|
+ Result = 28;
|
|
|
+ };
|
|
|
+ Result = this.FWasiFS.Seek(fd,offset,lWhence,{get: function () {
|
|
|
+ return NewPos;
|
|
|
+ }, set: function (v) {
|
|
|
+ NewPos = v;
|
|
|
+ }});
|
|
|
+ if (Result === 0) this.SetMemInfoInt64(newOffsetPtr,NewPos);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_sync = function (fd) {
|
|
|
+ var Result = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_sync(%d)",pas.System.VarRecs(19,fd));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.Sync(fd);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_tell = function (fd, offsetPtr) {
|
|
|
+ var Result = 0;
|
|
|
+ var NewPos = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_tell(%d,[%x])",pas.System.VarRecs(19,fd,0,offsetPtr));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.Seek(fd,0,1,{get: function () {
|
|
|
+ return NewPos;
|
|
|
+ }, set: function (v) {
|
|
|
+ NewPos = v;
|
|
|
+ }});
|
|
|
+ if (Result === 0) this.SetMemInfoInt32(offsetPtr,NewPos);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.fd_write = function (fd, iovs, iovsLen, nwritten) {
|
|
|
+ var Result = 0;
|
|
|
+ var view = null;
|
|
|
+ var Buf = null;
|
|
|
+ var written = 0;
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.fd_write(%d,[%d],%d,[%d])",pas.System.VarRecs(19,fd,19,iovs,19,iovsLen,19,nwritten));
|
|
|
+ view = this.getModuleMemoryDataView();
|
|
|
+ if ((fd === 1) || (fd === 2)) {
|
|
|
+ Buf = this.GetIOVsAsBytes(iovs,iovsLen);
|
|
|
+ written = Buf.byteLength;
|
|
|
+ this.DoConsoleWrite(fd === 2,Buf);
|
|
|
+ view.setUint32(nwritten,written,this.FIsLittleEndian);
|
|
|
+ Result = 0;
|
|
|
+ } else if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else {
|
|
|
+ Buf = this.GetIOVsAsBytes(iovs,iovsLen);
|
|
|
+ Result = this.FWasiFS.Write(fd,Buf,-1,{get: function () {
|
|
|
+ return written;
|
|
|
+ }, set: function (v) {
|
|
|
+ written = v;
|
|
|
+ }});
|
|
|
+ if (Result === 0) view.setUint32(nwritten,written,this.FIsLittleEndian);
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.path_create_directory = function (fd, pathPtr, pathLen) {
|
|
|
+ var Result = 0;
|
|
|
+ var S = "";
|
|
|
+ S = this.GetUTF8StringFromMem(pathPtr,pathLen);
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.path_create_directory(%d,'%s')",pas.System.VarRecs(19,fd,18,S));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.MkDirAt(fd,S);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.path_filestat_get = function (fd, flags, pathPtr, pathLen, bufPtr) {
|
|
|
+ var Result = 0;
|
|
|
+ var aPath = "";
|
|
|
+ var Info = pas.wasitypes.__wasi_filestat_t.$new();
|
|
|
+ aPath = this.GetUTF8StringFromMem(pathPtr,pathLen);
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.path_filestat_get(%d,%d,'%s',[%x])",pas.System.VarRecs(19,fd,19,flags,18,aPath,0,bufPtr));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.StatAt(fd,aPath,Info);
|
|
|
+ if (Result === 0) this.WriteFileStatToMem(bufPtr,pas.wasitypes.__wasi_filestat_t.$clone(Info));
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.path_filestat_set_times = function (fd, fstflags, pathPtr, pathLen, stAtim, stMtim) {
|
|
|
+ var Result = 0;
|
|
|
+ var aPath = "";
|
|
|
+ aPath = this.GetUTF8StringFromMem(pathPtr,pathLen);
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.path_filestat_set_times(%d,%d,'%s',%d,%d)",pas.System.VarRecs(19,fd,19,fstflags,18,aPath,19,stAtim,19,stMtim));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.UTimesAt(fd,aPath,new Date(stAtim),new Date(stMtim),false);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.path_link = function (oldFd, oldFlags, oldPath, oldPathLen, newFd, NewPath, newPathLen) {
|
|
|
+ var Result = 0;
|
|
|
+ var lOld = "";
|
|
|
+ var lNew = "";
|
|
|
+ lOld = this.GetUTF8StringFromMem(oldPath,oldPathLen);
|
|
|
+ lNew = this.GetUTF8StringFromMem(NewPath,newPathLen);
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.path_link(%d,%d,'%s',%d,'%s')",pas.System.VarRecs(19,oldFd,19,oldFlags,18,lOld,19,newFd,18,lNew));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.LinkAt(oldFd,lOld,newFd,lNew);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.path_open = function (dirfd, dirflags, pathPtr, pathLen, oflags, fsRightsBase, fsRightsInheriting, fsFlags, fd) {
|
|
|
+ var Result = 0;
|
|
|
+ var lPath = "";
|
|
|
+ var lFD = 0;
|
|
|
+ lPath = this.GetUTF8StringFromMem(pathPtr,pathLen);
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.path_open(%d,%d,'%s',%d,%d,%d,%d,[%x])",pas.System.VarRecs(19,dirfd,19,dirflags,18,lPath,19,oflags,19,fsRightsBase,19,fsRightsInheriting,19,fsFlags,0,fd));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.OpenAt(dirfd,dirflags,lPath,oflags,fsRightsBase,fsRightsInheriting,fsFlags,{get: function () {
|
|
|
+ return lFD;
|
|
|
+ }, set: function (v) {
|
|
|
+ lFD = v;
|
|
|
+ }});
|
|
|
+ if (Result === 0) this.SetMemInfoInt32(fd,lFD);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.path_readlink = function (fd, pathPtr, pathLen, buf, bufLen, bufused) {
|
|
|
+ var Result = 0;
|
|
|
+ var lTarget = "";
|
|
|
+ var lPath = "";
|
|
|
+ var Written = 0;
|
|
|
+ lPath = this.GetUTF8StringFromMem(pathPtr,pathLen);
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.path_readlink(%d,'%s',[%x],%d,%d,[%x])",pas.System.VarRecs(19,fd,18,lPath,0,buf,19,bufLen,0,bufused));
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.path_readlink");
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.ReadLinkAt(fd,lPath,{get: function () {
|
|
|
+ return lTarget;
|
|
|
+ }, set: function (v) {
|
|
|
+ lTarget = v;
|
|
|
+ }});
|
|
|
+ if (Result === 0) {
|
|
|
+ Written = this.SetUTF8StringInMem(buf,bufLen,lTarget);
|
|
|
+ if (Written === -1) {
|
|
|
+ Result = 1}
|
|
|
+ else this.SetMemInfoInt32(bufused,Written);
|
|
|
+ };
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.path_remove_directory = function (fd, pathPtr, pathLen) {
|
|
|
+ var Result = 0;
|
|
|
+ var lPath = "";
|
|
|
+ lPath = this.GetUTF8StringFromMem(pathPtr,pathLen);
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.path_remove_directory(%d,'%s')",pas.System.VarRecs(19,fd,18,lPath));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.RmDirAt(fd,lPath);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.path_rename = function (oldFd, oldPath, oldPathLen, newFd, newPath, newPathLen) {
|
|
|
+ var Result = 0;
|
|
|
+ var lOld = "";
|
|
|
+ var lNew = "";
|
|
|
+ lOld = this.GetUTF8StringFromMem(oldPath,oldPathLen);
|
|
|
+ lNew = this.GetUTF8StringFromMem(newPath,newPathLen);
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.path_rename(%d,'%s',%d,'%s')",pas.System.VarRecs(19,oldFd,18,lOld,19,newFd,18,lNew));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.RenameAt(oldFd,lOld,newFd,lNew);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.path_symlink = function (oldPath, oldPathLen, fd, newPath, newPathLen) {
|
|
|
+ var Result = 0;
|
|
|
+ var lOld = "";
|
|
|
+ var lNew = "";
|
|
|
+ lOld = this.GetUTF8StringFromMem(oldPath,oldPathLen);
|
|
|
+ lNew = this.GetUTF8StringFromMem(newPath,newPathLen);
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.path_symlink('%s',%d,'%s')",pas.System.VarRecs(18,lOld,19,fd,18,lNew));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.SymLinkAt(fd,lOld,lNew);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.path_unlink_file = function (fd, pathPtr, pathLen) {
|
|
|
+ var Result = 0;
|
|
|
+ var lPath = "";
|
|
|
+ lPath = this.GetUTF8StringFromMem(pathPtr,pathLen);
|
|
|
+ if (this.FLogAPI) this.DoLog$1("TPas2JSWASIEnvironment.path_unlink_file(%d,'%s')",pas.System.VarRecs(19,fd,18,lPath));
|
|
|
+ if (!(this.FWasiFS != null)) {
|
|
|
+ Result = 52}
|
|
|
+ else try {
|
|
|
+ Result = this.FWasiFS.UnLinkAt(fd,lPath);
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ Result = this.$class.ErrorToCode(E);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.poll_oneoff = function (sin, sout, nsubscriptions, nevents) {
|
|
|
+ var Result = 0;
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.poll_oneoff");
|
|
|
+ Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.proc_exit = function (rval) {
|
|
|
+ var Result = 0;
|
|
|
+ this.FExitCode = rval;
|
|
|
+ Result = 0;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.proc_raise = function (sig) {
|
|
|
+ var Result = 0;
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.proc_raise");
|
|
|
+ Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.random_get = function (bufPtr, bufLen) {
|
|
|
+ var Result = 0;
|
|
|
+ var arr = null;
|
|
|
+ var I = 0;
|
|
|
+ var View = null;
|
|
|
+ arr = new Uint8Array(bufLen);
|
|
|
+ crypto.getRandomValues(arr);
|
|
|
+ View = this.getModuleMemoryDataView();
|
|
|
+ for (var $l = 0, $end = arr.length - 1; $l <= $end; $l++) {
|
|
|
+ I = $l;
|
|
|
+ View.setInt8(bufPtr + I,arr[I]);
|
|
|
+ };
|
|
|
+ Result = 0;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.sched_yield = function () {
|
|
|
+ var Result = 0;
|
|
|
+ Result = 0;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.sock_recv = function () {
|
|
|
+ var Result = 0;
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.sock_recv");
|
|
|
+ Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.sock_send = function () {
|
|
|
+ var Result = 0;
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.sock_recv");
|
|
|
+ Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.sock_shutdown = function () {
|
|
|
+ var Result = 0;
|
|
|
+ console.log("Unimplemented: TPas2JSWASIEnvironment.sock_shutdown");
|
|
|
+ Result = 52;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SetMemory = function (aMemory) {
|
|
|
+ this.FMemory = aMemory;
|
|
|
+ };
|
|
|
+ this.Create$1 = function () {
|
|
|
+ var I = 0;
|
|
|
+ this.FIsLittleEndian = true;
|
|
|
+ this.FWASIImportName = "wasi_snapshot_preview1";
|
|
|
+ this.FArguments = pas.Classes.TStringList.$create("Create$1");
|
|
|
+ this.FEnvironment = pas.Classes.TStringList.$create("Create$1");
|
|
|
+ for (var $l = 0, $end = pas.SysUtils.GetEnvironmentVariableCount() - 1; $l <= $end; $l++) {
|
|
|
+ I = $l;
|
|
|
+ this.FEnvironment.Add(pas.SysUtils.GetEnvironmentString(I));
|
|
|
+ };
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ this.Destroy = function () {
|
|
|
+ pas.SysUtils.FreeAndNil({p: this, get: function () {
|
|
|
+ return this.p.FEnvironment;
|
|
|
+ }, set: function (v) {
|
|
|
+ this.p.FEnvironment = v;
|
|
|
+ }});
|
|
|
+ pas.SysUtils.FreeAndNil({p: this, get: function () {
|
|
|
+ return this.p.FArguments;
|
|
|
+ }, set: function (v) {
|
|
|
+ this.p.FArguments = v;
|
|
|
+ }});
|
|
|
+ pas.SysUtils.FreeAndNil({p: this, get: function () {
|
|
|
+ return this.p.FImportExtensions;
|
|
|
+ }, set: function (v) {
|
|
|
+ this.p.FImportExtensions = v;
|
|
|
+ }});
|
|
|
+ pas.System.TObject.Destroy.call(this);
|
|
|
+ };
|
|
|
+ this.GetUTF8StringFromMem = function (aLoc, aLen) {
|
|
|
+ var Result = "";
|
|
|
+ Result = this.UTF8TextDecoder.decode(this.getModuleMemoryDataView().buffer.slice(aLoc,aLoc + aLen));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SetUTF8StringInMem = function (aLoc, aLen, AString) {
|
|
|
+ var Result = 0;
|
|
|
+ var Arr = null;
|
|
|
+ Arr = this.UTF8TextEncoder.encode(AString);
|
|
|
+ if (Arr.byteLength > aLen) {
|
|
|
+ Result = -Arr.byteLength}
|
|
|
+ else if (Arr.byteLength === 0) {
|
|
|
+ Result = 0}
|
|
|
+ else Result = this.SetUTF8StringInMem$1(aLoc,aLen,Arr);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SetUTF8StringInMem$1 = function (aLoc, aLen, AStringBuf) {
|
|
|
+ var Result = 0;
|
|
|
+ var Arr = null;
|
|
|
+ if (AStringBuf == null) return 0;
|
|
|
+ Arr = new Uint8Array(this.getModuleMemoryDataView().buffer,aLoc,aLen);
|
|
|
+ Arr.set(AStringBuf);
|
|
|
+ Result = AStringBuf.byteLength;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SetMemInfoInt32 = function (aLoc, aValue) {
|
|
|
+ var Result = 0;
|
|
|
+ var View = null;
|
|
|
+ View = this.getModuleMemoryDataView();
|
|
|
+ View.setInt32(aLoc,aValue,this.FIsLittleEndian);
|
|
|
+ Result = aLoc + 4;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SetMemInfoInt64 = function (aLoc, aValue) {
|
|
|
+ var Result = 0;
|
|
|
+ var View = null;
|
|
|
+ View = this.getModuleMemoryDataView();
|
|
|
+ this.$class.setBigInt64(View,aLoc,aValue,this.FIsLittleEndian);
|
|
|
+ Result = aLoc + 8;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SetMemInfoUInt8 = function (aLoc, aValue) {
|
|
|
+ var Result = 0;
|
|
|
+ var View = null;
|
|
|
+ View = this.getModuleMemoryDataView();
|
|
|
+ View.setUint8(aLoc,aValue);
|
|
|
+ Result = aLoc + 1;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SetMemInfoUInt32 = function (aLoc, aValue) {
|
|
|
+ var Result = 0;
|
|
|
+ var View = null;
|
|
|
+ View = this.getModuleMemoryDataView();
|
|
|
+ View.setUint32(aLoc,aValue,this.FIsLittleEndian);
|
|
|
+ Result = aLoc + 4;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SetMemInfoUInt64 = function (aLoc, aValue) {
|
|
|
+ var Result = 0;
|
|
|
+ var View = null;
|
|
|
+ View = this.getModuleMemoryDataView();
|
|
|
+ this.$class.setBigUint64(View,aLoc,aValue,this.FIsLittleEndian);
|
|
|
+ Result = aLoc + 8;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.AddImports = function (aObject) {
|
|
|
+ var Ext = null;
|
|
|
+ var I = 0;
|
|
|
+ var O = null;
|
|
|
+ aObject[this.FWASIImportName] = this.GetImportObject();
|
|
|
+ if (this.FImportExtensions != null) for (var $l = 0, $end = this.FImportExtensions.FCount - 1; $l <= $end; $l++) {
|
|
|
+ I = $l;
|
|
|
+ Ext = rtl.getObject(this.FImportExtensions.Get(I));
|
|
|
+ O = new Object();
|
|
|
+ Ext.FillImportObject(O);
|
|
|
+ aObject[Ext.ImportName()] = O;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.SetExports = function (aExports) {
|
|
|
+ var Ext = null;
|
|
|
+ var I = 0;
|
|
|
+ if (this.FImportExtensions != null) for (var $l = 0, $end = this.FImportExtensions.FCount - 1; $l <= $end; $l++) {
|
|
|
+ I = $l;
|
|
|
+ Ext = rtl.getObject(this.FImportExtensions.Get(I));
|
|
|
+ Ext.SetInstanceExports(aExports);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"TImportExtension",pas.System.TObject,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.System.TObject.$init.call(this);
|
|
|
+ this.FEnv = null;
|
|
|
+ this.FInstanceExports = null;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.FEnv = undefined;
|
|
|
+ this.FInstanceExports = undefined;
|
|
|
+ pas.System.TObject.$final.call(this);
|
|
|
+ };
|
|
|
+ this.SetInstanceExports = function (AValue) {
|
|
|
+ if (this.FInstanceExports === AValue) return;
|
|
|
+ this.FInstanceExports = AValue;
|
|
|
+ };
|
|
|
+ this.Create$1 = function (aEnv) {
|
|
|
+ this.FEnv = aEnv;
|
|
|
+ if (this.FEnv != null) this.FEnv.AddExtension(this);
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ this.Destroy = function () {
|
|
|
+ if (this.FEnv != null) this.FEnv.RemoveExtension(this);
|
|
|
+ pas.System.TObject.Destroy.call(this);
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.recNewT(this,"TWebAssemblyStartDescriptor",function () {
|
|
|
+ this.Module = null;
|
|
|
+ this.Memory = null;
|
|
|
+ this.Table = null;
|
|
|
+ this.Exported = null;
|
|
|
+ this.Imports = null;
|
|
|
+ this.Instance = null;
|
|
|
+ this.CallRun = null;
|
|
|
+ this.RunExceptionClass = "";
|
|
|
+ this.RunExceptionMessage = "";
|
|
|
+ this.$eq = function (b) {
|
|
|
+ return (this.Module === b.Module) && (this.Memory === b.Memory) && (this.Table === b.Table) && (this.Exported === b.Exported) && (this.Imports === b.Imports) && (this.Instance === b.Instance) && rtl.eqCallback(this.CallRun,b.CallRun) && (this.RunExceptionClass === b.RunExceptionClass) && (this.RunExceptionMessage === b.RunExceptionMessage);
|
|
|
+ };
|
|
|
+ this.$assign = function (s) {
|
|
|
+ this.Module = s.Module;
|
|
|
+ this.Memory = s.Memory;
|
|
|
+ this.Table = s.Table;
|
|
|
+ this.Exported = s.Exported;
|
|
|
+ this.Imports = s.Imports;
|
|
|
+ this.Instance = s.Instance;
|
|
|
+ this.CallRun = s.CallRun;
|
|
|
+ this.RunExceptionClass = s.RunExceptionClass;
|
|
|
+ this.RunExceptionMessage = s.RunExceptionMessage;
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"TWASIHost",pas.Classes.TComponent,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.Classes.TComponent.$init.call(this);
|
|
|
+ this.FAfterInstantation = null;
|
|
|
+ this.FAfterStart = null;
|
|
|
+ this.FBeforeInstantation = null;
|
|
|
+ this.FBeforeStart = null;
|
|
|
+ this.FEnv = null;
|
|
|
+ this.FExported = null;
|
|
|
+ this.FOnInstantiateFail = null;
|
|
|
+ this.FOnLoadFail = null;
|
|
|
+ this.FPreparedStartDescriptor = $mod.TWebAssemblyStartDescriptor.$new();
|
|
|
+ this.FMemoryDescriptor = pas.webassembly.TJSWebAssemblyMemoryDescriptor.$new();
|
|
|
+ this.FOnConsoleRead = null;
|
|
|
+ this.FOnConsoleWrite = null;
|
|
|
+ this.FPredefinedConsoleInput = null;
|
|
|
+ this.FReadLineCount = 0;
|
|
|
+ this.FRunEntryFunction = "";
|
|
|
+ this.FTableDescriptor = pas.webassembly.TJSWebAssemblyTableDescriptor.$new();
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.FAfterInstantation = undefined;
|
|
|
+ this.FAfterStart = undefined;
|
|
|
+ this.FBeforeInstantation = undefined;
|
|
|
+ this.FBeforeStart = undefined;
|
|
|
+ this.FEnv = undefined;
|
|
|
+ this.FExported = undefined;
|
|
|
+ this.FOnInstantiateFail = undefined;
|
|
|
+ this.FOnLoadFail = undefined;
|
|
|
+ this.FPreparedStartDescriptor = undefined;
|
|
|
+ this.FMemoryDescriptor = undefined;
|
|
|
+ this.FOnConsoleRead = undefined;
|
|
|
+ this.FOnConsoleWrite = undefined;
|
|
|
+ this.FPredefinedConsoleInput = undefined;
|
|
|
+ this.FTableDescriptor = undefined;
|
|
|
+ pas.Classes.TComponent.$final.call(this);
|
|
|
+ };
|
|
|
+ this.GetStartDescriptorReady = function () {
|
|
|
+ var Result = false;
|
|
|
+ var $with = this.FPreparedStartDescriptor;
|
|
|
+ Result = ($with.Memory != null) && ($with.Module != null);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.DoAfterInstantiate = function () {
|
|
|
+ if (this.FAfterInstantation != null) this.FAfterInstantation(this);
|
|
|
+ };
|
|
|
+ this.DoBeforeInstantiate = function () {
|
|
|
+ if (this.FBeforeInstantation != null) this.FBeforeInstantation(this);
|
|
|
+ };
|
|
|
+ this.DoLoadFail = function (aError) {
|
|
|
+ if (this.FOnLoadFail != null) this.FOnLoadFail(this,aError);
|
|
|
+ };
|
|
|
+ this.DoInstantiateFail = function (aError) {
|
|
|
+ if (this.FOnInstantiateFail != null) this.FOnInstantiateFail(this,aError);
|
|
|
+ };
|
|
|
+ this.PrepareWebAssemblyInstance = function (aDescr) {
|
|
|
+ this.FPreparedStartDescriptor.$assign(aDescr);
|
|
|
+ this.FExported = aDescr.Exported;
|
|
|
+ this.FEnv.SetInstance(aDescr.Instance);
|
|
|
+ this.FEnv.SetMemory(aDescr.Memory);
|
|
|
+ this.FEnv.SetExports(this.FExported);
|
|
|
+ this.DoAfterInstantiate();
|
|
|
+ };
|
|
|
+ this.RunWebAssemblyInstance = function (aBeforeStart, aAfterStart, aRun) {
|
|
|
+ var Result = false;
|
|
|
+ Result = true;
|
|
|
+ if (aBeforeStart != null) Result = aBeforeStart(this,$mod.TWebAssemblyStartDescriptor.$clone(this.FPreparedStartDescriptor));
|
|
|
+ if (this.FBeforeStart != null) this.FBeforeStart(this,$mod.TWebAssemblyStartDescriptor.$clone(this.FPreparedStartDescriptor),{get: function () {
|
|
|
+ return Result;
|
|
|
+ }, set: function (v) {
|
|
|
+ Result = v;
|
|
|
+ }});
|
|
|
+ if (!Result) return Result;
|
|
|
+ try {
|
|
|
+ if (aRun === null) aRun = this.FPreparedStartDescriptor.CallRun;
|
|
|
+ aRun(this.FPreparedStartDescriptor.Exported);
|
|
|
+ if (aAfterStart != null) aAfterStart(this,$mod.TWebAssemblyStartDescriptor.$clone(this.FPreparedStartDescriptor));
|
|
|
+ if (this.FAfterStart != null) this.FAfterStart(this,$mod.TWebAssemblyStartDescriptor.$clone(this.FPreparedStartDescriptor));
|
|
|
+ } catch ($e) {
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf($e)) {
|
|
|
+ var E = $e;
|
|
|
+ this.FPreparedStartDescriptor.RunExceptionClass = E.$classname;
|
|
|
+ this.FPreparedStartDescriptor.RunExceptionMessage = E.fMessage;
|
|
|
+ } else if (rtl.isExt($e,Error)) {
|
|
|
+ var JE = $e;
|
|
|
+ this.FPreparedStartDescriptor.RunExceptionClass = typeof(JE);
|
|
|
+ this.FPreparedStartDescriptor.RunExceptionMessage = JE.message;
|
|
|
+ } else if (rtl.isExt($e,Object)) {
|
|
|
+ var OE = $e;
|
|
|
+ this.FPreparedStartDescriptor.RunExceptionClass = typeof(OE);
|
|
|
+ this.FPreparedStartDescriptor.RunExceptionMessage = JSON.stringify(OE);
|
|
|
+ } else throw $e
|
|
|
+ };
|
|
|
+ if (this.FPreparedStartDescriptor.RunExceptionClass !== "") console.error("Running Webassembly resulted in exception. Exception class: ",this.FPreparedStartDescriptor.RunExceptionClass,", message:",this.FPreparedStartDescriptor.RunExceptionMessage);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.DoStdRead = function (Sender, AInput) {
|
|
|
+ var S = "";
|
|
|
+ S = "";
|
|
|
+ if (this.FOnConsoleRead != null) {
|
|
|
+ this.FOnConsoleRead(this,{get: function () {
|
|
|
+ return S;
|
|
|
+ }, set: function (v) {
|
|
|
+ S = v;
|
|
|
+ }})}
|
|
|
+ else {
|
|
|
+ if (this.FReadLineCount < this.FPredefinedConsoleInput.GetCount()) {
|
|
|
+ S = this.FPredefinedConsoleInput.Get(this.FReadLineCount);
|
|
|
+ this.FReadLineCount += 1;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ AInput.set(S);
|
|
|
+ };
|
|
|
+ this.DoStdWrite = function (Sender, aOutput) {
|
|
|
+ this.WriteOutput(aOutput);
|
|
|
+ };
|
|
|
+ this.CreateWebAssembly = function (aPath, aImportObject) {
|
|
|
+ var $Self = this;
|
|
|
+ var Result = null;
|
|
|
+ function InstantiateOK(Res) {
|
|
|
+ var Result = undefined;
|
|
|
+ Result = Res;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ function InstantiateFail(Res) {
|
|
|
+ var Result = undefined;
|
|
|
+ Result = false;
|
|
|
+ console.log("Instantiating of WebAssembly from " + aPath + " failed " + $impl.ValueToMessage(Res));
|
|
|
+ $Self.DoInstantiateFail(Res);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ function ArrayOK(res2) {
|
|
|
+ var Result = undefined;
|
|
|
+ $Self.DoBeforeInstantiate();
|
|
|
+ Result = WebAssembly.instantiate(res2,aImportObject).then(InstantiateOK,InstantiateFail);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ function DoFail(res) {
|
|
|
+ var Result = undefined;
|
|
|
+ Result = false;
|
|
|
+ console.log('Loading of WebAssembly from URL "' + aPath + '" failed: ' + $impl.ValueToMessage(res));
|
|
|
+ $Self.DoLoadFail(res);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ function fetchOK(res) {
|
|
|
+ var Result = undefined;
|
|
|
+ if (rtl.trunc(res.status / 100) !== 2) {
|
|
|
+ $Self.DoLoadFail(res);
|
|
|
+ throw new Error('Loading of WebAssembly from URL "' + aPath + '" failed: status: ' + pas.SysUtils.IntToStr(res.status) + " " + res.statusText);
|
|
|
+ } else Result = res.arrayBuffer().then(ArrayOK,null);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ Result = fetch(aPath).then(fetchOK,DoFail);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.CreateWasiEnvironment = function () {
|
|
|
+ var Result = null;
|
|
|
+ Result = $mod.TPas2JSWASIEnvironment.$create("Create$1");
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetTable = function () {
|
|
|
+ var Result = null;
|
|
|
+ Result = new WebAssembly.Table(pas.webassembly.TJSWebAssemblyTableDescriptor.$clone(this.FTableDescriptor));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetMemory = function () {
|
|
|
+ var Result = null;
|
|
|
+ Result = new WebAssembly.Memory(pas.webassembly.TJSWebAssemblyMemoryDescriptor.$clone(this.FMemoryDescriptor));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Create$1 = function (aOwner) {
|
|
|
+ pas.Classes.TComponent.Create$1.call(this,aOwner);
|
|
|
+ this.FEnv = this.CreateWasiEnvironment();
|
|
|
+ this.FEnv.FOnStdErrorWrite = rtl.createCallback(this,"DoStdWrite");
|
|
|
+ this.FEnv.FOnStdOutputWrite = rtl.createCallback(this,"DoStdWrite");
|
|
|
+ this.FEnv.FOnGetConsoleInputString = rtl.createCallback(this,"DoStdRead");
|
|
|
+ this.FMemoryDescriptor.initial = 256;
|
|
|
+ this.FMemoryDescriptor.maximum = 256;
|
|
|
+ this.FMemoryDescriptor.shared = false;
|
|
|
+ this.FTableDescriptor.initial = 0;
|
|
|
+ this.FTableDescriptor.maximum = 0;
|
|
|
+ this.FTableDescriptor.element = "anyfunc";
|
|
|
+ this.FPredefinedConsoleInput = pas.Classes.TStringList.$create("Create$1");
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ this.Destroy = function () {
|
|
|
+ pas.SysUtils.FreeAndNil({p: this, get: function () {
|
|
|
+ return this.p.FPredefinedConsoleInput;
|
|
|
+ }, set: function (v) {
|
|
|
+ this.p.FPredefinedConsoleInput = v;
|
|
|
+ }});
|
|
|
+ pas.SysUtils.FreeAndNil({p: this, get: function () {
|
|
|
+ return this.p.FEnv;
|
|
|
+ }, set: function (v) {
|
|
|
+ this.p.FEnv = v;
|
|
|
+ }});
|
|
|
+ pas.Classes.TComponent.Destroy.call(this);
|
|
|
+ };
|
|
|
+ this.WriteOutput = function (aOutput) {
|
|
|
+ if (this.FOnConsoleWrite != null) {
|
|
|
+ this.FOnConsoleWrite(this,aOutput)}
|
|
|
+ else pas.System.Writeln(aOutput);
|
|
|
+ };
|
|
|
+ this.InitStartDescriptor = function (aMemory, aTable, aImportObj) {
|
|
|
+ var Result = $mod.TWebAssemblyStartDescriptor.$new();
|
|
|
+ Result.Memory = aMemory;
|
|
|
+ Result.Table = aTable;
|
|
|
+ if (!(aImportObj != null)) aImportObj = new Object();
|
|
|
+ aImportObj["env"] = pas.JS.New(["memory",Result.Memory,"tbl",Result.Table]);
|
|
|
+ this.FEnv.AddImports(aImportObj);
|
|
|
+ Result.Imports = aImportObj;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.StartWebAssembly = function (aPath, DoRun, aBeforeStart, aAfterStart) {
|
|
|
+ var $Self = this;
|
|
|
+ var Result = null;
|
|
|
+ var WASD = $mod.TWebAssemblyStartDescriptor.$new();
|
|
|
+ function InitEnv(aValue) {
|
|
|
+ var Result = undefined;
|
|
|
+ if (!(typeof(aValue) === "object")) throw $mod.EWasiError.$create("Create$1",["Did not get a instantiated webassembly"]);
|
|
|
+ WASD.Instance = aValue.instance;
|
|
|
+ WASD.Module = aValue.module;
|
|
|
+ WASD.Exported = WASD.Instance.exports;
|
|
|
+ WASD.CallRun = function (aExports) {
|
|
|
+ if ($Self.FRunEntryFunction === "") {
|
|
|
+ if (aExports["_initialize"] != null) {
|
|
|
+ aExports._initialize()}
|
|
|
+ else aExports._start()}
|
|
|
+ else aExports[$Self.FRunEntryFunction]();
|
|
|
+ };
|
|
|
+ $Self.PrepareWebAssemblyInstance($mod.TWebAssemblyStartDescriptor.$clone(WASD));
|
|
|
+ if (DoRun) $Self.RunWebAssemblyInstance(aBeforeStart,aAfterStart,null);
|
|
|
+ Result = Promise.resolve($mod.TWebAssemblyStartDescriptor.$clone(WASD));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ function DoFail(aValue) {
|
|
|
+ var Result = undefined;
|
|
|
+ Result = true;
|
|
|
+ console.log("Failed to create webassembly. Reason:");
|
|
|
+ console.debug(aValue);
|
|
|
+ if (rtl.isObject(aValue)) throw aValue;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.FReadLineCount = 0;
|
|
|
+ this.FPreparedStartDescriptor.$assign($mod.TWebAssemblyStartDescriptor.$new());
|
|
|
+ WASD.$assign(this.InitStartDescriptor(this.GetMemory(),this.GetTable(),null));
|
|
|
+ Result = this.CreateWebAssembly(aPath,WASD.Imports).then(InitEnv,DoFail);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ $mod.$implcode = function () {
|
|
|
+ $impl.ValueToMessage = function (Res) {
|
|
|
+ var Result = "";
|
|
|
+ if (rtl.isObject(Res)) {
|
|
|
+ Result = rtl.getObject(Res).$classname;
|
|
|
+ if (pas.SysUtils.Exception.isPrototypeOf(rtl.getObject(Res))) Result = Result + ": " + rtl.getObject(Res).fMessage;
|
|
|
+ };
|
|
|
+ if ((typeof(Res) === "object") && Res.hasOwnProperty("message")) {
|
|
|
+ Result = "" + Res["message"]}
|
|
|
+ else Result = JSON.stringify(Res);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ $impl.toUTF8Array = function (str) {
|
|
|
+ var Result = null;
|
|
|
+ var Len = 0;
|
|
|
+ var I = 0;
|
|
|
+ var P = 0;
|
|
|
+ var charCode = 0;
|
|
|
+ function push(abyte) {
|
|
|
+ Result[P] = abyte;
|
|
|
+ P += 1;
|
|
|
+ };
|
|
|
+ Result = new Uint8Array(str.length * 4);
|
|
|
+ P = 0;
|
|
|
+ Len = str.length;
|
|
|
+ I = 1;
|
|
|
+ while (I <= Len) {
|
|
|
+ charCode = str.charCodeAt(I - 1);
|
|
|
+ if (charCode < 0x80) {
|
|
|
+ push(charCode)}
|
|
|
+ else if (charCode < 0x800) {
|
|
|
+ push(rtl.or(0xc0,Math.floor(charCode / 64)));
|
|
|
+ push(rtl.or(0x80,charCode & 0x3f));
|
|
|
+ } else if ((charCode < 0xd800) || (charCode >= 0xe000)) {
|
|
|
+ push(rtl.or(0xe0,Math.floor(charCode / 4096)));
|
|
|
+ push(rtl.or(0x80,Math.floor(charCode / 64) & 0x3f));
|
|
|
+ push(rtl.or(0x80,charCode & 0x3f));
|
|
|
+ } else {
|
|
|
+ I += 1;
|
|
|
+ charCode = 0x10000 + rtl.or(rtl.shl(charCode & 0x3ff,10),str.charCodeAt(I - 1) & 0x3ff);
|
|
|
+ push(rtl.or(0xf0,Math.floor(charCode / 262144)));
|
|
|
+ push(rtl.or(0x80,Math.floor(charCode / 4096) & 0x3f));
|
|
|
+ push(rtl.or(0x80,Math.floor(charCode / 64) & 0x3f));
|
|
|
+ push(rtl.or(0x80,charCode & 0x3f));
|
|
|
+ };
|
|
|
+ I += 1;
|
|
|
+ };
|
|
|
+ Result = Result.slice(0,P);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ $mod.$init = function () {
|
|
|
+ (function () {
|
|
|
+ var Opts = null;
|
|
|
+ Opts = new Object();
|
|
|
+ Opts.ignoreBOM = true;
|
|
|
+ Opts.fatal = true;
|
|
|
+ $mod.TPas2JSWASIEnvironment.UTF8TextDecoder = new TextDecoder("utf-8",Opts);
|
|
|
+ $mod.TPas2JSWASIEnvironment.UTF8TextEncoder = new TextEncoder();
|
|
|
+ })();
|
|
|
+ };
|
|
|
+},["weborworker"]);
|
|
|
+rtl.module("Rtl.WebThreads",["System","JS","SysUtils","wasienv","webassembly"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ this.ThreadIDInterval = 1000;
|
|
|
+ this.cmdConsole = "console";
|
|
|
+ this.cmdException = "exception";
|
|
|
+ this.cmdCleanup = "cleanup";
|
|
|
+ this.cmdCancel = "cancel";
|
|
|
+ this.cmdLoaded = "loaded";
|
|
|
+ this.cmdKill = "kill";
|
|
|
+ this.cmdSpawn = "spawn";
|
|
|
+ this.cmdLoad = "load";
|
|
|
+ this.cmdRun = "run";
|
|
|
+ this.cmdExecute = "execute";
|
|
|
+ this.DefaultThreadWorker = "pas2jsthreadworker.js";
|
|
|
+ this.DefaultThreadCount = 2;
|
|
|
+ this.DefaultMaxWorkerCount = 100;
|
|
|
+ this.sThreadSpawn = "thread-spawn";
|
|
|
+ this.sThreadDetach = "thread_detach";
|
|
|
+ this.sThreadCancel = "thread_cancel";
|
|
|
+ this.sThreadSelf = "thread_self";
|
|
|
+ rtl.createClass(this,"EWasmThreads",pas.SysUtils.Exception,function () {
|
|
|
+ });
|
|
|
+ rtl.createHelper(this,"TWorkerCommandHelper",null,function () {
|
|
|
+ this.NewWorker = function (aCommand, aThreadID) {
|
|
|
+ var Result = null;
|
|
|
+ Result = new Object();
|
|
|
+ Result.Command = pas.SysUtils.LowerCase(aCommand);
|
|
|
+ if (aThreadID !== -1) Result.ThreadID = aThreadID;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.createHelper(this,"TWorkerExceptionCommandHelper",null,function () {
|
|
|
+ this.CommandName = function () {
|
|
|
+ var Result = "";
|
|
|
+ Result = $mod.cmdException;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.CreateNew = function (aExceptionClass, aExceptionMessage, aThreadID) {
|
|
|
+ var Result = null;
|
|
|
+ Result = $mod.TWorkerCommandHelper.NewWorker($mod.TWorkerExceptionCommandHelper.CommandName(),aThreadID);
|
|
|
+ Result.ExceptionClass = aExceptionClass;
|
|
|
+ Result.ExceptionMessage = aExceptionMessage;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.createHelper(this,"TWorkerConsoleCommandHelper",null,function () {
|
|
|
+ this.CommandName = function () {
|
|
|
+ var Result = "";
|
|
|
+ Result = $mod.cmdConsole;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Create = function (aMessage, aThreadID) {
|
|
|
+ var Result = null;
|
|
|
+ Result = $mod.TWorkerCommandHelper.NewWorker($mod.TWorkerConsoleCommandHelper.CommandName(),aThreadID);
|
|
|
+ Result.ConsoleMessage = aMessage;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.createHelper(this,"TWorkerLoadCommandHelper",null,function () {
|
|
|
+ this.CommandName = function () {
|
|
|
+ var Result = "";
|
|
|
+ Result = $mod.cmdLoad;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Create = function (aStartThreadIdRange, aModule, aMemory) {
|
|
|
+ var Result = null;
|
|
|
+ Result = $mod.TWorkerCommandHelper.NewWorker($mod.TWorkerLoadCommandHelper.CommandName(),-1);
|
|
|
+ Result.ThreadRangeStart = aStartThreadIdRange;
|
|
|
+ Result.Memory = aMemory;
|
|
|
+ Result.Module = aModule;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.createHelper(this,"TWorkerRunCommandHelper",null,function () {
|
|
|
+ this.CommandName = function () {
|
|
|
+ var Result = "";
|
|
|
+ Result = $mod.cmdRun;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Create = function (aThreadID, aArgs) {
|
|
|
+ var Result = null;
|
|
|
+ Result = $mod.TWorkerCommandHelper.NewWorker($mod.TWorkerRunCommandHelper.CommandName(),-1);
|
|
|
+ Result.ThreadID = aThreadID;
|
|
|
+ Result.Args = aArgs;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.recNewT(this,"TThreadinfo",function () {
|
|
|
+ this.OriginThreadID = 0;
|
|
|
+ this.ThreadID = 0;
|
|
|
+ this.Arguments = 0;
|
|
|
+ this.$eq = function (b) {
|
|
|
+ return (this.OriginThreadID === b.OriginThreadID) && (this.ThreadID === b.ThreadID) && (this.Arguments === b.Arguments);
|
|
|
+ };
|
|
|
+ this.$assign = function (s) {
|
|
|
+ this.OriginThreadID = s.OriginThreadID;
|
|
|
+ this.ThreadID = s.ThreadID;
|
|
|
+ this.Arguments = s.Arguments;
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"TWasmThreadSupport",pas.wasienv.TImportExtension,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.wasienv.TImportExtension.$init.call(this);
|
|
|
+ this.FOnSendCommand = null;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.FOnSendCommand = undefined;
|
|
|
+ pas.wasienv.TImportExtension.$final.call(this);
|
|
|
+ };
|
|
|
+ this.ImportName = function () {
|
|
|
+ var Result = "";
|
|
|
+ Result = "wasi";
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.FillImportObject = function (aObject) {
|
|
|
+ aObject[$mod.sThreadSpawn] = rtl.createCallback(this,"thread_spawn");
|
|
|
+ aObject[$mod.sThreadDetach] = rtl.createCallback(this,"thread_detach");
|
|
|
+ aObject[$mod.sThreadCancel] = rtl.createCallback(this,"thread_cancel");
|
|
|
+ aObject[$mod.sThreadSelf] = rtl.createCallback(this,"thread_self");
|
|
|
+ };
|
|
|
+ this.HandleCommand = function (aCommand) {
|
|
|
+ var P = null;
|
|
|
+ P = new Object();
|
|
|
+ P.ExceptionClass = "ENotSupportedException";
|
|
|
+ P.ExceptionMessage = "Unsupported command : " + JSON.stringify(aCommand);
|
|
|
+ this.SendCommand(aCommand);
|
|
|
+ };
|
|
|
+ this.SendCommand = function (aCommand) {
|
|
|
+ if (this.FOnSendCommand != null) this.FOnSendCommand(this,aCommand);
|
|
|
+ };
|
|
|
+ });
|
|
|
+});
|
|
|
+rtl.module("Rtl.threadcontroller",["System","JS","Classes","SysUtils","Rtl.WebThreads","wasienv","weborworker"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ rtl.createHelper(this,"TWasmThreadHelper",null,function () {
|
|
|
+ this.GetLoadSent = function () {
|
|
|
+ var Result = false;
|
|
|
+ var S = undefined;
|
|
|
+ S = this["FLoadSent"];
|
|
|
+ if (pas.JS.isBoolean(S)) {
|
|
|
+ Result = !(S == false)}
|
|
|
+ else Result = false;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetThreadID = function () {
|
|
|
+ var Result = 0;
|
|
|
+ Result = $mod.TWasmThreadHelper.GetThreadInfo.call(this).ThreadID;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetThreadIDRange = function () {
|
|
|
+ var Result = 0;
|
|
|
+ var S = undefined;
|
|
|
+ S = this["FThreadIDRange"];
|
|
|
+ if (rtl.isNumber(S)) {
|
|
|
+ Result = rtl.trunc(S)}
|
|
|
+ else Result = 0;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetThreadInfo = function () {
|
|
|
+ var Result = pas["Rtl.WebThreads"].TThreadinfo.$new();
|
|
|
+ var S = undefined;
|
|
|
+ S = this["FThreadInfo"];
|
|
|
+ if (rtl.isObject(S)) {
|
|
|
+ Result.$assign(rtl.getObject(S))}
|
|
|
+ else Result.$assign(pas["Rtl.WebThreads"].TThreadinfo.$new());
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SetLoaded = function (AValue) {
|
|
|
+ this["FLoaded"] = AValue;
|
|
|
+ };
|
|
|
+ this.SetLoadSent = function (AValue) {
|
|
|
+ this["FLoadSent"] = AValue;
|
|
|
+ };
|
|
|
+ this.SetThreadID = function (AValue) {
|
|
|
+ $mod.TWasmThreadHelper.GetThreadInfo.call(this).ThreadID = AValue;
|
|
|
+ };
|
|
|
+ this.SetThreadIDRange = function (AValue) {
|
|
|
+ this["FThreadIDRange"] = AValue;
|
|
|
+ };
|
|
|
+ this.SetThreadInfo = function (AValue) {
|
|
|
+ this["FThreadInfo"] = AValue;
|
|
|
+ };
|
|
|
+ this.Create = function (aScript) {
|
|
|
+ var Result = null;
|
|
|
+ Result = new Worker(aScript);
|
|
|
+ $mod.TWasmThreadHelper.SetThreadID.call(Result,-1);
|
|
|
+ $mod.TWasmThreadHelper.SetLoaded.call(Result,false);
|
|
|
+ $mod.TWasmThreadHelper.SetLoadSent.call(Result,false);
|
|
|
+ $mod.TWasmThreadHelper.SetThreadIDRange.call(Result,-1);
|
|
|
+ $mod.TWasmThreadHelper.SetThreadInfo.call(Result,pas["Rtl.WebThreads"].TThreadinfo.$new());
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SendCommand = function (aCommand) {
|
|
|
+ this.postMessage(aCommand);
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"TThreadController",pas["Rtl.WebThreads"].TWasmThreadSupport,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas["Rtl.WebThreads"].TWasmThreadSupport.$init.call(this);
|
|
|
+ this.FInitialWorkerCount = 0;
|
|
|
+ this.FMaxWorkerCount = 0;
|
|
|
+ this.FOnUnknownMessage = null;
|
|
|
+ this.FHost = null;
|
|
|
+ this.FWorkerScript = "";
|
|
|
+ this.FNextIDRange = 0;
|
|
|
+ this.FNextThreadID = 0;
|
|
|
+ this.FIdleWorkers = [];
|
|
|
+ this.FBusyWorkers = [];
|
|
|
+ this.FThreads = null;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.FOnUnknownMessage = undefined;
|
|
|
+ this.FHost = undefined;
|
|
|
+ this.FIdleWorkers = undefined;
|
|
|
+ this.FBusyWorkers = undefined;
|
|
|
+ this.FThreads = undefined;
|
|
|
+ pas["Rtl.WebThreads"].TWasmThreadSupport.$final.call(this);
|
|
|
+ };
|
|
|
+ this.SetWasiHost = function (AValue) {
|
|
|
+ if (this.FHost === AValue) return;
|
|
|
+ this.FHost = AValue;
|
|
|
+ if ((this.FHost != null) && this.FHost.GetStartDescriptorReady()) this.SendLoadCommands();
|
|
|
+ };
|
|
|
+ this.thread_spawn = function (start_arg) {
|
|
|
+ var Result = 0;
|
|
|
+ var aInfo = pas["Rtl.WebThreads"].TThreadinfo.$new();
|
|
|
+ pas.System.Writeln("In host thread_spawn");
|
|
|
+ aInfo.ThreadID = this.AllocateThreadID();
|
|
|
+ aInfo.Arguments = start_arg;
|
|
|
+ aInfo.OriginThreadID = 0;
|
|
|
+ Result = this.SpawnThread(pas["Rtl.WebThreads"].TThreadinfo.$clone(aInfo));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.thread_detach = function (thread_id) {
|
|
|
+ var Result = 0;
|
|
|
+ Result = -1;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.thread_cancel = function (thread_id) {
|
|
|
+ var Result = 0;
|
|
|
+ Result = -1;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.thread_self = function () {
|
|
|
+ var Result = 0;
|
|
|
+ Result = -1;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.AllocateThreadID = function () {
|
|
|
+ var Result = 0;
|
|
|
+ this.FNextThreadID += 1;
|
|
|
+ Result = this.FNextThreadID;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetNextThreadIDRange = function () {
|
|
|
+ var Result = 0;
|
|
|
+ this.FNextIDRange += 1000;
|
|
|
+ Result = this.FNextIDRange;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.DoWorkerMessage = function (aEvent) {
|
|
|
+ var aData = null;
|
|
|
+ var aWorker = null;
|
|
|
+ if (rtl.isObject(aEvent.data) && aEvent.data.hasOwnProperty("Command")) {
|
|
|
+ aData = aEvent.data;
|
|
|
+ aWorker = aEvent.target;
|
|
|
+ this.HandleCommand$1(aWorker,aData);
|
|
|
+ } else if (this.FOnUnknownMessage != null) {
|
|
|
+ this.FOnUnknownMessage(aEvent)}
|
|
|
+ else pas.System.Writeln("Unknown worker message : ",JSON.stringify(aEvent));
|
|
|
+ };
|
|
|
+ this.AllocateNewWorker = function (aWorkerScript) {
|
|
|
+ var Result = null;
|
|
|
+ Result = $mod.TWasmThreadHelper.Create(aWorkerScript);
|
|
|
+ $mod.TWasmThreadHelper.SetThreadIDRange.call(Result,this.GetNextThreadIDRange());
|
|
|
+ Result.addEventListener("message",rtl.createSafeCallback(this,"DoWorkerMessage"));
|
|
|
+ if ((this.FHost != null) && this.FHost.GetStartDescriptorReady()) {
|
|
|
+ this.SendLoadCommand(Result)}
|
|
|
+ else pas.System.Writeln("Host not set, delaying sending load command." + aWorkerScript);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SendLoadCommand = function (aThreadWorker) {
|
|
|
+ var WLC = null;
|
|
|
+ WLC = pas["Rtl.WebThreads"].TWorkerLoadCommandHelper.Create($mod.TWasmThreadHelper.GetThreadIDRange.call(aThreadWorker),this.FHost.FPreparedStartDescriptor.Module,this.FHost.FPreparedStartDescriptor.Memory);
|
|
|
+ $mod.TWasmThreadHelper.SendCommand.call(aThreadWorker,WLC);
|
|
|
+ $mod.TWasmThreadHelper.SetLoadSent.call(aThreadWorker,true);
|
|
|
+ };
|
|
|
+ this.GetNewWorker = function () {
|
|
|
+ var Result = null;
|
|
|
+ var WT = null;
|
|
|
+ if (rtl.length(this.FIdleWorkers) === 0) {
|
|
|
+ if (rtl.length(this.FBusyWorkers) < this.FMaxWorkerCount) {
|
|
|
+ WT = this.AllocateNewWorker(this.FWorkerScript)}
|
|
|
+ else throw pas["Rtl.WebThreads"].EWasmThreads.$create("Create$1",[rtl.getResStr($mod,"SErrMaxWorkersReached")]);
|
|
|
+ } else {
|
|
|
+ WT = this.FIdleWorkers.pop();
|
|
|
+ };
|
|
|
+ this.FBusyWorkers.push(WT);
|
|
|
+ Result = WT;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SpawnThread = function (aInfo) {
|
|
|
+ var $Self = this;
|
|
|
+ var Result = 0;
|
|
|
+ var WT = null;
|
|
|
+ var TryCount = 0;
|
|
|
+ TryCount = 0;
|
|
|
+ WT = this.GetNewWorker();
|
|
|
+ if (WT === null) {
|
|
|
+ pas.System.Writeln("Error: no worker !");
|
|
|
+ return -1;
|
|
|
+ };
|
|
|
+ $mod.TWasmThreadHelper.SetThreadInfo.call(WT,aInfo);
|
|
|
+ this.FThreads[aInfo.ThreadID] = WT;
|
|
|
+ this.SendRunCommand(WT);
|
|
|
+ Result = aInfo.ThreadID;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.SendRunCommand = function (aThreadWorker) {
|
|
|
+ var WRC = null;
|
|
|
+ var $with = $mod.TWasmThreadHelper.GetThreadInfo.call(aThreadWorker);
|
|
|
+ WRC = pas["Rtl.WebThreads"].TWorkerRunCommandHelper.Create($with.ThreadID,$with.Arguments);
|
|
|
+ $mod.TWasmThreadHelper.SendCommand.call(aThreadWorker,WRC);
|
|
|
+ };
|
|
|
+ this.HandleSpawnCommand = function (aWorker, aCommand) {
|
|
|
+ var aInfo = pas["Rtl.WebThreads"].TThreadinfo.$new();
|
|
|
+ aInfo.OriginThreadID = $mod.TWasmThreadHelper.GetThreadID.call(aWorker);
|
|
|
+ aInfo.ThreadID = aCommand.ThreadID;
|
|
|
+ aInfo.Arguments = aCommand.Arguments;
|
|
|
+ this.SpawnThread(pas["Rtl.WebThreads"].TThreadinfo.$clone(aInfo));
|
|
|
+ };
|
|
|
+ this.HandleCancelCommand = function (aWorker, aCommand) {
|
|
|
+ };
|
|
|
+ this.HandleCleanupCommand = function (aWorker, aCommand) {
|
|
|
+ var Idx = 0;
|
|
|
+ $mod.TWasmThreadHelper.SetThreadInfo.call(aWorker,pas["Rtl.WebThreads"].TThreadinfo.$new());
|
|
|
+ Idx = this.FBusyWorkers.indexOf(aWorker);
|
|
|
+ if (Idx !== -1) this.FBusyWorkers.splice(Idx,1);
|
|
|
+ Idx = this.FIdleWorkers.indexOf(aWorker);
|
|
|
+ if (Idx === -1) this.FIdleWorkers = rtl.arrayPushN(this.FIdleWorkers,aWorker);
|
|
|
+ };
|
|
|
+ this.HandleKillCommand = function (aWorker, aCommand) {
|
|
|
+ };
|
|
|
+ this.HandleLoadedCommand = function (aWorker, aCommand) {
|
|
|
+ $mod.TWasmThreadHelper.SetLoaded.call(aWorker,true);
|
|
|
+ if ($mod.TWasmThreadHelper.GetThreadID.call(aWorker) > 0) this.SendRunCommand(aWorker);
|
|
|
+ };
|
|
|
+ this.HandleConsoleCommand = function (aWorker, aCommand) {
|
|
|
+ var Prefix = "";
|
|
|
+ Prefix = pas.SysUtils.Format("Wasm thread %d: ",pas.System.VarRecs(0,$mod.TWasmThreadHelper.GetThreadID.call(aWorker)));
|
|
|
+ if (this.FHost.FOnConsoleWrite != null) {
|
|
|
+ this.FHost.FOnConsoleWrite(this.FHost,Prefix + aCommand.ConsoleMessage)}
|
|
|
+ else pas.System.Writeln(Prefix + aCommand.ConsoleMessage);
|
|
|
+ };
|
|
|
+ this.Create$1 = function (aEnv) {
|
|
|
+ this.Create$3(aEnv,pas["Rtl.WebThreads"].DefaultThreadWorker,2);
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ this.Create$3 = function (aEnv, aWorkerScript, aSpawnWorkerCount) {
|
|
|
+ var I = 0;
|
|
|
+ pas.wasienv.TImportExtension.Create$1.call(this,aEnv);
|
|
|
+ this.FThreads = new Object();
|
|
|
+ this.FWorkerScript = aWorkerScript;
|
|
|
+ this.FInitialWorkerCount = aSpawnWorkerCount;
|
|
|
+ this.FMaxWorkerCount = 100;
|
|
|
+ for (var $l = 1, $end = aSpawnWorkerCount; $l <= $end; $l++) {
|
|
|
+ I = $l;
|
|
|
+ this.FIdleWorkers.push(this.AllocateNewWorker(aWorkerScript));
|
|
|
+ };
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ this.HandleCommand$1 = function (aWorker, aCommand) {
|
|
|
+ var $tmp = aCommand.Command;
|
|
|
+ if ($tmp === pas["Rtl.WebThreads"].cmdSpawn) {
|
|
|
+ this.HandleSpawnCommand(aWorker,aCommand)}
|
|
|
+ else if ($tmp === pas["Rtl.WebThreads"].cmdCleanup) {
|
|
|
+ this.HandleCleanupCommand(aWorker,aCommand)}
|
|
|
+ else if ($tmp === pas["Rtl.WebThreads"].cmdKill) {
|
|
|
+ this.HandleKillCommand(aWorker,aCommand)}
|
|
|
+ else if ($tmp === pas["Rtl.WebThreads"].cmdCancel) {
|
|
|
+ this.HandleCancelCommand(aWorker,aCommand)}
|
|
|
+ else if ($tmp === pas["Rtl.WebThreads"].cmdLoaded) {
|
|
|
+ this.HandleLoadedCommand(aWorker,aCommand)}
|
|
|
+ else if ($tmp === pas["Rtl.WebThreads"].cmdConsole) {
|
|
|
+ this.HandleConsoleCommand(aWorker,aCommand)}
|
|
|
+ else {
|
|
|
+ this.HandleCommand(aCommand);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.SendLoadCommands = function () {
|
|
|
+ var WT = null;
|
|
|
+ for (var $in = this.FIdleWorkers, $l = 0, $end = rtl.length($in) - 1; $l <= $end; $l++) {
|
|
|
+ WT = $in[$l];
|
|
|
+ if (!$mod.TWasmThreadHelper.GetLoadSent.call(WT)) this.SendLoadCommand(WT);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ });
|
|
|
+ $mod.$implcode = function () {
|
|
|
+ $mod.$resourcestrings = {SErrMaxWorkersReached: {org: "Cannot create thread worker, Maximum number of workers (%d) reached."}};
|
|
|
+ };
|
|
|
+},[]);
|
|
|
+rtl.module("wasiworkerthreadhost",["System","Classes","SysUtils","JS","CustApp","weborworker","webworker","webassembly","wasienv","Rtl.WebThreads","Rtl.threadcontroller"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ rtl.createClass(this,"TWorkerWASIHostApplication",pas.CustApp.TCustomApplication,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.CustApp.TCustomApplication.$init.call(this);
|
|
|
+ this.FHost = null;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.FHost = undefined;
|
|
|
+ pas.CustApp.TCustomApplication.$final.call(this);
|
|
|
+ };
|
|
|
+ this.DoOnSendCommand = function (Sender, aCommand) {
|
|
|
+ this.SendCommand(aCommand);
|
|
|
+ };
|
|
|
+ this.DoRun = function () {
|
|
|
+ self.addEventListener("message",rtl.createSafeCallback(this,"HandleMessage"));
|
|
|
+ };
|
|
|
+ this.Create$1 = function (aOwner) {
|
|
|
+ pas.CustApp.TCustomApplication.Create$1.call(this,aOwner);
|
|
|
+ this.FHost = this.CreateHost();
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ this.Destroy = function () {
|
|
|
+ pas.SysUtils.FreeAndNil({p: this, get: function () {
|
|
|
+ return this.p.FHost;
|
|
|
+ }, set: function (v) {
|
|
|
+ this.p.FHost = v;
|
|
|
+ }});
|
|
|
+ pas.Classes.TComponent.Destroy.call(this);
|
|
|
+ };
|
|
|
+ this.SendCommand = function (aCommand) {
|
|
|
+ self.postMessage(aCommand);
|
|
|
+ };
|
|
|
+ this.StartWebAssembly = function (aPath, DoRun, aBeforeStart, aAfterStart) {
|
|
|
+ this.FHost.StartWebAssembly(aPath,DoRun,aBeforeStart,aAfterStart);
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"TWASIThreadControllerHost",pas.wasienv.TWASIHost,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.wasienv.TWASIHost.$init.call(this);
|
|
|
+ this.FThreadSupport = null;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.FThreadSupport = undefined;
|
|
|
+ pas.wasienv.TWASIHost.$final.call(this);
|
|
|
+ };
|
|
|
+ this.SetThreadSupport = function (AValue) {
|
|
|
+ if (this.FThreadSupport != null) this.FThreadSupport.SetWasiHost(null);
|
|
|
+ this.FThreadSupport = AValue;
|
|
|
+ if (this.FThreadSupport != null) this.FThreadSupport.SetWasiHost(this);
|
|
|
+ };
|
|
|
+ this.DoAfterInstantiate = function () {
|
|
|
+ pas.wasienv.TWASIHost.DoAfterInstantiate.call(this);
|
|
|
+ if (this.FThreadSupport != null) this.FThreadSupport.SendLoadCommands();
|
|
|
+ };
|
|
|
+ this.Create$1 = function (aOwner) {
|
|
|
+ pas.wasienv.TWASIHost.Create$1.call(this,aOwner);
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ rtl.createClass(this,"TWorkerThreadControllerApplication",this.TWorkerWASIHostApplication,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ $mod.TWorkerWASIHostApplication.$init.call(this);
|
|
|
+ this.FThreadSupport = null;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.FThreadSupport = undefined;
|
|
|
+ $mod.TWorkerWASIHostApplication.$final.call(this);
|
|
|
+ };
|
|
|
+ this.HandleConsoleWrite = function (Sender, aOutput) {
|
|
|
+ this.SendCommand(pas["Rtl.WebThreads"].TWorkerConsoleCommandHelper.Create(aOutput,0));
|
|
|
+ };
|
|
|
+ this.HandleExecuteCommand = function (aCmd) {
|
|
|
+ if (rtl.isObject(aCmd.Env)) $impl.EnvNames = aCmd.Env;
|
|
|
+ if (rtl.isString(aCmd.ExecuteFunc)) this.FHost.FRunEntryFunction = aCmd.ExecuteFunc;
|
|
|
+ this.StartWebAssembly(aCmd.Url,true,null,null);
|
|
|
+ };
|
|
|
+ this.ShowException = function (aError) {
|
|
|
+ var Ex = null;
|
|
|
+ Ex = pas["Rtl.WebThreads"].TWorkerExceptionCommandHelper.CreateNew(aError.$classname,aError.fMessage,-1);
|
|
|
+ this.SendCommand(Ex);
|
|
|
+ };
|
|
|
+ this.HandleMessage = function (aEvent) {
|
|
|
+ var aData = null;
|
|
|
+ if (rtl.isObject(aEvent.data) && aEvent.data.hasOwnProperty("Command")) {
|
|
|
+ aData = aEvent.data;
|
|
|
+ var $tmp = aData.Command;
|
|
|
+ if ($tmp === pas["Rtl.WebThreads"].cmdExecute) {
|
|
|
+ this.HandleExecuteCommand(aData)}
|
|
|
+ else if ($tmp === pas["Rtl.WebThreads"].cmdConsole) {
|
|
|
+ this.SendCommand(aData)}
|
|
|
+ else {
|
|
|
+ this.FThreadSupport.HandleCommand(aData);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.CreateHost = function () {
|
|
|
+ var Result = null;
|
|
|
+ var TH = null;
|
|
|
+ var Mem = pas.webassembly.TJSWebAssemblyMemoryDescriptor.$new();
|
|
|
+ TH = $mod.TWASIThreadControllerHost.$create("Create$1",[this]);
|
|
|
+ TH.FOnConsoleWrite = rtl.createCallback(this,"HandleConsoleWrite");
|
|
|
+ this.FThreadSupport = pas["Rtl.threadcontroller"].TThreadController.$create("Create$1",[TH.FEnv]);
|
|
|
+ Mem.initial = 256;
|
|
|
+ Mem.maximum = 1024;
|
|
|
+ Mem.shared = true;
|
|
|
+ TH.FMemoryDescriptor.$assign(Mem);
|
|
|
+ this.FThreadSupport.FOnSendCommand = rtl.createCallback(this,"DoOnSendCommand");
|
|
|
+ TH.SetThreadSupport(this.FThreadSupport);
|
|
|
+ Result = TH;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ $mod.$implcode = function () {
|
|
|
+ $impl.EnvNames = null;
|
|
|
+ $impl.ReloadEnvironmentStrings = function () {
|
|
|
+ var I = 0;
|
|
|
+ var S = "";
|
|
|
+ var N = "";
|
|
|
+ var A = [];
|
|
|
+ var P = [];
|
|
|
+ if ($impl.EnvNames != null) pas.SysUtils.FreeAndNil({p: $impl, get: function () {
|
|
|
+ return this.p.EnvNames;
|
|
|
+ }, set: function (v) {
|
|
|
+ this.p.EnvNames = v;
|
|
|
+ }});
|
|
|
+ $impl.EnvNames = new Object();
|
|
|
+ S = self.location.search;
|
|
|
+ S = pas.System.Copy(S,2,S.length - 1);
|
|
|
+ A = S.split("&");
|
|
|
+ for (var $l = 0, $end = rtl.length(A) - 1; $l <= $end; $l++) {
|
|
|
+ I = $l;
|
|
|
+ P = A[I].split("=");
|
|
|
+ N = pas.SysUtils.LowerCase(decodeURIComponent(P[0]));
|
|
|
+ if (rtl.length(P) === 2) {
|
|
|
+ $impl.EnvNames[N] = decodeURIComponent(P[1])}
|
|
|
+ else if (rtl.length(P) === 1) $impl.EnvNames[N] = "";
|
|
|
+ };
|
|
|
+ };
|
|
|
+ $impl.MyGetEnvironmentVariable = function (EnvVar) {
|
|
|
+ var Result = "";
|
|
|
+ var aName = "";
|
|
|
+ aName = pas.SysUtils.LowerCase(EnvVar);
|
|
|
+ if ($impl.EnvNames.hasOwnProperty(aName)) {
|
|
|
+ Result = "" + $impl.EnvNames[aName]}
|
|
|
+ else Result = "";
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ $impl.MyGetEnvironmentVariableCount = function () {
|
|
|
+ var Result = 0;
|
|
|
+ Result = rtl.length(Object.getOwnPropertyNames($impl.EnvNames));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ $impl.MyGetEnvironmentString = function (Index) {
|
|
|
+ var Result = "";
|
|
|
+ Result = "" + $impl.EnvNames[Object.getOwnPropertyNames($impl.EnvNames)[Index]];
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ $mod.$init = function () {
|
|
|
+ $impl.ReloadEnvironmentStrings();
|
|
|
+ pas.SysUtils.OnGetEnvironmentVariable = $impl.MyGetEnvironmentVariable;
|
|
|
+ pas.SysUtils.OnGetEnvironmentVariableCount = $impl.MyGetEnvironmentVariableCount;
|
|
|
+ pas.SysUtils.OnGetEnvironmentString = $impl.MyGetEnvironmentString;
|
|
|
+ };
|
|
|
+},["Types"]);
|
|
|
+rtl.module("program",["System","Classes","wasiworkerthreadhost"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ rtl.createClass(this,"TApplication",pas.wasiworkerthreadhost.TWorkerThreadControllerApplication,function () {
|
|
|
+ });
|
|
|
+ this.App = null;
|
|
|
+ $mod.$main = function () {
|
|
|
+ $mod.App = $mod.TApplication.$create("Create$1",[null]);
|
|
|
+ $mod.App.Run();
|
|
|
+ };
|
|
|
+});
|
|
|
+rtl.run();
|
|
|
+//# sourceMappingURL=wasmthreadcontroller.js.map
|