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:
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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; }
|
||||||
Reference in New Issue
Block a user