regeneratorRuntime 运行环境配置
注意710行与711行有做变更,代码来源于babel官网
https://babeljs.io/docs/en/learn
https://babeljs.io/repl
/*** Copyright (c) 2014-present, Facebook, Inc.** This source code is licensed under the MIT license found in the* LICENSE file in the root directory of this source tree.*/var runtime = (function (exports) {"use strict";var Op = Object.prototype;var hasOwn = Op.hasOwnProperty;var undefined; // More compressible than void 0.var $Symbol = typeof Symbol === "function" ? Symbol : {};var iteratorSymbol = $Symbol.iterator || "@@iterator";var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";function wrap(innerFn, outerFn, self, tryLocsList) {// If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;var generator = Object.create(protoGenerator.prototype);var context = new Context(tryLocsList || []);// The ._invoke method unifies the implementations of the .next,// .throw, and .return methods.generator._invoke = makeInvokeMethod(innerFn, self, context);return generator;}exports.wrap = wrap;// Try/catch helper to minimize deoptimizations. Returns a completion// record like context.tryEntries[i].completion. This interface could// have been (and was previously) designed to take a closure to be// invoked without arguments, but in all the cases we care about we// already have an existing method we want to call, so there's no need// to create a new function object. We can even get away with assuming// the method takes exactly one argument, since that happens to be true// in every case, so we don't have to touch the arguments object. The// only additional allocation required is the completion record, which// has a stable shape and so hopefully should be cheap to allocate.function tryCatch(fn, obj, arg) {try {return { type: "normal", arg: fn.call(obj, arg) };} catch (err) {return { type: "throw", arg: err };}}var GenStateSuspendedStart = "suspendedStart";var GenStateSuspendedYield = "suspendedYield";var GenStateExecuting = "executing";var GenStateCompleted = "completed";// Returning this object from the innerFn has the same effect as// breaking out of the dispatch switch statement.var ContinueSentinel = {};// Dummy constructor functions that we use as the .constructor and// .constructor.prototype properties for functions that return Generator// objects. For full spec compliance, you may wish to configure your// minifier not to mangle the names of these two functions.function Generator() {}function GeneratorFunction() {}function GeneratorFunctionPrototype() {}// This is a polyfill for %IteratorPrototype% for environments that// don't natively support it.var IteratorPrototype = {};IteratorPrototype[iteratorSymbol] = function () {return this;};var getProto = Object.getPrototypeOf;var NativeIteratorPrototype = getProto && getProto(getProto(values([])));if (NativeIteratorPrototype &&NativeIteratorPrototype !== Op &&hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {// This environment has a native %IteratorPrototype%; use it instead// of the polyfill.IteratorPrototype = NativeIteratorPrototype;}var Gp = GeneratorFunctionPrototype.prototype =Generator.prototype = Object.create(IteratorPrototype);GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;GeneratorFunctionPrototype.constructor = GeneratorFunction;GeneratorFunctionPrototype[toStringTagSymbol] =GeneratorFunction.displayName = "GeneratorFunction";// Helper for defining the .next, .throw, and .return methods of the// Iterator interface in terms of a single ._invoke method.function defineIteratorMethods(prototype) {["next", "throw", "return"].forEach(function(method) {prototype[method] = function(arg) {return this._invoke(method, arg);};});}exports.isGeneratorFunction = function(genFun) {var ctor = typeof genFun === "function" && genFun.constructor;return ctor? ctor === GeneratorFunction ||// For the native GeneratorFunction constructor, the best we can// do is to check its .name property.(ctor.displayName || ctor.name) === "GeneratorFunction": false;};exports.mark = function(genFun) {if (Object.setPrototypeOf) {Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);} else {genFun.__proto__ = GeneratorFunctionPrototype;if (!(toStringTagSymbol in genFun)) {genFun[toStringTagSymbol] = "GeneratorFunction";}}genFun.prototype = Object.create(Gp);return genFun;};// Within the body of any async function, `await x` is transformed to// `yield regeneratorRuntime.awrap(x)`, so that the runtime can test// `hasOwn.call(value, "__await")` to determine if the yielded value is// meant to be awaited.exports.awrap = function(arg) {return { __await: arg };};function AsyncIterator(generator) {function invoke(method, arg, resolve, reject) {var record = tryCatch(generator[method], generator, arg);if (record.type === "throw") {reject(record.arg);} else {var result = record.arg;var value = result.value;if (value &&typeof value === "object" &&hasOwn.call(value, "__await")) {return Promise.resolve(value.__await).then(function(value) {invoke("next", value, resolve, reject);}, function(err) {invoke("throw", err, resolve, reject);});}return Promise.resolve(value).then(function(unwrapped) {// When a yielded Promise is resolved, its final value becomes// the .value of the Promise<{value,done}> result for the// current iteration.result.value = unwrapped;resolve(result);}, function(error) {// If a rejected Promise was yielded, throw the rejection back// into the async generator function so it can be handled there.return invoke("throw", error, resolve, reject);});}}var previousPromise;function enqueue(method, arg) {function callInvokeWithMethodAndArg() {return new Promise(function(resolve, reject) {invoke(method, arg, resolve, reject);});}return previousPromise =// If enqueue has been called before, then we want to wait until// all previous Promises have been resolved before calling invoke,// so that results are always delivered in the correct order. If// enqueue has not been called before, then it is important to// call invoke immediately, without waiting on a callback to fire,// so that the async generator function has the opportunity to do// any necessary setup in a predictable way. This predictability// is why the Promise constructor synchronously invokes its// executor callback, and why async functions synchronously// execute code before the first await. Since we implement simple// async functions in terms of async generators, it is especially// important to get this right, even though it requires care.previousPromise ? previousPromise.then(callInvokeWithMethodAndArg,// Avoid propagating failures to Promises returned by later// invocations of the iterator.callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();}// Define the unified helper method that is used to implement .next,// .throw, and .return (see defineIteratorMethods).this._invoke = enqueue;}defineIteratorMethods(AsyncIterator.prototype);AsyncIterator.prototype[asyncIteratorSymbol] = function () {return this;};exports.AsyncIterator = AsyncIterator;// Note that simple async functions are implemented on top of// AsyncIterator objects; they just return a Promise for the value of// the final result produced by the iterator.exports.async = function(innerFn, outerFn, self, tryLocsList) {var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList));return exports.isGeneratorFunction(outerFn)? iter // If outerFn is a generator, return the full iterator.: iter.next().then(function(result) {return result.done ? result.value : iter.next();});};function makeInvokeMethod(innerFn, self, context) {var state = GenStateSuspendedStart;return function invoke(method, arg) {if (state === GenStateExecuting) {throw new Error("Generator is already running");}if (state === GenStateCompleted) {if (method === "throw") {throw arg;}// Be forgiving, per 25.3.3.3.3 of the spec:// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresumereturn doneResult();}context.method = method;context.arg = arg;while (true) {var delegate = context.delegate;if (delegate) {var delegateResult = maybeInvokeDelegate(delegate, context);if (delegateResult) {if (delegateResult === ContinueSentinel) continue;return delegateResult;}}if (context.method === "next") {// Setting context._sent for legacy support of Babel's// function.sent implementation.context.sent = context._sent = context.arg;} else if (context.method === "throw") {if (state === GenStateSuspendedStart) {state = GenStateCompleted;throw context.arg;}context.dispatchException(context.arg);} else if (context.method === "return") {context.abrupt("return", context.arg);}state = GenStateExecuting;var record = tryCatch(innerFn, self, context);if (record.type === "normal") {// If an exception is thrown from innerFn, we leave state ===// GenStateExecuting and loop back for another invocation.state = context.done? GenStateCompleted: GenStateSuspendedYield;if (record.arg === ContinueSentinel) {continue;}return {value: record.arg,done: context.done};} else if (record.type === "throw") {state = GenStateCompleted;// Dispatch the exception by looping back around to the// context.dispatchException(context.arg) call above.context.method = "throw";context.arg = record.arg;}}};}// Call delegate.iterator[context.method](context.arg) and handle the// result, either by returning a { value, done } result from the// delegate iterator, or by modifying context.method and context.arg,// setting context.delegate to null, and returning the ContinueSentinel.function maybeInvokeDelegate(delegate, context) {var method = delegate.iterator[context.method];if (method === undefined) {// A .throw or .return when the delegate iterator has no .throw// method always terminates the yield* loop.context.delegate = null;if (context.method === "throw") {// Note: ["return"] must be used for ES3 parsing compatibility.if (delegate.iterator["return"]) {// If the delegate iterator has a return method, give it a// chance to clean up.context.method = "return";context.arg = undefined;maybeInvokeDelegate(delegate, context);if (context.method === "throw") {// If maybeInvokeDelegate(context) changed context.method from// "return" to "throw", let that override the TypeError below.return ContinueSentinel;}}context.method = "throw";context.arg = new TypeError("The iterator does not provide a 'throw' method");}return ContinueSentinel;}var record = tryCatch(method, delegate.iterator, context.arg);if (record.type === "throw") {context.method = "throw";context.arg = record.arg;context.delegate = null;return ContinueSentinel;}var info = record.arg;if (! info) {context.method = "throw";context.arg = new TypeError("iterator result is not an object");context.delegate = null;return ContinueSentinel;}if (info.done) {// Assign the result of the finished delegate to the temporary// variable specified by delegate.resultName (see delegateYield).context[delegate.resultName] = info.value;// Resume execution at the desired location (see delegateYield).context.next = delegate.nextLoc;// If context.method was "throw" but the delegate handled the// exception, let the outer generator proceed normally. If// context.method was "next", forget context.arg since it has been// "consumed" by the delegate iterator. If context.method was// "return", allow the original .return call to continue in the// outer generator.if (context.method !== "return") {context.method = "next";context.arg = undefined;}} else {// Re-yield the result returned by the delegate method.return info;}// The delegate iterator is finished, so forget it and continue with// the outer generator.context.delegate = null;return ContinueSentinel;}// Define Generator.prototype.{next,throw,return} in terms of the// unified ._invoke helper method.defineIteratorMethods(Gp);Gp[toStringTagSymbol] = "Generator";// A Generator should always return itself as the iterator object when the// @@iterator function is called on it. Some browsers' implementations of the// iterator prototype chain incorrectly implement this, causing the Generator// object to not be returned from this call. This ensures that doesn't happen.// See https://github.com/facebook/regenerator/issues/274 for more details.Gp[iteratorSymbol] = function() {return this;};Gp.toString = function() {return "[object Generator]";};function pushTryEntry(locs) {var entry = { tryLoc: locs[0] };if (1 in locs) {entry.catchLoc = locs[1];}if (2 in locs) {entry.finallyLoc = locs[2];entry.afterLoc = locs[3];}this.tryEntries.push(entry);}function resetTryEntry(entry) {var record = entry.completion || {};record.type = "normal";delete record.arg;entry.completion = record;}function Context(tryLocsList) {// The root entry object (effectively a try statement without a catch// or a finally block) gives us a place to store values thrown from// locations where there is no enclosing try statement.this.tryEntries = [{ tryLoc: "root" }];tryLocsList.forEach(pushTryEntry, this);this.reset(true);}exports.keys = function(object) {var keys = [];for (var key in object) {keys.push(key);}keys.reverse();// Rather than returning an object with a next method, we keep// things simple and return the next function itself.return function next() {while (keys.length) {var key = keys.pop();if (key in object) {next.value = key;next.done = false;return next;}}// To avoid creating an additional object, we just hang the .value// and .done properties off the next function object itself. This// also ensures that the minifier will not anonymize the function.next.done = true;return next;};};function values(iterable) {if (iterable) {var iteratorMethod = iterable[iteratorSymbol];if (iteratorMethod) {return iteratorMethod.call(iterable);}if (typeof iterable.next === "function") {return iterable;}if (!isNaN(iterable.length)) {var i = -1, next = function next() {while (++i < iterable.length) {if (hasOwn.call(iterable, i)) {next.value = iterable[i];next.done = false;return next;}}next.value = undefined;next.done = true;return next;};return next.next = next;}}// Return an iterator with no values.return { next: doneResult };}exports.values = values;function doneResult() {return { value: undefined, done: true };}Context.prototype = {constructor: Context,reset: function(skipTempReset) {this.prev = 0;this.next = 0;// Resetting context._sent for legacy support of Babel's// function.sent implementation.this.sent = this._sent = undefined;this.done = false;this.delegate = null;this.method = "next";this.arg = undefined;this.tryEntries.forEach(resetTryEntry);if (!skipTempReset) {for (var name in this) {// Not sure about the optimal order of these conditions:if (name.charAt(0) === "t" &&hasOwn.call(this, name) &&!isNaN(+name.slice(1))) {this[name] = undefined;}}}},stop: function() {this.done = true;var rootEntry = this.tryEntries[0];var rootRecord = rootEntry.completion;if (rootRecord.type === "throw") {throw rootRecord.arg;}return this.rval;},dispatchException: function(exception) {if (this.done) {throw exception;}var context = this;function handle(loc, caught) {record.type = "throw";record.arg = exception;context.next = loc;if (caught) {// If the dispatched exception was caught by a catch block,// then let that catch block handle the exception normally.context.method = "next";context.arg = undefined;}return !! caught;}for (var i = this.tryEntries.length - 1; i >= 0; --i) {var entry = this.tryEntries[i];var record = entry.completion;if (entry.tryLoc === "root") {// Exception thrown outside of any try block that could handle// it, so set the completion value of the entire function to// throw the exception.return handle("end");}if (entry.tryLoc <= this.prev) {var hasCatch = hasOwn.call(entry, "catchLoc");var hasFinally = hasOwn.call(entry, "finallyLoc");if (hasCatch && hasFinally) {if (this.prev < entry.catchLoc) {return handle(entry.catchLoc, true);} else if (this.prev < entry.finallyLoc) {return handle(entry.finallyLoc);}} else if (hasCatch) {if (this.prev < entry.catchLoc) {return handle(entry.catchLoc, true);}} else if (hasFinally) {if (this.prev < entry.finallyLoc) {return handle(entry.finallyLoc);}} else {throw new Error("try statement without catch or finally");}}}},abrupt: function(type, arg) {for (var i = this.tryEntries.length - 1; i >= 0; --i) {var entry = this.tryEntries[i];if (entry.tryLoc <= this.prev &&hasOwn.call(entry, "finallyLoc") &&this.prev < entry.finallyLoc) {var finallyEntry = entry;break;}}if (finallyEntry &&(type === "break" ||type === "continue") &&finallyEntry.tryLoc <= arg &&arg <= finallyEntry.finallyLoc) {// Ignore the finally entry if control is not jumping to a// location outside the try/catch block.finallyEntry = null;}var record = finallyEntry ? finallyEntry.completion : {};record.type = type;record.arg = arg;if (finallyEntry) {this.method = "next";this.next = finallyEntry.finallyLoc;return ContinueSentinel;}return this.complete(record);},complete: function(record, afterLoc) {if (record.type === "throw") {throw record.arg;}if (record.type === "break" ||record.type === "continue") {this.next = record.arg;} else if (record.type === "return") {this.rval = this.arg = record.arg;this.method = "return";this.next = "end";} else if (record.type === "normal" && afterLoc) {this.next = afterLoc;}return ContinueSentinel;},finish: function(finallyLoc) {for (var i = this.tryEntries.length - 1; i >= 0; --i) {var entry = this.tryEntries[i];if (entry.finallyLoc === finallyLoc) {this.complete(entry.completion, entry.afterLoc);resetTryEntry(entry);return ContinueSentinel;}}},"catch": function(tryLoc) {for (var i = this.tryEntries.length - 1; i >= 0; --i) {var entry = this.tryEntries[i];if (entry.tryLoc === tryLoc) {var record = entry.completion;if (record.type === "throw") {var thrown = record.arg;resetTryEntry(entry);}return thrown;}}// The context.catch method must only be called with a location// argument that corresponds to a known catch block.throw new Error("illegal catch attempt");},delegateYield: function(iterable, resultName, nextLoc) {this.delegate = {iterator: values(iterable),resultName: resultName,nextLoc: nextLoc};if (this.method === "next") {// Deliberately forget the last sent value so that we don't// accidentally pass it on to the delegate.this.arg = undefined;}return ContinueSentinel;}};// Regardless of whether this script is executing as a CommonJS module// or not, return the runtime object so that we can declare the variable// regeneratorRuntime in the outer scope, which allows this module to be// injected easily by `bin/regenerator --include-runtime script.js`.return exports;}(// If this script is executing as a CommonJS module, use module.exports// as the regeneratorRuntime namespace. Otherwise create a new empty// object. Either way, the resulting object will be used to initialize// the regeneratorRuntime variable at the top of this file./* true ? module.exports : undefined */{ exports: {} }));try {regeneratorRuntime = runtime;} catch (accidentalStrictMode) {// This module should not be running in strict mode, so the above// assignment should always work unless something is misconfigured. Just// in case runtime.js accidentally runs in strict mode, we can escape// strict mode using a global Function call. This could conceivably fail// if a Content Security Policy forbids using Function, but in that case// the proper solution is to fix the accidental strict mode problem. If// you've misconfigured your bundler to force strict mode and applied a// CSP to forbid Function, and you're not willing to fix either of those// problems, please detail your unique predicament in a GitHub issue.Function("r", "regeneratorRuntime = r")(runtime);}
bable编译前的代码
function * demo (){console.log('1')var a = yield new Promise(function(resolve, reject){console.log('2');setTimeout(()=>{console.log('3');resolve(1);}, 3000);});console.log('4');var b = yield Promise.resolve(a + 1);console.log('5');var c = yield Promise.resolve(b + 1);return c;}function co(generator) {var gen = generator();function nextFunc(arg) {console.log('arg', arg);var next = gen.next(arg);if (!next.done) {next.value.then(function(data){console.log('data',data);nextFunc(data);});} else if (next.value) {console.log('return',next.value)return next.value;}}nextFunc();}co(demo);arg undefinedVM672:2 1VM672:4 2undefinedVM672:6 3VM672:23 data 1VM672:19 arg 1VM672:10 4VM672:23 data 2VM672:19 arg 2VM672:12 5VM672:23 data 3VM672:19 arg 3VM672:27 return 3
babel编译后的代码
"use strict";var _marked =/*#__PURE__*/regeneratorRuntime.mark(demo);function demo() {var a, b, c;return regeneratorRuntime.wrap(function demo$(_context) {while (1) {switch (_context.prev = _context.next) {case 0:_context.next = 2;return Promise.resolve(1);case 2:a = _context.sent;_context.next = 5;return Promise.resolve(a + 1);case 5:b = _context.sent;_context.next = 8;return Promise.resolve(b + 1);case 8:c = _context.sent;return _context.abrupt("return", c);case 10:case "end":return _context.stop();}}}, _marked);}function co(generator) {var gen = generator();function nextFunc(arg) {console.log('arg', arg);var next = gen.next(arg);if (!next.done) {next.value.then(function (data) {console.log('data', data);nextFunc(data);});} else if (next.value) {console.log('return', next.value);return next.value;}}nextFunc();}co(demo);
学习过的后的理解
1.创建3个构造函数,Generator,GeneratorFunction,GeneratorFunctionPrototype
2.首先将数组的Symbol.iterator的拿出来给上面的三个构造函数使用
3.var _marked = regeneratorRuntime.mark(demo); 方法将next与throw,return方法添加到demo里面,是demo的类型变成Generator类型
4.co是一个函数执行器,当完成第一个操作的时候,执行next方法执行第二个方法
5.demo是一个函数分配器,指定下一步执行什么处理
var regeneratorRuntime = (function (exports) {"use strict";function Generator() { };function GeneratorFunctionPrototype() { };function GeneratorFunction() { };var Op = Object.prototype;var $Symbol = typeof Symbol === 'function' ? Symbol : {};var iteratorSymbol = $Symbol.iterator || "@@iterator";var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";var hasOwn = Object.hasOwnProperty;var getProto = Object.getPrototypeOf;;;;;;;var IteratorPrototype = {};IteratorPrototype[iteratorSymbol] = function () {return this;}function values(iterable) {if (iterable) {var iteratorMethod = iterable[iteratorSymbol];if (iteratorMethod) {return iteratorMethod.call(iterable);}}}var NativeIteratorPrototype = getProto && getProto(getProto(values([])));if (NativeIteratorPrototype && NativeIteratorPrototype !== Op &&hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {;;;;;// 将数组的 Array Iterator 给了 IteratorPrototypeIteratorPrototype = NativeIteratorPrototype;}var Gp = GeneratorFunctionPrototype.prototype =Generator.prototype = Object.create(IteratorPrototype);GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;GeneratorFunctionPrototype.constructor = GeneratorFunction;GeneratorFunctionPrototype[toStringTagSymbol] =GeneratorFunction.displayName = "GeneratorFunction";defineIteratorMethods(Gp);Gp[toStringTagSymbol] = "Generator";Gp[iteratorSymbol] = function () {return this;};Gp.toString = function () {return "[object Generator]";};function defineIteratorMethods(prototype) {['next', 'throw', 'return'].forEach(function (method) {;;;;;prototype[method] = function (arg) {;;;;;return this._invoke(method, arg);}});}exports.mark = function (genFun) {Object.setPrototypeOf(genFun, Generator);genFun.prototype = Object.create(Gp);return genFun;}exports.wrap = function (innerFn, outerFn) {// innerFn, outerFnvar protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;var generator = Object.create(protoGenerator.prototype);var context = new Context([]);generator._invoke = makeInvokeMethod(innerFn, self, context);return generator;}function tryCatch(fn, obj, arg) { // 公共的try catch;;;;;;try {// arg 返回函数执行结果return { type: 'normal', arg: fn.call(obj, arg) };} catch (err) {return { type: 'throw', arg: err };}}function Context(arg) {this.arg = undefined;this.delegate = null;this.done = false;this.method = "next";this.next = 0;this.prev = 0;this.sent = undefinedthis.tryEntries = [];this._sent = undefined}// 一些状态值var GenStateSuspendedStart = "suspendedStart";var GenStateSuspendedYield = "suspendedYield";var GenStateExecuting = "executing";var GenStateCompleted = "completed";var ContinueSentinel = {};function makeInvokeMethod(innerFn, self, context) {var state = GenStateSuspendedStart;;;;;;;return function invoke(method, arg) {;;;;;;if (state === GenStateExecuting) {throw new Error("Generator is already running");}if (state === GenStateCompleted) {if (method === "throw") {throw arg;}return doneResult();}context.method = method;context.arg = arg;while (true) {state = GenStateExecuting;if (context.method === 'next') {context.sent = context._sent = context.arg;} else if (context.method === 'throw') {if (state === GenStateSuspendedStart) {state = GenStateCompleted;throw context.arg;}return {done: true,value: arg}} else if (context.method === 'return') {state = GenStateCompleted;return {done: true,value: arg}}var record = tryCatch(innerFn, self, context);state = GenStateExecuting;if (record.type === 'normal') {state = context.done? GenStateCompleted: GenStateSuspendedYield;if (record.arg === ContinueSentinel) {continue;}return {value: record.arg,done: context.done}} else if (record.type === "throw") {state = GenStateCompleted;context.method = "throw";context.arg = record.arg;}}}}return exports;})({ exports: {} });var _marked =/*#__PURE__*/regeneratorRuntime.mark(demo);function demo() {var a, b, c;return regeneratorRuntime.wrap(function demo$(_context) {while (1) {switch (_context.prev = _context.next) {case 0:_context.next = 2;return Promise.resolve(1);case 2:a = _context.sent;_context.next = 5;return Promise.resolve(a + 1);case 5:b = _context.sent;_context.next = 8;return Promise.resolve(b + 1);case 8:c = _context.sent;return _context.abrupt("return", c);case 10:case "end":return _context.stop();}}}, _marked);}function co(generator) {var gen = generator();function nextFunc(arg) {var next = gen.next(arg);console.log('next', next);if (!next.done) {next.value.then(function (data) {nextFunc(data);});} else if (next.value) {console.log('return', next.value);return next.value;}}nextFunc();}co(demo);
var runtime = (function (exports) {"use strict";debuggervar Op = Object.prototype;var hasOwn = Object.hasOwnProperty;var undefined;var $Symbol = typeof Symbol === 'function' ? Symbol : {};// 同步的迭代器var iteratorSymbol = $Symbol.iterator || "@@iterator";// 异步的迭代器var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";// [object TagName]var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";// 一些状态值var GenStateSuspendedStart = "suspendedStart";var GenStateSuspendedYield = "suspendedYield";var GenStateExecuting = "executing";var GenStateCompleted = "completed";var ContinueSentinel = {};var IteratorPrototype = {};IteratorPrototype[iteratorSymbol] = function () {// 此方法相当于一个展位符,在后面的语句里被修改// IteratorPrototype此对象会具备数组Array的Symbol.iterator方法debuggerreturn this;}var getProto = Object.getPrototypeOf;// 获取数组的原型的原型 是一个实例没有prototype方法// getProto(getProto(values([]))) return { Symbol(Symbol.iterator): fn ,__proto__: Object }// 返回了一个object的实例var NativeIteratorPrototype = getProto && getProto(getProto(values([])));if (NativeIteratorPrototype && NativeIteratorPrototype !== Op &&hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {debugger// 将数组的 Array Iterator 给了 IteratorPrototypeIteratorPrototype = NativeIteratorPrototype;}/*使他们都具备Symbol.iterator接口注意Gp是一个Object的实例, GeneratorFunctionPrototype原型, Generator的原型*/var Gp = GeneratorFunctionPrototype.prototype =Generator.prototype = Object.create(IteratorPrototype);GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;GeneratorFunctionPrototype.constructor = GeneratorFunction;GeneratorFunctionPrototype[toStringTagSymbol] =GeneratorFunction.displayName = "GeneratorFunction";defineIteratorMethods(AsyncIterator.prototype); // 添加默认方法next,return,throwAsyncIterator.prototype[asyncIteratorSymbol] = function () {debuggerreturn this;}defineIteratorMethods(Gp); // 添加默认方法next,return,throwGp[toStringTagSymbol] = "Generator";Gp[iteratorSymbol] = function () {debuggerreturn this;};Gp.toString = function () {debuggerreturn "[object Generator]";};Context.prototype = {constructor: Context,reset: function (skipTempReset) { // (#6)debugger;this.prev = 0;this.next = 0;this.sent = this._sent = undefined;this.done = false;this.delegate = null;this.method = 'next';this.arg = undefined;this.tryEntries.forEach(resetTryEntry);if (!skipTempReset) {for (var name in this) {if (name.charAt(0) === 't' &&hasOwn.call(this, name) &&!isNaN(+name.slice(1))) {this[name] = undefined;}}}},stop: function () {debuggerthis.done = true;var rootEntry = this.tryEntries[0];var rootRecord = rootEntry.completion;if (rootRecord.type === 'throw') {throw rootRecord.arg;}return this.rval;},dispatchException: function (exception) {debuggerif (this.done) {throw exception;}var context = this;function handle(loc, caught) {debuggerrecord.type = "throw";record.arg = exception;context.next = loc;if (caught) {context.method = "next";context.arg = undefined;}return !!caught;}for (var i = this.tryEntries.length - 1; i >= 0; --i) {var entry = this.tryEntries[i];var record = entry.completion;if (entry.tryLoc === "root") {return handle("end");}if (entry.tryLoc <= this.prev) {var hasCatch = hasOwn.call(entry, "catchLoc");var hasFinally = hasOwn.call(entry, "finallyLoc");if (hasCatch && hasFinally) {if (this.prev < entry.catchLoc) {return handle(entry.catchLoc, true);} else if (this.prev < entry.finallyLoc) {return handle(entry.finallyLoc);}} else if (hasCatch) {if (this.prev < entry.catchLoc) {return handle(entry.catchLoc, true);}} else if (hasFinally) {if (this.prev < entry.finallyLoc) {return handle(entry.finallyLoc);}} else {throw new Error("try statement without catch or finally");}}}},abrupt: function (type, arg) {debuggerfor (var i = this.tryEntries.length - 1; i >= 0; --i) {var entry = this.tryEntries[i];if (entry.tryLoc <= this.prev &&hasOwn.call(entry, "finallyLoc") &&this.prev < entry.finallyLoc) {var finallyEntry = entry;break;}}if (finallyEntry &&(type === "break" ||type === "continue") &&finallyEntry.tryLoc <= arg &&arg <= finallyEntry.finallyLoc) {// Ignore the finally entry if control is not jumping to a// location outside the try/catch block.finallyEntry = null;}var record = finallyEntry ? finallyEntry.completion : {};record.type = type;record.arg = arg;if (finallyEntry) {this.method = "next";this.next = finallyEntry.finallyLoc;return ContinueSentinel;}return this.complete(record);},complete: function (record, afterLoc) {debuggerif (record.type === "throw") {throw record.arg;}if (record.type === "break" ||record.type === "continue") {this.next = record.arg;} else if (record.type === "return") {this.rval = this.arg = record.arg;this.method = "return";this.next = "end";} else if (record.type === "normal" && afterLoc) {this.next = afterLoc;}return ContinueSentinel;},finish: function (finallyLoc) {debuggerfor (var i = this.tryEntries.length - 1; i >= 0; --i) {var entry = this.tryEntries[i];if (entry.finallyLoc === finallyLoc) {this.complete(entry.completion, entry.afterLoc);resetTryEntry(entry);return ContinueSentinel;}}},catch: function (tryLoc) {debuggerfor (var i = this.tryEntries.length - 1; i >= 0; --i) {var entry = this.tryEntries[i];if (entry.tryLoc === tryLoc) {var record = entry.completion;if (record.type === "throw") {var thrown = record.arg;resetTryEntry(entry);}return thrown;}}// The context.catch method must only be called with a location// argument that corresponds to a known catch block.throw new Error("illegal catch attempt");},delegateYield: function (iterable, resultName, nextLoc) {debuggerthis.delegate = {iterator: values(iterable),resultName: resultName,nextLoc: nextLoc};if (this.method === "next") {// Deliberately forget the last sent value so that we don't// accidentally pass it on to the delegate.this.arg = undefined;}return ContinueSentinel;}}function AsyncIterator(generator) { // 异步的迭代器debuggerfunction invoke(method, arg, resolve, reject) {debuggervar record = tryCatch(generator[method], generator, arg);if (record.type === 'throw') {reject(record.arg);} else {var result = record.arg;var value = result.value;if (value && typeof value === "object" &&hasOwn.call(value, "__await")) {return Promise.resolve(value.__await).then(function (value) {invoke("next", value, resolve, reject);}, function (err) {invoke("throw", err, resolve, reject);});}return Promise.resolve(value).then(function (unwraooed) {result.value = unwrapped;resolve(result);}, function (error) {return invoke("throw", error, resolve, reject);});}}var previousPromise;function enqueue(method, arg) {debuggerfunction callInvokeWithMethodAndArg() {debuggerreturn new Promise(function (resolve, reject) {invoke(method, arg, resolve, reject);});}return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg,callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();}this._invoke = enqueue;}function makeInvokeMethod(innerFn, self, context) { // (#8)// exports.wrap 里面调用debuggervar state = GenStateSuspendedStart;return function invoke(method, arg) {debuggerif (state === GenStateExecuting) {throw new Error("Generator is already running")}if (state === GenStateCompleted) {if (method === 'throw') {throw arg;}return doneResult();}context.method = method;context.arg = arg;while (true) {var delegate = context.delegate;if (delegate) {var delegateResult = maybeInvokeDelegate(delegate, context);if (delegateResult) {if (delegateResult === ContinueSentinel) continue;return delegateResult;}}if (context.method === 'next') {context.sent = context._sent = context.arg;} else if (context.method === 'throw') {if (state === GenStateSuspendedStart) {state = GenStateCompleted;throw context.arg;}context.dispatchException(context.arg);} else if (context.method === 'return') {context.abrupt("return", context.arg);}state = GenStateExecuting;var record = tryCatch(innerFn, self, context);if (record.type === 'normal') {state = context.done? GenStateCompleted: GenStateSuspendedYield;if (record.arg === ContinueSentinel) {continue;}return {value: record.arg,done: context.done}} else if (record.type === "throw") {state = GenStateCompleted;context.method = "throw";context.arg = record.arg;}}};}function maybeInvokeDelegate(delegate, context) {// makeInvokeMethod 有调用debuggervar method = delegate.iterator[context.method];if (method === undefined) {context.delegate = null;if (context.method === 'throw') {if (delegate.iterator["return"]) {context.method = "return";context.arg = undefined;maybeInvokeDelegate(delegate, context);if (context.method === 'throw') {return ContinueSentinel;}}context.method = "throw";context.arg = new TypeError("The iterator does not provide a 'throw' method");}return ContinueSentinel;}var record = tryCatch(method, delegate.iterator, context.arg);if (record.type === 'throw') {context.method = 'throw';context.arg = record.arg;context.delegate = null;return ContinueSentinel;}var info = record.arg;if (!info) {context.method = "throw";context.arg = new TypeError("iterator result is not an object");context.delegate = null;return ContinueSentinel;}if (info.done) {context[delegate.resultName] = info.value;context.next = delegate.nextLoc;if (context.method !== 'return') {context.method = "next";context.arg = undefined;}} else {return info;}context.delegate = null;return ContinueSentinel;}function values(iterable) { // (#1)debuggerif (iterable) {/*var a = [];a.push('1');a['iterator'] = { a: 1 };console.log(a); // ['1', 'iterator': { a: 1} ]console.log(a.length); // 1a.push('2');console.log(a.length); // 2*/// 数组默认具备Iterator接口var iteratorMethod = iterable[iteratorSymbol];if (iteratorMethod) {// 返回一个 Array Iterator { __proto__: Array Iterator }return iteratorMethod.call(iterable);}if (typeof iterable.next === 'function') {return iterable;}if (!isNaN(iterable.length)) {var i = -1, next = function next() {while (++i < iterable.length) {if (hasOwn.call(iterable, i)) {next.value = iterable[i];next.done = false;return next;}}next.value = undefined;next.done = true;return next;}return next.next = next;}}return { next: doneResult };}function pushTryEntry(locs) { // Context方法在使用debuggervar entry = { tryLoc: locs[0] };if (1 in locs) {entry.catchLoc = locs[1];}if (2 in locs) {entry.finallyLoc = locs[2];entry.afterLoc = locs[3];}this.tryEntries.push(entry);}function resetTryEntry(entry) { // (#7) // Context对象的reset方法在使用debuggervar record = entry.completion || {};record.type = "normal";delete record.arg;entry.completion = record;}function Context(tryLocsList) { // (#5)debuggerthis.tryEntries = [{ tryLoc: "root" }];tryLocsList.forEach(pushTryEntry, this);this.reset(true);}function doneResult() {debuggerreturn { value: undefined, done: true };}function defineIteratorMethods(prototype) { //(#2)debugger['next', 'throw', 'return'].forEach(function (method) {debuggerprototype[method] = function (arg) {debuggerreturn this._invoke(method, arg);}});}function tryCatch(fn, obj, arg) { // 公共的try catchdebuggertry {// arg 返回函数执行结果return { type: 'normal', arg: fn.call(obj, arg) };} catch (err) {return { type: 'throw', arg: err };}}function Generator() {console.log('Generator')};function GeneratorFunction() {console.log('GeneratorFunction')};function GeneratorFunctionPrototype() {console.log('GeneratorFunctionPrototype')};function wrap(innerFn, outerFn, self, tryLocsList) { // (#4)// 执行debuggervar protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;var generator = Object.create(protoGenerator.prototype);var context = new Context(tryLocsList || []);generator._invoke = makeInvokeMethod(innerFn, self, context);return generator;}function mark(genFun) {// (#3) // 声明这个函数是一个Generator函数debugger// 改变函数的原型的类型,以及他的原型链/* 最初的时候genFun:functiongenFun.prototype:object { contructor: function(){ 这个是它本身 } }genFun.__proto__:function 指向function.prototype*/if (Object.setPrototypeOf) {// 改变他的原型链,就可以使用原型链上的方法Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);} else {// 改变他的原型链,就可以使用原型链上的方法genFun.__proto__ = GeneratorFunctionPrototype;if (!(toStringTagSymbol in genFun)) {genFun[toStringTagSymbol] = "GeneratorFunction";}}// 改变他的原型类型,可以使用它的原型的方法genFun.prototype = Object.create(Gp);/* 最初的时候genFun:functiongenFun.prototype: GeneratorgenFun.__proto__: GeneratorFunctionPrototype*/return genFun;}exports.wrap = wrap;exports.isGeneratorFunction = function (genFun) {debuggervar ctor = typeof genFun === 'function' && genFun.constructor;return ctor? ctor === GeneratorFunction ||(ctor.displayName || ctor.name) === "GeneratorFunction": false;;}exports.mark = mark;exports.awrap = function (arg) {debuggerreturn { __await: arg };}exports.AsyncIterator = AsyncIterator;exports.async = function (innerFn, outerFn, self, tryLocsList) {debuggeriter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList));return exports.isGeneratorFunction(outerFn)? iter :iter.next().then(function (result) {debuggerreturn result.done ? result.value : iter.next();});};exports.keys = function (object) {debuggervar keys = [];for (var key in object) {keys.push(key);}keys.reverse();return function next() {while (keys.length) {var key = keys.pop();if (key in object) {next.value = key;next.done = false;return next;}}next.done = true;return next;}}exports.values = values;return exports;})({ exports: {} });try {regeneratorRuntime = runtime;} catch (accidentalStrictMode) {// 严格模式下可能会有异常出现Function("r", "regeneratorRuntime = r")(runtime);}var _marked =/*#__PURE__*/regeneratorRuntime.mark(demo);function demo() {debuggervar a, b, c;return regeneratorRuntime.wrap(function demo$(_context) {debuggerwhile (1) {switch (_context.prev = _context.next) {case 0:_context.next = 2;return Promise.resolve(1);case 2:a = _context.sent;_context.next = 5;return Promise.resolve(a + 1);case 5:b = _context.sent;_context.next = 8;return Promise.resolve(b + 1);case 8:c = _context.sent;return _context.abrupt("return", c);case 10:case "end":return _context.stop();}}}, _marked);}function co(generator) {debuggervar gen = generator();function nextFunc(arg) {debuggerconsole.log('arg', arg);var next = gen.next(arg);if (!next.done) {next.value.then(function (data) {console.log('data', data);nextFunc(data);});} else if (next.value) {console.log('return', next.value);return next.value;}}nextFunc();}co(demo);
