Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(promise): don't include the promise rejection tracker hook in the bytecode #1162

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
212 changes: 46 additions & 166 deletions lib/InternalBytecode/01-Promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,16 @@
if (typeof fn !== 'function') {
throw new TypeError('Promise constructor\'s argument is not a function');
}
this._h = 0;
this._i = 0;
this._j = null;
this._k = null;
this._x = 0;
this._y = 0;
this._z = null;
this._A = null;
if (fn === noop) return;
doResolve(fn, this);
}
Promise._l = null;
Promise._m = null;
Promise._n = noop;
Promise._B = null;
Promise._C = null;
Promise._D = noop;

Promise.prototype.then = function(onFulfilled, onRejected) {
if (this.constructor !== Promise) {
Expand All @@ -85,41 +85,41 @@
});
}
function handle(self, deferred) {
while (self._i === 3) {
self = self._j;
while (self._y === 3) {
self = self._z;
}
if (Promise._l) {
Promise._l(self);
if (Promise._B) {
Promise._B(self);
}
if (self._i === 0) {
if (self._h === 0) {
self._h = 1;
self._k = deferred;
if (self._y === 0) {
if (self._x === 0) {
self._x = 1;
self._A = deferred;
return;
}
if (self._h === 1) {
self._h = 2;
self._k = [self._k, deferred];
if (self._x === 1) {
self._x = 2;
self._A = [self._A, deferred];
return;
}
self._k.push(deferred);
self._A.push(deferred);
return;
}
handleResolved(self, deferred);
}

function handleResolved(self, deferred) {
(useEngineQueue ? HermesInternal.enqueueJob : setImmediate)(function() {
var cb = self._i === 1 ? deferred.onFulfilled : deferred.onRejected;
var cb = self._y === 1 ? deferred.onFulfilled : deferred.onRejected;
if (cb === null) {
if (self._i === 1) {
resolve(deferred.promise, self._j);
if (self._y === 1) {
resolve(deferred.promise, self._z);
} else {
reject(deferred.promise, self._j);
reject(deferred.promise, self._z);
}
return;
}
var ret = tryCallOne(cb, self._j);
var ret = tryCallOne(cb, self._z);
if (ret === IS_ERROR) {
reject(deferred.promise, LAST_ERROR);
} else {
Expand Down Expand Up @@ -147,38 +147,38 @@
then === self.then &&
newValue instanceof Promise
) {
self._i = 3;
self._j = newValue;
self._y = 3;
self._z = newValue;
finale(self);
return;
} else if (typeof then === 'function') {
doResolve(then.bind(newValue), self);
return;
}
}
self._i = 1;
self._j = newValue;
self._y = 1;
self._z = newValue;
finale(self);
}

function reject(self, newValue) {
self._i = 2;
self._j = newValue;
if (Promise._m) {
Promise._m(self, newValue);
self._y = 2;
self._z = newValue;
if (Promise._C) {
Promise._C(self, newValue);
}
finale(self);
}
function finale(self) {
if (self._h === 1) {
handle(self, self._k);
self._k = null;
if (self._x === 1) {
handle(self, self._A);
self._A = null;
}
if (self._h === 2) {
for (var i = 0; i < self._k.length; i++) {
handle(self, self._k[i]);
if (self._x === 2) {
for (var i = 0; i < self._A.length; i++) {
handle(self, self._A[i]);
}
self._k = null;
self._A = null;
}
}

Expand Down Expand Up @@ -227,9 +227,9 @@
var EMPTYSTRING = valuePromise('');

function valuePromise(value) {
var p = new core(core._n);
p._i = 1;
p._j = value;
var p = new core(core._D);
p._y = 1;
p._z = value;
return p;
}
core.resolve = function (value) {
Expand Down Expand Up @@ -278,11 +278,11 @@
function res(i, val) {
if (val && (typeof val === 'object' || typeof val === 'function')) {
if (val instanceof core && val.then === core.prototype.then) {
while (val._i === 3) {
val = val._j;
while (val._y === 3) {
val = val._z;
}
if (val._i === 1) return res(i, val._j);
if (val._i === 2) reject(val._j);
if (val._y === 1) return res(i, val._z);
if (val._y === 2) reject(val._z);
val.then(function (val) {
res(i, val);
}, reject);
Expand Down Expand Up @@ -408,121 +408,6 @@
});
};

var DEFAULT_WHITELIST = [
ReferenceError,
TypeError,
RangeError
];

var enabled = false;
var disable_1 = disable;
function disable() {
enabled = false;
core._l = null;
core._m = null;
}

var enable_1 = enable;
function enable(options) {
options = options || {};
if (enabled) disable();
enabled = true;
var id = 0;
var displayId = 0;
var rejections = {};
core._l = function (promise) {
if (
promise._i === 2 && // IS REJECTED
rejections[promise._o]
) {
if (rejections[promise._o].logged) {
onHandled(promise._o);
} else {
clearTimeout(rejections[promise._o].timeout);
}
delete rejections[promise._o];
}
};
core._m = function (promise, err) {
if (promise._h === 0) { // not yet handled
promise._o = id++;
rejections[promise._o] = {
displayId: null,
error: err,
timeout: setTimeout(
onUnhandled.bind(null, promise._o),
// For reference errors and type errors, this almost always
// means the programmer made a mistake, so log them after just
// 100ms
// otherwise, wait 2 seconds to see if they get handled
matchWhitelist(err, DEFAULT_WHITELIST)
? 100
: 2000
),
logged: false
};
}
};
function onUnhandled(id) {
if (
options.allRejections ||
matchWhitelist(
rejections[id].error,
options.whitelist || DEFAULT_WHITELIST
)
) {
rejections[id].displayId = displayId++;
if (options.onUnhandled) {
rejections[id].logged = true;
options.onUnhandled(
rejections[id].displayId,
rejections[id].error
);
} else {
rejections[id].logged = true;
logError(
rejections[id].displayId,
rejections[id].error
);
}
}
}
function onHandled(id) {
if (rejections[id].logged) {
if (options.onHandled) {
options.onHandled(rejections[id].displayId, rejections[id].error);
} else if (!rejections[id].onUnhandled) {
console.warn(
'Promise Rejection Handled (id: ' + rejections[id].displayId + '):'
);
console.warn(
' This means you can ignore any previous messages of the form "Possible Unhandled Promise Rejection" with id ' +
rejections[id].displayId + '.'
);
}
}
}
}

function logError(id, error) {
console.warn('Possible Unhandled Promise Rejection (id: ' + id + '):');
var errStr = (error && (error.stack || error)) + '';
errStr.split('\n').forEach(function (line) {
console.warn(' ' + line);
});
}

function matchWhitelist(error, list) {
return list.some(function (cls) {
return error instanceof cls;
});
}

var rejectionTracking = {
disable: disable_1,
enable: enable_1
};

// @nolint
// This file is used to generate InternalBytecode/Promise.js
// See InternalBytecode/README.md for more details.
Expand All @@ -534,11 +419,6 @@
// expose Promise to global.
globalThis.Promise = es6Extensions;

// register the JavaScript implemented `enable` function into
// the Hermes' internal promise rejection tracker.
var enableHook = rejectionTracking.enable;
HermesInternal?.setPromiseRejectionTrackingHook?.(enableHook);

var promise = {

};
Expand Down
5 changes: 0 additions & 5 deletions utils/promise/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,3 @@ require('promise/setimmediate/finally');

// expose Promise to global.
globalThis.Promise = Promise;

// register the JavaScript implemented `enable` function into
// the Hermes' internal promise rejection tracker.
var enableHook = require('promise/setimmediate/rejection-tracking').enable
HermesInternal?.setPromiseRejectionTrackingHook?.(enableHook);