We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
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
https://github.com/tc39/proposal-promise-allSettled core-js/packages/core-js/modules/es.promise.all-settled.js
https://github.com/tc39/proposal-promise-allSettled
core-js/packages/core-js/modules/es.promise.all-settled.js
function allSettled(iterable) { var C = this; // 创建一个对象,capability属性为 // { // promise : promise实例 // resolve : promise实例resolve函数 // reject : promise实例reject函数 // } var capability = newPromiseCapabilityModule.f(C); var resolve = capability.resolve; var reject = capability.reject; // perform: // function (exec) { // try { // return { error: false, value: exec() }; // } catch (error) { // return { error: true, value: error }; // } // }; // catch掉同步执行的错误,在最后通过reject抛出 var result = perform(function () { var promiseResolve = aCallable(C.resolve); // 存放结果的数组 var values = []; // 对应values索引 var counter = 0; // 剩余几个未完成 var remaining = 1; // 遍历iterable数组,执行第二个参数 iterate(iterable, function (promise) { var index = counter++; // 是否被调用 var alreadyCalled = false; // 每次循环先++ remaining++; // 相当于Promise.resolve(promise).then() call(promiseResolve, C, promise).then(function (value) { if (alreadyCalled) return; alreadyCalled = true; values[index] = { status: 'fulfilled', value: value }; // 如果没有剩余就resolve --remaining || resolve(values); }, function (error) { // then第二个参数,用于捕获reject if (alreadyCalled) return; alreadyCalled = true; values[index] = { status: 'rejected', reason: error }; // 同样的减减操作 --remaining || resolve(values); }); }); // 由于remaining初始是1,所以再次-- --remaining || resolve(values); }); if (result.error) reject(result.value); // 返回promise用于后续链式调用 return capability.promise; }
perform
reject
.then
Promise.all
counter
remaining
capability.reject
https://github.com/tc39/proposal-accessible-object-hasownproperty core-js/packages/core-js/modules/es.object.has-own.js
https://github.com/tc39/proposal-accessible-object-hasownproperty
core-js/packages/core-js/modules/es.object.has-own.js
var uncurryThis = require('../internals/function-uncurry-this'); var toObject = require('../internals/to-object'); var hasOwnProperty = uncurryThis({}.hasOwnProperty); // `HasOwnProperty` abstract operation // https://tc39.es/ecma262/#sec-hasownproperty // eslint-disable-next-line es-x/no-object-hasown -- safe module.exports = Object.hasOwn || function hasOwn(it, key) { return hasOwnProperty(toObject(it), key); };
uncurryThis
hasOwnProperty
https://github.com/tc39/proposal-global core-js/packages/core-js/internals/global.js 很简单,不用注释了
https://github.com/tc39/proposal-global
core-js/packages/core-js/internals/global.js
很简单,不用注释了
var check = function (it) { return it && it.Math == Math && it; }; // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 module.exports = // eslint-disable-next-line es-x/no-global-this -- safe check(typeof globalThis == 'object' && globalThis) || check(typeof window == 'object' && window) || // eslint-disable-next-line no-restricted-globals -- safe check(typeof self == 'object' && self) || check(typeof global == 'object' && global) || // eslint-disable-next-line no-new-func -- fallback (function () { return this; })() || Function('return this')();
https://github.com/tc39/proposal-promise-any core-js/packages/core-js/modules/es.promise.any.js
https://github.com/tc39/proposal-promise-any
core-js/packages/core-js/modules/es.promise.any.js
var PROMISE_ANY_ERROR = 'No one promise resolved'; // `Promise.any` method // https://tc39.es/ecma262/#sec-promise.any $({ target: 'Promise', stat: true }, { any: function any(iterable) { var C = this; var AggregateError = getBuiltIn('AggregateError'); var capability = newPromiseCapabilityModule.f(C); var resolve = capability.resolve; var reject = capability.reject; var result = perform(function () { var promiseResolve = aCallable(C.resolve); var errors = []; var counter = 0; var remaining = 1; var alreadyResolved = false; iterate(iterable, function (promise) { var index = counter++; var alreadyRejected = false; remaining++; call(promiseResolve, C, promise).then(function (value) { if (alreadyRejected || alreadyResolved) return; alreadyResolved = true; // 只要有一个成功就resolve resolve(value); }, function (error) { if (alreadyRejected || alreadyResolved) return; alreadyRejected = true; errors[index] = error; // 全错才会reject --remaining || reject(new AggregateError(errors, PROMISE_ANY_ERROR)); }); }); --remaining || reject(new AggregateError(errors, PROMISE_ANY_ERROR)); }); if (result.error) reject(result.value); return capability.promise; } });
Promise.allSettled
AggregateError
https://github.com/tc39/proposal-relative-indexing-method core-js/packages/core-js/proposals/relative-indexing-method.js 给所有可索引类(Array, String, TypedArray)加上at函数
https://github.com/tc39/proposal-relative-indexing-method
core-js/packages/core-js/proposals/relative-indexing-method.js
给所有可索引类(Array, String, TypedArray)加上at函数
以 Array为例,其余的感兴趣可以自行了解下
Array
// `Array.prototype.at` method // https://github.com/tc39/proposal-relative-indexing-method $({ target: 'Array', proto: true }, { at: function at(index) { var O = toObject(this); var len = lengthOfArrayLike(O); var relativeIndex = toIntegerOrInfinity(index); var k = relativeIndex >= 0 ? relativeIndex : len + relativeIndex; return (k < 0 || k >= len) ? undefined : O[k]; } }); // 设置Symbol.unscopables // addToUnscopables: // function (key) { // ArrayPrototype[UNSCOPABLES][key] = true; // }; // 在with环境中at属性不会暴露,感兴趣可以去查下mdn addToUnscopables('at');
toIntegerOrInfinity:
toIntegerOrInfinity
// `ToIntegerOrInfinity` abstract operation // https://tc39.es/ecma262/#sec-tointegerorinfinity module.exports = function (argument) { var number = +argument; // eslint-disable-next-line no-self-compare -- safe // NaN情况 取靠近0的整数 return number !== number || number === 0 ? 0 : (number > 0 ? floor : ceil)(number); };
https://github.com/tc39/proposal-string-matchall core-js/packages/core-js/modules/es.string.match-all.js
https://github.com/tc39/proposal-string-matchall
core-js/packages/core-js/modules/es.string.match-all.js
var MATCH_ALL = wellKnownSymbol('matchAll'); var REGEXP_STRING = 'RegExp String'; var REGEXP_STRING_ITERATOR = REGEXP_STRING + ' Iterator'; var setInternalState = InternalStateModule.set; var getInternalState = InternalStateModule.getterFor(REGEXP_STRING_ITERATOR); var RegExpPrototype = RegExp.prototype; var TypeError = global.TypeError; var getFlags = uncurryThis(regExpFlags); var stringIndexOf = uncurryThis(''.indexOf); var un$MatchAll = uncurryThis(''.matchAll); // 判断是否可以支持没有全局标志的正则 var WORKS_WITH_NON_GLOBAL_REGEX = !!un$MatchAll && !fails(function () { un$MatchAll('a', /./); }); // 设置正则表达式迭代器 // 篇幅太长不过多解释,大概流程就是: // RegExpStringIterator函数为构造函数,设置构造函数的prototype.__proto__[Symbol.iterator] // 感兴趣可自行查看 var $RegExpStringIterator = createIteratorConstructor(function RegExpStringIterator(regexp, string, $global, fullUnicode) { setInternalState(this, { type: REGEXP_STRING_ITERATOR, regexp: regexp, string: string, global: $global, unicode: fullUnicode, done: false }); }, REGEXP_STRING, function next() { var state = getInternalState(this); if (state.done) return { value: undefined, done: true }; var R = state.regexp; var S = state.string; var match = regExpExec(R, S); if (match === null) return { value: undefined, done: state.done = true }; if (state.global) { if (toString(match[0]) === '') R.lastIndex = advanceStringIndex(S, toLength(R.lastIndex), state.unicode); return { value: match, done: false }; } state.done = true; return { value: match, done: false }; }); var $matchAll = function (string) { // R为正则 var R = anObject(this); // S为被匹配的字符串 var S = toString(string); var C, flagsValue, flags, matcher, $global, fullUnicode; // 拿到构造函数,会通过[Symbol.species]来获取,感兴趣可以看下 C = speciesConstructor(R, RegExp); // 正则标志位 flagsValue = R.flags; // isPrototypeOf(RegExpPrototype, R):断正则的原型是否是RegExp.prototype if (flagsValue === undefined && isPrototypeOf(RegExpPrototype, R) && !('flags' in RegExpPrototype)) { flagsValue = getFlags(R); } flags = flagsValue === undefined ? '' : toString(flagsValue); // R.source值为正则去掉标志符号和两遍的斜杠 matcher = new C(C === RegExp ? R.source : R, flags); // 是否含有g标志 $global = !!~stringIndexOf(flags, 'g'); // 是否含有u标志 fullUnicode = !!~stringIndexOf(flags, 'u'); // lastIndex用来指定下一次匹配的起始索引 matcher.lastIndex = toLength(R.lastIndex); return new $RegExpStringIterator(matcher, S, $global, fullUnicode); }; // `String.prototype.matchAll` method // https://tc39.es/ecma262/#sec-string.prototype.matchall $({ target: 'String', proto: true, forced: WORKS_WITH_NON_GLOBAL_REGEX }, { // 入口,从这块开始看 matchAll: function matchAll(regexp) { // 检查this是否是undefined var O = requireObjectCoercible(this); var flags, S, matcher, rx; if (regexp != null) { // 如果有参数 if (isRegExp(regexp)) { // 参数是一个正则 // 判断'flags'属性是否存在于RegExp.prototype中 // flags属性返回一个字符串,由当前正则表达式对象的标志组成。 flags = toString(requireObjectCoercible('flags' in RegExpPrototype ? regexp.flags // 同样是获取标志,只不过是通过判断global,ignoreCase等属性,有兴趣可自行了解 : getFlags(regexp) )); // 如果正则中未含有g标记,报错 if (!~stringIndexOf(flags, 'g')) throw TypeError('`.matchAll` does not allow non-global regexes'); } if (WORKS_WITH_NON_GLOBAL_REGEX) return un$MatchAll(O, regexp); // 相当于regexp[Symbol.matchAll] matcher = getMethod(regexp, MATCH_ALL); // 如果matcher为undefined && PURE模式 && regexp为正则 if (matcher === undefined && IS_PURE && classof(regexp) == 'RegExp') matcher = $matchAll; if (matcher) return call(matcher, regexp, O); // 同样判断是否支持 没有全局标志的正则的matchAll函数 } else if (WORKS_WITH_NON_GLOBAL_REGEX) return un$MatchAll(O, regexp); // 走到此处有几种情况,例如 // regexp===null && WORKS_WITH_NON_GLOBAL_REGEX===false // regexp不为正则 // 等 S = toString(O); rx = new RegExp(regexp, 'g'); return IS_PURE ? call($matchAll, rx, S) : rx[MATCH_ALL](S); } });
在设置迭代器的时候是这么设置的
// 简写 // 通常写法: { [Symbole.iterator]=function(){ return { next(){.....} } }, } // corejs中是这么写的 { [Symbole.iterator]=function(){ return this }, next:function next(){} }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
promise.all-settled
perform
函数捕获同步错误,最后通过reject
抛出.then
第二个入参Promise.all
源码很类似,都是通过counter
对应结果数组索引remaining
对应未完成数量,不同在于前者.then
第二个入参为capability.reject
accessible-object-hasownproperty
uncurryThis
包装hasOwnProperty
globalThis
Promise.any
Promise.allSettled
逻辑非常相似,不同的是注释的地方,逻辑不同AggregateError
是一种错误类型,可以多种错误包含在一起,感兴趣可以去了解下mdnrelative-indexing-method
以
Array
为例,其余的感兴趣可以自行了解下toIntegerOrInfinity
:String.prototype.matchAll
在设置迭代器的时候是这么设置的
The text was updated successfully, but these errors were encountered: