1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-15 07:43:50 +00:00

1. Merged GC optimization for promise.js

2. Fixed crash that can occur if dgram is GC'ed during event dispatch
3. Fixed compiler warning in ILibWebClient.c
4. Updated GC for dhcp.js
This commit is contained in:
Bryan Roe
2021-07-17 11:32:25 -07:00
parent 980005b40b
commit c7a4356dac
5 changed files with 152 additions and 96 deletions

View File

@@ -103,8 +103,9 @@ void ILibDuktape_Dgram_Socket_OnData(ILibAsyncUDPSocket_SocketModule socketModul
duk_push_int(ptrs->ctx, bufferLength); duk_push_int(ptrs->ctx, bufferLength);
duk_put_prop_string(ptrs->ctx, -2, "size"); duk_put_prop_string(ptrs->ctx, -2, "size");
duk_context *X = ptrs->ctx;
if (duk_pcall_method(ptrs->ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "dgram.message() dispatch error"); } if (duk_pcall_method(ptrs->ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "dgram.message() dispatch error"); }
duk_pop(ptrs->ctx); // ... duk_pop(X); // ...
} }
} }
void ILibDuktape_Dgram_Socket_OnSendOK(ILibAsyncUDPSocket_SocketModule socketModule, void *user1, void *user2) void ILibDuktape_Dgram_Socket_OnSendOK(ILibAsyncUDPSocket_SocketModule socketModule, void *user1, void *user2)

File diff suppressed because one or more lines are too long

View File

@@ -2328,8 +2328,8 @@ void ILibWebClient_PreProcess(void* WebClientModule, fd_set *readset, fd_set *wr
NULL, NULL,
wcdo->proxy_remoteHostAndPort, wcdo->proxy_remoteHostAndPort,
(struct sockaddr*)&wcdo->proxy, (struct sockaddr*)&wcdo->proxy,
wcdo->proxy_username[0]==NULL?NULL:wcdo->proxy_username, wcdo->proxy_username[0]==0?NULL:wcdo->proxy_username,
wcdo->proxy_password[0]==NULL?NULL:wcdo->proxy_password, wcdo->proxy_password[0]==0?NULL:wcdo->proxy_password,
ILibWebClient_OnInterrupt, ILibWebClient_OnInterrupt,
wcdo); wcdo);
} }

View File

