diff --git a/Makefile b/Makefile index f3dc5a995..0341cf99c 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ RUNTIME_SRC = \ src/runtime/runtime.js \ src/runtime/spread.js \ src/runtime/classes.js \ + src/runtime/generators.js \ src/runtime/url.js \ src/runtime/ModuleStore.js SRC = \ diff --git a/bin/traceur.js b/bin/traceur.js index 4b1bc7ca0..b13c76c06 100644 --- a/bin/traceur.js +++ b/bin/traceur.js @@ -267,6 +267,149 @@ throw $TypeError(x + ' is not an Object'); return x; } + function setupGlobals(global) { + global.Symbol = Symbol; + polyfillObject(global.Object); + } + setupGlobals(global); + global.$traceurRuntime = { + assertObject: assertObject, + exportStar: exportStar, + getOwnHashObject: getOwnHashObject, + setProperty: setProperty, + setupGlobals: setupGlobals, + toObject: toObject, + toProperty: toProperty, + type: types, + typeof: typeOf, + createPrivateName: createPrivateName, + defineProperties: $defineProperties, + defineProperty: $defineProperty, + getOwnPropertyDescriptor: $getOwnPropertyDescriptor, + getOwnPropertyNames: $getOwnPropertyNames + }; +})(typeof global !== 'undefined' ? global : this); +(function() { + 'use strict'; + var toObject = $traceurRuntime.toObject; + function spread() { + var rv = [], + k = 0; + for (var i = 0; i < arguments.length; i++) { + var valueToSpread = toObject(arguments[i]); + for (var j = 0; j < valueToSpread.length; j++) { + rv[k++] = valueToSpread[j]; + } + } + return rv; + } + $traceurRuntime.spread = spread; +})(); +(function() { + 'use strict'; + var $Object = Object; + var $TypeError = TypeError; + var $create = $Object.create; + var $defineProperties = $traceurRuntime.defineProperties; + var $defineProperty = $traceurRuntime.defineProperty; + var $getOwnPropertyDescriptor = $traceurRuntime.getOwnPropertyDescriptor; + var $getOwnPropertyNames = $traceurRuntime.getOwnPropertyNames; + var $getPrototypeOf = Object.getPrototypeOf; + function superDescriptor(homeObject, name) { + var proto = $getPrototypeOf(homeObject); + do { + var result = $getOwnPropertyDescriptor(proto, name); + if (result) + return result; + proto = $getPrototypeOf(proto); + } while (proto); + return undefined; + } + function superCall(self, homeObject, name, args) { + return superGet(self, homeObject, name).apply(self, args); + } + function superGet(self, homeObject, name) { + var descriptor = superDescriptor(homeObject, name); + if (descriptor) { + if (!descriptor.get) + return descriptor.value; + return descriptor.get.call(self); + } + return undefined; + } + function superSet(self, homeObject, name, value) { + var descriptor = superDescriptor(homeObject, name); + if (descriptor && descriptor.set) { + descriptor.set.call(self, value); + return value; + } + throw $TypeError("super has no setter '" + name + "'."); + } + function getDescriptors(object) { + var descriptors = {}, + name, + names = $getOwnPropertyNames(object); + for (var i = 0; i < names.length; i++) { + var name = names[i]; + descriptors[name] = $getOwnPropertyDescriptor(object, name); + } + return descriptors; + } + function createClass(ctor, object, staticObject, superClass) { + $defineProperty(object, 'constructor', { + value: ctor, + configurable: true, + enumerable: false, + writable: true + }); + if (arguments.length > 3) { + if (typeof superClass === 'function') + ctor.__proto__ = superClass; + ctor.prototype = $create(getProtoParent(superClass), getDescriptors(object)); + } else { + ctor.prototype = object; + } + $defineProperty(ctor, 'prototype', { + configurable: false, + writable: false + }); + return $defineProperties(ctor, getDescriptors(staticObject)); + } + function getProtoParent(superClass) { + if (typeof superClass === 'function') { + var prototype = superClass.prototype; + if ($Object(prototype) === prototype || prototype === null) + return superClass.prototype; + } + if (superClass === null) + return null; + throw new $TypeError(); + } + function defaultSuperCall(self, homeObject, args) { + if ($getPrototypeOf(homeObject) !== null) + superCall(self, homeObject, 'constructor', args); + } + $traceurRuntime.createClass = createClass; + $traceurRuntime.defaultSuperCall = defaultSuperCall; + $traceurRuntime.superCall = superCall; + $traceurRuntime.superGet = superGet; + $traceurRuntime.superSet = superSet; +})(); +(function() { + 'use strict'; + var createPrivateName = $traceurRuntime.createPrivateName; + var $defineProperties = $traceurRuntime.defineProperties; + var $defineProperty = $traceurRuntime.defineProperty; + var $create = Object.create; + var $TypeError = TypeError; + function nonEnum(value) { + return { + configurable: true, + enumerable: false, + value: value, + writable: true + }; + } var ST_NEWBORN = 0; var ST_EXECUTING = 1; var ST_SUSPENDED = 2; @@ -389,7 +532,7 @@ next: {enumerable: false}, throw: {enumerable: false} }); - defineProperty(GeneratorFunctionPrototype.prototype, Symbol.iterator, nonEnum(function() { + Object.defineProperty(GeneratorFunctionPrototype.prototype, Symbol.iterator, nonEnum(function() { return this; })); function createGeneratorInstance(innerFunction, functionObject, self) { @@ -414,7 +557,7 @@ ctx.reject = reject; }); } - AsyncFunctionContext.prototype = Object.create(GeneratorContext.prototype); + AsyncFunctionContext.prototype = $create(GeneratorContext.prototype); AsyncFunctionContext.prototype.end = function() { switch (this.state) { case END_STATE: @@ -469,135 +612,9 @@ if (last.finallyFallThrough !== undefined) ctx.finallyFallThrough = last.finallyFallThrough; } - function setupGlobals(global) { - global.Symbol = Symbol; - polyfillObject(global.Object); - } - setupGlobals(global); - global.$traceurRuntime = { - assertObject: assertObject, - asyncWrap: asyncWrap, - exportStar: exportStar, - initGeneratorFunction: initGeneratorFunction, - createGeneratorInstance: createGeneratorInstance, - getOwnHashObject: getOwnHashObject, - setProperty: setProperty, - setupGlobals: setupGlobals, - toObject: toObject, - toProperty: toProperty, - type: types, - typeof: typeOf, - defineProperties: $defineProperties, - defineProperty: $defineProperty, - getOwnPropertyDescriptor: $getOwnPropertyDescriptor, - getOwnPropertyNames: $getOwnPropertyNames - }; -})(typeof global !== 'undefined' ? global : this); -(function() { - 'use strict'; - var toObject = $traceurRuntime.toObject; - function spread() { - var rv = [], - k = 0; - for (var i = 0; i < arguments.length; i++) { - var valueToSpread = toObject(arguments[i]); - for (var j = 0; j < valueToSpread.length; j++) { - rv[k++] = valueToSpread[j]; - } - } - return rv; - } - $traceurRuntime.spread = spread; -})(); -(function() { - 'use strict'; - var $Object = Object; - var $TypeError = TypeError; - var $create = $Object.create; - var $defineProperties = $traceurRuntime.defineProperties; - var $defineProperty = $traceurRuntime.defineProperty; - var $getOwnPropertyDescriptor = $traceurRuntime.getOwnPropertyDescriptor; - var $getOwnPropertyNames = $traceurRuntime.getOwnPropertyNames; - var $getPrototypeOf = Object.getPrototypeOf; - function superDescriptor(homeObject, name) { - var proto = $getPrototypeOf(homeObject); - do { - var result = $getOwnPropertyDescriptor(proto, name); - if (result) - return result; - proto = $getPrototypeOf(proto); - } while (proto); - return undefined; - } - function superCall(self, homeObject, name, args) { - return superGet(self, homeObject, name).apply(self, args); - } - function superGet(self, homeObject, name) { - var descriptor = superDescriptor(homeObject, name); - if (descriptor) { - if (!descriptor.get) - return descriptor.value; - return descriptor.get.call(self); - } - return undefined; - } - function superSet(self, homeObject, name, value) { - var descriptor = superDescriptor(homeObject, name); - if (descriptor && descriptor.set) { - descriptor.set.call(self, value); - return value; - } - throw $TypeError("super has no setter '" + name + "'."); - } - function getDescriptors(object) { - var descriptors = {}, - name, - names = $getOwnPropertyNames(object); - for (var i = 0; i < names.length; i++) { - var name = names[i]; - descriptors[name] = $getOwnPropertyDescriptor(object, name); - } - return descriptors; - } - function createClass(ctor, object, staticObject, superClass) { - $defineProperty(object, 'constructor', { - value: ctor, - configurable: true, - enumerable: false, - writable: true - }); - if (arguments.length > 3) { - if (typeof superClass === 'function') - ctor.__proto__ = superClass; - ctor.prototype = $create(getProtoParent(superClass), getDescriptors(object)); - } else { - ctor.prototype = object; - } - $defineProperty(ctor, 'prototype', { - configurable: false, - writable: false - }); - return $defineProperties(ctor, getDescriptors(staticObject)); - } - function getProtoParent(superClass) { - if (typeof superClass === 'function') { - var prototype = superClass.prototype; - if ($Object(prototype) === prototype || prototype === null) - return superClass.prototype; - } - if (superClass === null) - return null; - throw new $TypeError(); - } - function defaultSuperCall(self, homeObject, args) { - if ($getPrototypeOf(homeObject) !== null) - superCall(self, homeObject, 'constructor', args); - } - $traceurRuntime.createClass = createClass; - $traceurRuntime.defaultSuperCall = defaultSuperCall; - $traceurRuntime.superCall = superCall; - $traceurRuntime.superGet = superGet; - $traceurRuntime.superSet = superSet; + $traceurRuntime.asyncWrap = asyncWrap; + $traceurRuntime.initGeneratorFunction = initGeneratorFunction; + $traceurRuntime.createGeneratorInstance = createGeneratorInstance; })(); (function() { function buildFromEncodedParts(opt_scheme, opt_userInfo, opt_domain, opt_port, opt_path, opt_queryData, opt_fragment) { diff --git a/src/runtime/runtime.js b/src/runtime/runtime.js index 8cafe7e2a..6eb61f298 100644 --- a/src/runtime/runtime.js +++ b/src/runtime/runtime.js @@ -391,244 +391,6 @@ return x; } - // Generator states. Terminology roughly matches that of - // http://wiki.ecmascript.org/doku.php?id=harmony:generators - // Since 'state' is already taken, use 'GState' instead to denote what's - // referred to as "G.[[State]]" on that page. - var ST_NEWBORN = 0; - var ST_EXECUTING = 1; - var ST_SUSPENDED = 2; - var ST_CLOSED = 3; - - var END_STATE = -2; - var RETHROW_STATE = -3; - - - function getInternalError(state) { - return new Error('Traceur compiler bug: invalid state in state machine: ' + - state); - } - - function GeneratorContext() { - this.state = 0; - this.GState = ST_NEWBORN; - this.storedException = undefined; - this.finallyFallThrough = undefined; - this.sent_ = undefined; - this.returnValue = undefined; - this.tryStack_ = []; - } - GeneratorContext.prototype = { - pushTry: function(catchState, finallyState) { - if (finallyState !== null) { - var finallyFallThrough = null; - for (var i = this.tryStack_.length - 1; i >= 0; i--) { - if (this.tryStack_[i].catch !== undefined) { - finallyFallThrough = this.tryStack_[i].catch; - break; - } - } - if (finallyFallThrough === null) - finallyFallThrough = RETHROW_STATE; - - this.tryStack_.push({ - finally: finallyState, - finallyFallThrough: finallyFallThrough - }); - } - - if (catchState !== null) { - this.tryStack_.push({catch: catchState}); - } - }, - popTry: function() { - this.tryStack_.pop(); - }, - get sent() { - this.maybeThrow(); - return this.sent_; - }, - set sent(v) { - this.sent_ = v; - }, - get sentIgnoreThrow() { - return this.sent_; - }, - maybeThrow: function() { - if (this.action === 'throw') { - this.action = 'next'; - throw this.sent_; - } - }, - end: function() { - switch (this.state) { - case END_STATE: - return this; - case RETHROW_STATE: - throw this.storedException; - default: - throw getInternalError(this.state); - } - }, - handleException: function(ex) { - this.GState = ST_CLOSED; - this.state = END_STATE; - throw ex; - } - }; - - function nextOrThrow(ctx, moveNext, action, x) { - switch (ctx.GState) { - case ST_EXECUTING: - throw new Error(`"${action}" on executing generator`); - - case ST_CLOSED: - throw new Error(`"${action}" on closed generator`); - - case ST_NEWBORN: - if (action === 'throw') { - ctx.GState = ST_CLOSED; - throw x; - } - if (x !== undefined) - throw $TypeError('Sent value to newborn generator'); - // fall through - - case ST_SUSPENDED: - ctx.GState = ST_EXECUTING; - ctx.action = action; - ctx.sent = x; - var value = moveNext(ctx); - var done = value === ctx; - if (done) - value = ctx.returnValue; - ctx.GState = done ? ST_CLOSED : ST_SUSPENDED; - return {value: value, done: done}; - } - } - - var ctxName = createPrivateName(); - var moveNextName = createPrivateName(); - - function GeneratorFunction() {} - - function GeneratorFunctionPrototype() {} - - GeneratorFunction.prototype = GeneratorFunctionPrototype; - - $defineProperty(GeneratorFunctionPrototype, 'constructor', - nonEnum(GeneratorFunction)); - - GeneratorFunctionPrototype.prototype = { - constructor: GeneratorFunctionPrototype, - next: function(v) { - return nextOrThrow(this[ctxName], this[moveNextName], 'next', v); - }, - throw: function(v) { - return nextOrThrow(this[ctxName], this[moveNextName], 'throw', v); - } - }; - - $defineProperties(GeneratorFunctionPrototype.prototype, { - constructor: {enumerable: false}, - next: {enumerable: false}, - throw: {enumerable: false}, - }); - - defineProperty(GeneratorFunctionPrototype.prototype, Symbol.iterator, - nonEnum(function() { - return this; - })); - - function createGeneratorInstance(innerFunction, functionObject, self) { - // TODO(arv): Use [[GeneratorState]] - var moveNext = getMoveNext(innerFunction, self); - var ctx = new GeneratorContext(); - - var object = $create(functionObject.prototype); - object[ctxName] = ctx; - object[moveNextName] = moveNext; - return object; - } - - function initGeneratorFunction(functionObject) { - functionObject.prototype = $create(GeneratorFunctionPrototype.prototype); - functionObject.__proto__ = GeneratorFunctionPrototype; - return functionObject; - } - - function AsyncFunctionContext() { - GeneratorContext.call(this); - this.err = undefined; - var ctx = this; - ctx.result = new Promise(function(resolve, reject) { - ctx.resolve = resolve; - ctx.reject = reject; - }); - } - AsyncFunctionContext.prototype = Object.create(GeneratorContext.prototype); - AsyncFunctionContext.prototype.end = function() { - switch (this.state) { - case END_STATE: - this.resolve(this.returnValue); - break; - case RETHROW_STATE: - this.reject(this.storedException); - break; - default: - this.reject(getInternalError(this.state)); - } - }; - AsyncFunctionContext.prototype.handleException = function() { - this.state = RETHROW_STATE; - }; - - function asyncWrap(innerFunction, self) { - var moveNext = getMoveNext(innerFunction, self); - var ctx = new AsyncFunctionContext(); - ctx.createCallback = function(newState) { - return function (value) { - ctx.state = newState; - ctx.value = value; - moveNext(ctx); - }; - } - - ctx.errback = function(err) { - handleCatch(ctx, err); - moveNext(ctx); - }; - - moveNext(ctx); - return ctx.result; - } - - function getMoveNext(innerFunction, self) { - return function(ctx) { - while (true) { - try { - return innerFunction.call(self, ctx); - } catch (ex) { - handleCatch(ctx, ex); - } - } - }; - } - - function handleCatch(ctx, ex) { - ctx.storedException = ex; - var last = ctx.tryStack_[ctx.tryStack_.length - 1]; - if (!last) { - ctx.handleException(ex); - return; - } - - ctx.state = last.catch !== undefined ? last.catch : last.finally; - - if (last.finallyFallThrough !== undefined) - ctx.finallyFallThrough = last.finallyFallThrough; - } - function setupGlobals(global) { global.Symbol = Symbol; @@ -639,10 +401,8 @@ global.$traceurRuntime = { assertObject: assertObject, - asyncWrap: asyncWrap, + createPrivateName: createPrivateName, exportStar: exportStar, - initGeneratorFunction: initGeneratorFunction, - createGeneratorInstance: createGeneratorInstance, getOwnHashObject: getOwnHashObject, setProperty: setProperty, setupGlobals: setupGlobals,