从Google V8引擎剖析Promise实现 本文阅读的源码为Google V8 Engine v3.29.45,此版本的promise实现为js版本,在后续版本Google继续对其实现进行了处理。引入了es6语法等,在7.X版本迭代后,逐渐迭代成了C版本实现。 贴上源码地址:https://chromium.googlesource... 大家自觉传送。
代码中所有类似%functionName的函数均是C语言实现的运行时函数。
Define variables首先定义了将要在JS作用域使用了一些变量,提高了编译器的效率。
var IsPromise;var PromiseCreate;var PromiseResolve;var PromiseReject;var PromiseChain;var PromiseCatch;var PromiseThen;var PromiseHasRejectHandler;随后定义了一些全局私有变量供给和C语音交互,用于维护Promise的状态和进行Debug。
var promiseStatus = GLOBAL_PRIVATE("Promise#status");var promiseValue = GLOBAL_PRIVATE("Promise#value");var promiseOnResolve = GLOBAL_PRIVATE("Promise#onResolve");var promiseOnReject = GLOBAL_PRIVATE("Promise#onReject");var promiseRaw = GLOBAL_PRIVATE("Promise#raw");var promiseDebug = GLOBAL_PRIVATE("Promise#debug");var lastMicrotaskId = 0;其中GLOBAL_PRIVATE是python进行实现的,运用python的宏定义(macro)来定义调用了C语言的CreateGlobalPrivateOwnSymbol方法。
macro GLOBAL_PRIVATE(name) = (%CreateGlobalPrivateOwnSymbol(name));随后运用了一个自执行的匿名函数进行闭包逻辑。
(function() { // 主逻辑})();在闭包逻辑的最后,在promise原型上挂载了三个方法:chain,then,catch。在promise对象上挂载了all,race等六个方法。将Promise对象注册到了global。
%AddNamedProperty(global, 'Promise', $Promise, DONT_ENUM);InstallFunctions($Promise, DONT_ENUM, [ "defer", PromiseDeferred, "accept", PromiseResolved, "reject", PromiseRejected, "all", PromiseAll, "race", PromiseOne, "resolve", PromiseCast]);InstallFunctions($Promise.prototype, DONT_ENUM, [ "chain", PromiseChain, "then", PromiseThen, "catch", PromiseCatch]);Start from constructorvar $Promise = function Promise(resolver) { // 如果传入参数为全局promiseRaw变量的时候return if (resolver === promiseRaw) return; // 如果当前函数不是构造函数的化,抛出错误这不是一个promise if (!%_IsConstructCall()) throw MakeTypeError('not_a_promise', [this]); // 如果传入参数不是一个函数的话,抛出错误,传入参数不是一个function if (!IS_SPEC_FUNCTION(resolver)) throw MakeTypeError('resolver_not_a_function', [resolver]); var promise = PromiseInit(this); try { // debug相关忽略 %DebugPushPromise(promise); resolver(function(x) { PromiseResolve(promise, x) }, function(r) { PromiseReject(promise, r) }); } catch (e) { // 报错之后走到错误处理函数 PromiseReject(promise, e); } finally { // debug相关忽略 %DebugPopPromise(); }}构造函数在做完额外的异常和参数判断后,进入主逻辑调用PromiseInit方法初始化promise,随后调用了resolver方法,传入了两个默认的处理函数。在promise在内部被调用时(PromiseDeferred方法被调用时)会实例化$promise,将默认方法return回去,使得创建的promise示例具有resolve和reject方法。
...