@@ -193,9 +193,7 @@ function createPacket(messageType, data)
function raw(localAddress, port, buffer, handler) function raw(localAddress, port, buffer, handler)
{ {
var ret = new promise(promise_default); var ret = new promise(promise_default);
ret.handler = handler;
ret.socket = require('dgram').createSocket({ type: 'udp4' }); ret.socket = require('dgram').createSocket({ type: 'udp4' });
ret.socket.promise = ret;
try try
{ {
ret.socket.bind({ address: localAddress, port: (port != null && port != 0) ? port : null }); ret.socket.bind({ address: localAddress, port: (port != null && port != 0) ? port : null });
@@ -205,6 +203,7 @@ function raw(localAddress, port, buffer, handler)
ret._rej('Unable to bind to ' + localAddress); ret._rej('Unable to bind to ' + localAddress);
return (ret); return (ret);
} }
ret.socket.setBroadcast(true); ret.socket.setBroadcast(true);
ret.socket.setMulticastInterface(localAddress); ret.socket.setMulticastInterface(localAddress);
ret.socket.setMulticastTTL(1); ret.socket.setMulticastTTL(1);
@@ -213,6 +212,7 @@ function raw(localAddress, port, buffer, handler)
ret.socket.send(buffer, 67, '255.255.255.255'); ret.socket.send(buffer, 67, '255.255.255.255');
return (ret); return (ret);
} }
function info(interfaceName, port) function info(interfaceName, port)
{ {
var f = require('os').networkInterfaces(); var f = require('os').networkInterfaces();
@@ -226,18 +226,23 @@ function info(interfaceName, port)
try try
{ {
var b = createPacket(8, { ciaddress: f[interfaceName][i].address, chaddress: f[interfaceName][i].mac }); var b = createPacket(8, { ciaddress: f[interfaceName][i].address, chaddress: f[interfaceName][i].mac });
var p = raw(f[interfaceName][i].address, port, b, function infoHandler(msg) _hide(raw(f[interfaceName][i].address, port, b, function infoHandler(msg)
{ {
var res = parseDHCP(msg); var res = parseDHCP(msg);
if (res.chaddr.toUpperCase() == this.hwaddr.toUpperCase() && res.options != null && res.options.lease != null) if (res.chaddr.toUpperCase() == this.hwaddr.toUpperCase() && res.options != null && res.options.lease != null)
{ {
clearTimeout(this.timeout); clearTimeout(this.timeout);
setImmediate(function (s) { s.removeAllListeners('message'); }, this.socket); // Works around bug in older dgram.js
this._res(res); this._res(res);
} }
}); }));
p.hwaddr = f[interfaceName][i].mac; _hide().hwaddr = f[interfaceName][i].mac;
p.timeout = setTimeout(function (x) { x._rej('timeout'); }, 2000, p); _hide().timeout = setTimeout(function (x)
return (p); {
x.socket.removeAllListeners('message');
x._rej('timeout');
}, 2000, _hide());
return (_hide(true));
} }
catch(e) catch(e)
{ {

View File

@@ -16,6 +16,12 @@ limitations under the License.
var refTable = {}; var refTable = {};
function promiseInitializer(r,j)
{
this._res = r;
this._rej = j;
}
function getRootPromise(obj) function getRootPromise(obj)
{ {
while(obj.parentPromise) while(obj.parentPromise)
@@ -25,39 +31,39 @@ function getRootPromise(obj)
return (obj); return (obj);
} }
function event_switcher_helper(desired_callee, target, forward)
{
this._ObjectID = 'event_switcher';
this.func = function func()
{
var args = [];
if (func.forward != null) { args.push(func.forward); }
for(var i in arguments)
{
args.push(arguments[i]);
}
return (func.target.apply(func.desired, args));
};
this.func.desired = desired_callee;
this.func.target = target;
this.func.forward = forward;
this.func.self = this;
}
function event_switcher(desired_callee, target) function event_switcher(desired_callee, target)
{ {
return (new event_switcher_helper(desired_callee, target)); return ({ _ObjectID: 'event_switcher', func: target.bind(desired_callee) });
} }
function event_forwarder(sourceObj, sourceName, targetObj, targetName) function event_forwarder(sourceObj, sourceName, targetObj, targetName)
{ {
sourceObj.on(sourceName, (new event_switcher_helper(targetObj, targetObj.emit, targetName)).func); sourceObj.on(sourceName, targetObj.emit.bind(targetObj));
} }
function return_resolved()
{
var parms = ['resolved'];
for (var ai in arguments)
{
parms.push(arguments[ai]);
}
this._XSLF.emit.apply(this._XSLF, parms);
}
function return_rejected()
{
this._XSLF.promise.__childPromise._rej(e);
}
function emitreject(a)
{
process.emit('uncaughtException', 'promise.uncaughtRejection: ' + JSON.stringify(a));
}
function Promise(promiseFunc) function Promise(promiseFunc)
{ {
this._ObjectID = 'promise'; this._ObjectID = 'promise';
this.promise = this; this.promise = this;
this._internal = { _ObjectID: 'promise.internal', promise: this, func: promiseFunc, completed: false, errors: false, completedArgs: [], internalCount: 0, _up: null }; this._internal = { _ObjectID: 'promise.internal', promise: this, completed: false, errors: false, completedArgs: [], internalCount: 0, _up: null };
require('events').EventEmitter.call(this._internal); require('events').EventEmitter.call(this._internal);
Object.defineProperty(this, "parentPromise", Object.defineProperty(this, "parentPromise",
{ {
@@ -76,10 +82,22 @@ function Promise(promiseFunc)
this._up = value; this._up = value;
} }
}); });
Object.defineProperty(this, "descriptorMetadata",
{
get: function ()
this._internal.on('newListener', function (eventName, eventCallback) {
return (require('events').getProperty.call(this._internal, '?_FinalizerDebugMessage'));
},
set: function (value)
{
require('events').setProperty.call(this._internal, '?_FinalizerDebugMessage', value);
}
});
this._internal.on('~', function ()
{
this.completedArgs = [];
});
this._internal.on('newListener2', (function (eventName, eventCallback)
{ {
//console.log('newListener', eventName, 'errors/' + this.errors + ' completed/' + this.completed); //console.log('newListener', eventName, 'errors/' + this.errors + ' completed/' + this.completed);
var r = null; var r = null;
@@ -91,9 +109,12 @@ function Promise(promiseFunc)
{ {
this.emit_returnValue('resolved', r); this.emit_returnValue('resolved', r);
} }
this.removeAllListeners('resolved');
this.removeAllListeners('rejected');
} }
if (eventName == 'rejected' && (eventCallback.internal == null || eventCallback.internal == false)) //if (eventName == 'rejected' && (eventCallback.internal == null || eventCallback.internal == false))
if (eventName == 'rejected')
{ {
var rp = getRootPromise(this.promise); var rp = getRootPromise(this.promise);
rp._internal.external = true; rp._internal.external = true;
@@ -112,101 +133,100 @@ function Promise(promiseFunc)
if (eventName == 'rejected' && this.errors && this.completed) if (eventName == 'rejected' && this.errors && this.completed)
{ {
eventCallback.apply(this, this.completedArgs); eventCallback.apply(this, this.completedArgs);
this.removeAllListeners('resolved');
this.removeAllListeners('rejected');
} }
if (eventName == 'settled' && this.completed) if (eventName == 'settled' && this.completed)
{ {
eventCallback.apply(this, []); eventCallback.apply(this, []);
} }
}); }).internal);
this._internal.resolver = function _resolver() this._internal.resolver = function _resolver()
{ {
if (_resolver._self.completed) { return; } if (this.completed) { return; }
_resolver._self.errors = false; this.errors = false;
_resolver._self.completed = true; this.completed = true;
_resolver._self.completedArgs = []; this.completedArgs = [];
var args = ['resolved']; var args = ['resolved'];
if (this.emit_returnValue && this.emit_returnValue('resolved') != null) if (this.emit_returnValue && this.emit_returnValue('resolved') != null)
{ {
_resolver._self.completedArgs.push(this.emit_returnValue('resolved')); this.completedArgs.push(this.emit_returnValue('resolved'));
args.push(this.emit_returnValue('resolved')); args.push(this.emit_returnValue('resolved'));
} }
else else
{ {
for (var a in arguments) for (var a in arguments)
{ {
_resolver._self.completedArgs.push(arguments[a]); this.completedArgs.push(arguments[a]);
args.push(arguments[a]); args.push(arguments[a]);
} }
} }
if (args.length == 2 && args[1]!=null && typeof(args[1]) == 'object' && args[1]._ObjectID == 'promise') if (args.length == 2 && args[1]!=null && typeof(args[1]) == 'object' && args[1]._ObjectID == 'promise')
{ {
var pr = getRootPromise(_resolver._self.promise); var pr = getRootPromise(this.promise);
args[1]._XSLF = _resolver._self; args[1]._XSLF = this;
args[1].then(function _returnResolved() args[1].then(return_resolved, return_rejected);
{
var parms = ['resolved'];
for (var ai in arguments)
{
parms.push(arguments[ai]);
}
this._XSLF.emit.apply(this._XSLF, parms);
},
function _returnRejected(e)
{
this._XSLF.promise.__childPromise._rej(e);
});
} }
else else
{ {
_resolver._self.emit.apply(_resolver._self, args); this.emit.apply(this, args);
_resolver._self.emit('settled'); this.emit('settled');
} }
}; };
this._internal.rejector = function _rejector() this._internal.rejector = function _rejector()
{ {
if (_rejector._self.completed) { return; } if (this.completed) { return; }
_rejector._self.errors = true; this.errors = true;
_rejector._self.completed = true; this.completed = true;
_rejector._self.completedArgs = []; this.completedArgs = [];
var args = ['rejected']; var args = ['rejected'];
for (var a in arguments) for (var a in arguments)
{ {
_rejector._self.completedArgs.push(arguments[a]); this.completedArgs.push(arguments[a]);
args.push(arguments[a]); args.push(arguments[a]);
} }
var r = getRootPromise(_rejector._self.promise); var r = getRootPromise(this.promise);
if ((r._internal.external == null || r._internal.external == false) && r._internal.uncaught == null) if ((r._internal.external == null || r._internal.external == false) && r._internal.uncaught == null)
{ {
r._internal.uncaught = setImmediate(function (a) r._internal.uncaught = setImmediate(emitreject, arguments[0]);
{
process.emit('uncaughtException', 'promise.uncaughtRejection: ' + JSON.stringify(a));
}, arguments[0]);
} }
_rejector._self.emit.apply(_rejector._self, args); this.emit.apply(this, args);
_rejector._self.emit('settled'); this.emit('settled');
}; };
this._internal.rejector.internal = true;
this.catch = function(func) this.catch = function(func)
{ {
var rt = getRootPromise(this); var rt = getRootPromise(this);
this._internal.once('rejected', event_switcher(this, func).func); if (rt._internal.uncaught != null) { clearImmediate(rt._internal.uncaught); }
this._internal.once('rejected', event_switcher(this, func).func.internal);
} }
this.finally = function (func) this.finally = function (func)
{ {
this._internal.once('settled', event_switcher(this, func).func); this._internal.once('settled', event_switcher(this, func).func.internal);
}; };
this.then = function (resolved, rejected) this.then = function (resolved, rejected)
{ {
if (resolved) { this._internal.once('resolved', event_switcher(this, resolved).func); } if (resolved)
{
this._internal.once('resolved', event_switcher(this, resolved).func.internal);
}
if (rejected) if (rejected)
{ {
this._internal.once('rejected', event_switcher(this, rejected).func); if (this._internal.completed)
{
var r = getRootPromise(this);
if(r._internal.uncaught != null)
{
clearImmediate(r._internal.uncaught);
}
}
this._internal.once('rejected', event_switcher(this, rejected).func.internal);
} }
var retVal = new Promise(function (r, j) { this._rej = j; }); var retVal = new Promise(promiseInitializer);
retVal.parentPromise = this; retVal.parentPromise = this;
if (this._internal.completed) if (this._internal.completed)
@@ -218,37 +238,35 @@ function Promise(promiseFunc)
if(rv._ObjectID == 'promise') if(rv._ObjectID == 'promise')
{ {
rv.parentPromise = this; rv.parentPromise = this;
rv._internal.once('resolved', retVal._internal.resolver); rv._internal.once('resolved', retVal._internal.resolver.bind(retVal._internal).internal);
rv._internal.once('rejected', retVal._internal.rejector); rv._internal.once('rejected', retVal._internal.rejector.bind(retVal._internal).internal);
} }
else else
{ {
retVal._internal.resolver(rv); retVal._internal.resolver.call(retVal._internal, rv);
} }
} }
else else
{ {
this._internal.once('resolved', retVal._internal.resolver); this._internal.once('resolved', retVal._internal.resolver.bind(retVal._internal).internal);
this._internal.once('rejected', retVal._internal.rejector); this._internal.once('rejected', retVal._internal.rejector.bind(retVal._internal).internal);
} }
} }
else else
{ {
this._internal.once('resolved', retVal._internal.resolver); this._internal.once('resolved', retVal._internal.resolver.bind(retVal._internal).internal);
this._internal.once('rejected', retVal._internal.rejector); this._internal.once('rejected', retVal._internal.rejector.bind(retVal._internal).internal);
} }
this.__childPromise = retVal;
return (retVal);
};
this._internal.resolver._self = this._internal; this.__childPromise = retVal;
this._internal.rejector._self = this._internal;; return(retVal);
};
try try
{ {
promiseFunc.call(this, this._internal.resolver, this._internal.rejector); promiseFunc.call(this, this._internal.resolver.bind(this._internal), this._internal.rejector.bind(this._internal));
} }
catch(e) catch (e)
{ {
this._internal.errors = true; this._internal.errors = true;
this._internal.completed = true; this._internal.completed = true;
@@ -261,7 +279,10 @@ function Promise(promiseFunc)
{ {
// Save reference of this object // Save reference of this object
refTable[this._internal._hashCode()] = this._internal; refTable[this._internal._hashCode()] = this._internal;
this._internal.once('settled', function () { delete refTable[this._hashCode()]; }); this._internal.once('settled', function ()
{
delete refTable[this._hashCode()];
});
} }
Object.defineProperty(this, "completed", { Object.defineProperty(this, "completed", {
get: function () get: function ()
@@ -269,6 +290,19 @@ function Promise(promiseFunc)
return (this._internal.completed); return (this._internal.completed);
} }
}); });
this._internal.once('settled', (function ()
{
delete this.promise._up;
delete this.promise.__childPromise;
delete this.promise.promise;
delete this._up;
delete this.__childPromise;
delete this.promise;
this.removeAllListeners('resolved');
this.removeAllListeners('rejected');
}).internal);
} }
Promise.resolve = function resolve() Promise.resolve = function resolve()
@@ -332,3 +366,4 @@ Promise.all = function all(promiseList)
module.exports = Promise; module.exports = Promise;
module.exports.event_switcher = event_switcher; module.exports.event_switcher = event_switcher;
module.exports.event_forwarder = event_forwarder; module.exports.event_forwarder = event_forwarder;
module.exports.defaultInit = function defaultInit(res, rej) { this.resolve = res; this.reject = rej; }