diff --git a/CHANGELOG.md b/CHANGELOG.md index 299acace330f..78b61ddb4ccf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Changelog ##### Unreleased - Fixed the order of calling reactions of already fulfilled / rejected promises in `Promise.prototype.then`, [#1026](https://github.com/zloirock/core-js/issues/1026) +- Fixed possible memory leaking in specific promise chains - Fixed some missed dependencies of entries - Added Deno 1.18 compat data mapping diff --git a/packages/core-js/internals/queue.js b/packages/core-js/internals/queue.js new file mode 100644 index 000000000000..2137d0603e34 --- /dev/null +++ b/packages/core-js/internals/queue.js @@ -0,0 +1,23 @@ +var Queue = function () { + this.head = null; + this.tail = null; +}; + +Queue.prototype = { + add: function (item) { + var entry = { item: item, next: null }; + if (this.head) this.tail.next = entry; + else this.head = entry; + this.tail = entry; + }, + get: function () { + var entry = this.head; + if (entry) { + this.head = entry.next; + if (this.tail === entry) this.tail = null; + return entry.item; + } + } +}; + +module.exports = Queue; diff --git a/packages/core-js/modules/es.promise.js b/packages/core-js/modules/es.promise.js index fc7ad03f1558..9541ac54a544 100644 --- a/packages/core-js/modules/es.promise.js +++ b/packages/core-js/modules/es.promise.js @@ -4,7 +4,6 @@ var IS_PURE = require('../internals/is-pure'); var global = require('../internals/global'); var getBuiltIn = require('../internals/get-built-in'); var call = require('../internals/function-call'); -var uncurryThis = require('../internals/function-uncurry-this'); var NativePromise = require('../internals/native-promise-constructor'); var redefine = require('../internals/redefine'); var redefineAll = require('../internals/redefine-all'); @@ -25,6 +24,7 @@ var promiseResolve = require('../internals/promise-resolve'); var hostReportErrors = require('../internals/host-report-errors'); var newPromiseCapabilityModule = require('../internals/new-promise-capability'); var perform = require('../internals/perform'); +var Queue = require('../internals/queue'); var InternalStateModule = require('../internals/internal-state'); var isForced = require('../internals/is-forced'); var wellKnownSymbol = require('../internals/well-known-symbol'); @@ -44,7 +44,6 @@ var PromisePrototype = NativePromisePrototype; var TypeError = global.TypeError; var document = global.document; var process = global.process; -var push = uncurryThis([].push); var newPromiseCapability = newPromiseCapabilityModule.f; var newGenericPromiseCapability = newPromiseCapability; @@ -136,13 +135,11 @@ var notify = function (state, isReject) { if (state.notified) return; state.notified = true; microtask(function () { - var chain = state.reactions; - var index = 0; - // variable length - can't use forEach - while (chain.length > index) { - callReaction(chain[index++], state); + var reactions = state.reactions; + var reaction; + while (reaction = reactions.get()) { + callReaction(reaction, state); } - state.reactions = []; state.notified = false; if (isReject && !state.rejection) onUnhandled(state); }); @@ -259,7 +256,7 @@ if (FORCED) { done: false, notified: false, parent: false, - reactions: [], + reactions: new Queue(), rejection: false, state: PENDING, value: undefined @@ -275,7 +272,7 @@ if (FORCED) { reaction.ok = isCallable(onFulfilled) ? onFulfilled : true; reaction.fail = isCallable(onRejected) && onRejected; reaction.domain = IS_NODE ? process.domain : undefined; - if (state.state == PENDING) push(state.reactions, reaction); + if (state.state == PENDING) state.reactions.add(reaction); else microtask(function () { callReaction(reaction, state); });