diff options
Diffstat (limited to 'web/src/vendor/react/JSXTransformer.js')
-rw-r--r-- | web/src/vendor/react/JSXTransformer.js | 4575 |
1 files changed, 3164 insertions, 1411 deletions
diff --git a/web/src/vendor/react/JSXTransformer.js b/web/src/vendor/react/JSXTransformer.js index 9a7bf5f0..be1cae1f 100644 --- a/web/src/vendor/react/JSXTransformer.js +++ b/web/src/vendor/react/JSXTransformer.js @@ -1,7 +1,348 @@ /** - * JSXTransformer v0.11.1 + * JSXTransformer v0.12.1 */ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.JSXTransformer=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.JSXTransformer=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ +/* jshint browser: true */ +/* jslint evil: true */ + +'use strict'; + +var buffer = _dereq_('buffer'); +var transform = _dereq_('jstransform').transform; +var typesSyntax = _dereq_('jstransform/visitors/type-syntax'); +var visitors = _dereq_('./fbtransform/visitors'); + +var headEl; +var dummyAnchor; +var inlineScriptCount = 0; + +// The source-map library relies on Object.defineProperty, but IE8 doesn't +// support it fully even with es5-sham. Indeed, es5-sham's defineProperty +// throws when Object.prototype.__defineGetter__ is missing, so we skip building +// the source map in that case. +var supportsAccessors = Object.prototype.hasOwnProperty('__defineGetter__'); + +/** + * Run provided code through jstransform. + * + * @param {string} source Original source code + * @param {object?} options Options to pass to jstransform + * @return {object} object as returned from jstransform + */ +function transformReact(source, options) { + // TODO: just use react-tools + options = options || {}; + var visitorList; + if (options.harmony) { + visitorList = visitors.getAllVisitors(); + } else { + visitorList = visitors.transformVisitors.react; + } + + if (options.stripTypes) { + // Stripping types needs to happen before the other transforms + // unfortunately, due to bad interactions. For example, + // es6-rest-param-visitors conflict with stripping rest param type + // annotation + source = transform(typesSyntax.visitorList, source, options).code; + } + + return transform(visitorList, source, { + sourceMap: supportsAccessors && options.sourceMap + }); +} + +/** + * Eval provided source after transforming it. + * + * @param {string} source Original source code + * @param {object?} options Options to pass to jstransform + */ +function exec(source, options) { + return eval(transformReact(source, options).code); +} + +/** + * This method returns a nicely formated line of code pointing to the exact + * location of the error `e`. The line is limited in size so big lines of code + * are also shown in a readable way. + * + * Example: + * ... x', overflow:'scroll'}} id={} onScroll={this.scroll} class=" ... + * ^ + * + * @param {string} code The full string of code + * @param {Error} e The error being thrown + * @return {string} formatted message + * @internal + */ +function createSourceCodeErrorMessage(code, e) { + var sourceLines = code.split('\n'); + var erroneousLine = sourceLines[e.lineNumber - 1]; + + // Removes any leading indenting spaces and gets the number of + // chars indenting the `erroneousLine` + var indentation = 0; + erroneousLine = erroneousLine.replace(/^\s+/, function(leadingSpaces) { + indentation = leadingSpaces.length; + return ''; + }); + + // Defines the number of characters that are going to show + // before and after the erroneous code + var LIMIT = 30; + var errorColumn = e.column - indentation; + + if (errorColumn > LIMIT) { + erroneousLine = '... ' + erroneousLine.slice(errorColumn - LIMIT); + errorColumn = 4 + LIMIT; + } + if (erroneousLine.length - errorColumn > LIMIT) { + erroneousLine = erroneousLine.slice(0, errorColumn + LIMIT) + ' ...'; + } + var message = '\n\n' + erroneousLine + '\n'; + message += new Array(errorColumn - 1).join(' ') + '^'; + return message; +} + +/** + * Actually transform the code. + * + * @param {string} code + * @param {string?} url + * @param {object?} options + * @return {string} The transformed code. + * @internal + */ +function transformCode(code, url, options) { + try { + var transformed = transformReact(code, options); + } catch(e) { + e.message += '\n at '; + if (url) { + if ('fileName' in e) { + // We set `fileName` if it's supported by this error object and + // a `url` was provided. + // The error will correctly point to `url` in Firefox. + e.fileName = url; + } + e.message += url + ':' + e.lineNumber + ':' + e.column; + } else { + e.message += location.href; + } + e.message += createSourceCodeErrorMessage(code, e); + throw e; + } + + if (!transformed.sourceMap) { + return transformed.code; + } + + var map = transformed.sourceMap.toJSON(); + var source; + if (url == null) { + source = "Inline JSX script"; + inlineScriptCount++; + if (inlineScriptCount > 1) { + source += ' (' + inlineScriptCount + ')'; + } + } else if (dummyAnchor) { + // Firefox has problems when the sourcemap source is a proper URL with a + // protocol and hostname, so use the pathname. We could use just the + // filename, but hopefully using the full path will prevent potential + // issues where the same filename exists in multiple directories. + dummyAnchor.href = url; + source = dummyAnchor.pathname.substr(1); + } + map.sources = [source]; + map.sourcesContent = [code]; + + return ( + transformed.code + + '\n//# sourceMappingURL=data:application/json;base64,' + + buffer.Buffer(JSON.stringify(map)).toString('base64') + ); +} + + +/** + * Appends a script element at the end of the <head> with the content of code, + * after transforming it. + * + * @param {string} code The original source code + * @param {string?} url Where the code came from. null if inline + * @param {object?} options Options to pass to jstransform + * @internal + */ +function run(code, url, options) { + var scriptEl = document.createElement('script'); + scriptEl.text = transformCode(code, url, options); + headEl.appendChild(scriptEl); +} + +/** + * Load script from the provided url and pass the content to the callback. + * + * @param {string} url The location of the script src + * @param {function} callback Function to call with the content of url + * @internal + */ +function load(url, successCallback, errorCallback) { + var xhr; + xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') + : new XMLHttpRequest(); + + // async, however scripts will be executed in the order they are in the + // DOM to mirror normal script loading. + xhr.open('GET', url, true); + if ('overrideMimeType' in xhr) { + xhr.overrideMimeType('text/plain'); + } + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + if (xhr.status === 0 || xhr.status === 200) { + successCallback(xhr.responseText); + } else { + errorCallback(); + throw new Error("Could not load " + url); + } + } + }; + return xhr.send(null); +} + +/** + * Loop over provided script tags and get the content, via innerHTML if an + * inline script, or by using XHR. Transforms are applied if needed. The scripts + * are executed in the order they are found on the page. + * + * @param {array} scripts The <script> elements to load and run. + * @internal + */ +function loadScripts(scripts) { + var result = []; + var count = scripts.length; + + function check() { + var script, i; + + for (i = 0; i < count; i++) { + script = result[i]; + + if (script.loaded && !script.executed) { + script.executed = true; + run(script.content, script.url, script.options); + } else if (!script.loaded && !script.error && !script.async) { + break; + } + } + } + + scripts.forEach(function(script, i) { + var options = { + sourceMap: true + }; + if (/;harmony=true(;|$)/.test(script.type)) { + options.harmony = true + } + if (/;stripTypes=true(;|$)/.test(script.type)) { + options.stripTypes = true; + } + + // script.async is always true for non-javascript script tags + var async = script.hasAttribute('async'); + + if (script.src) { + result[i] = { + async: async, + error: false, + executed: false, + content: null, + loaded: false, + url: script.src, + options: options + }; + + load(script.src, function(content) { + result[i].loaded = true; + result[i].content = content; + check(); + }, function() { + result[i].error = true; + check(); + }); + } else { + result[i] = { + async: async, + error: false, + executed: false, + content: script.innerHTML, + loaded: true, + url: null, + options: options + }; + } + }); + + check(); +} + +/** + * Find and run all script tags with type="text/jsx". + * + * @internal + */ +function runScripts() { + var scripts = document.getElementsByTagName('script'); + + // Array.prototype.slice cannot be used on NodeList on IE8 + var jsxScripts = []; + for (var i = 0; i < scripts.length; i++) { + if (/^text\/jsx(;|$)/.test(scripts.item(i).type)) { + jsxScripts.push(scripts.item(i)); + } + } + + if (jsxScripts.length < 1) { + return; + } + + console.warn( + 'You are using the in-browser JSX transformer. Be sure to precompile ' + + 'your JSX for production - ' + + 'http://facebook.github.io/react/docs/tooling-integration.html#jsx' + ); + + loadScripts(jsxScripts); +} + +// Listen for load event if we're in a browser and then kick off finding and +// running of scripts. +if (typeof window !== "undefined" && window !== null) { + headEl = document.getElementsByTagName('head')[0]; + dummyAnchor = document.createElement('a'); + + if (window.addEventListener) { + window.addEventListener('DOMContentLoaded', runScripts, false); + } else { + window.attachEvent('onload', runScripts); + } +} + +module.exports = { + transform: transformReact, + exec: exec +}; + +},{"./fbtransform/visitors":37,"buffer":2,"jstransform":21,"jstransform/visitors/type-syntax":33}],2:[function(_dereq_,module,exports){ /*! * The buffer module from node.js, for the browser. * @@ -11,29 +352,45 @@ var base64 = _dereq_('base64-js') var ieee754 = _dereq_('ieee754') +var isArray = _dereq_('is-array') exports.Buffer = Buffer exports.SlowBuffer = Buffer exports.INSPECT_MAX_BYTES = 50 -Buffer.poolSize = 8192 +Buffer.poolSize = 8192 // not used by this implementation + +var kMaxLength = 0x3fffffff /** - * If `Buffer._useTypedArrays`: + * If `Buffer.TYPED_ARRAY_SUPPORT`: * === true Use Uint8Array implementation (fastest) - * === false Use Object implementation (compatible down to IE6) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Note: + * + * - Implementation must support adding new properties to `Uint8Array` instances. + * Firefox 4-29 lacked support, fixed in Firefox 30+. + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + * + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will + * get the Object implementation, which is slower but will work correctly. */ -Buffer._useTypedArrays = (function () { - // Detect if browser supports Typed Arrays. Supported browsers are IE 10+, Firefox 4+, - // Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. If the browser does not support adding - // properties to `Uint8Array` instances, then that's the same as no `Uint8Array` support - // because we need to be able to add all the node Buffer API methods. This is an issue - // in Firefox 4-29. Now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438 +Buffer.TYPED_ARRAY_SUPPORT = (function () { try { var buf = new ArrayBuffer(0) var arr = new Uint8Array(buf) arr.foo = function () { return 42 } - return 42 === arr.foo() && - typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray` + return 42 === arr.foo() && // typed array instances can be augmented + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` } catch (e) { return false } @@ -66,14 +423,18 @@ function Buffer (subject, encoding, noZero) { subject = base64clean(subject) length = Buffer.byteLength(subject, encoding) } else if (type === 'object' && subject !== null) { // assume object is array-like - if (subject.type === 'Buffer' && Array.isArray(subject.data)) + if (subject.type === 'Buffer' && isArray(subject.data)) subject = subject.data length = +subject.length > 0 ? Math.floor(+subject.length) : 0 } else - throw new Error('First argument needs to be a number, array or string.') + throw new TypeError('must start with number, buffer, array or string') + + if (this.length > kMaxLength) + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength.toString(16) + ' bytes') var buf - if (Buffer._useTypedArrays) { + if (Buffer.TYPED_ARRAY_SUPPORT) { // Preferred: Return an augmented `Uint8Array` instance for best performance buf = Buffer._augment(new Uint8Array(length)) } else { @@ -84,7 +445,7 @@ function Buffer (subject, encoding, noZero) { } var i - if (Buffer._useTypedArrays && typeof subject.byteLength === 'number') { + if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') { // Speed optimization -- use set if we're copying from a typed array buf._set(subject) } else if (isArrayish(subject)) { @@ -98,7 +459,7 @@ function Buffer (subject, encoding, noZero) { } } else if (type === 'string') { buf.write(subject, 0, encoding) - } else if (type === 'number' && !Buffer._useTypedArrays && !noZero) { + } else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) { for (i = 0; i < length; i++) { buf[i] = 0 } @@ -107,8 +468,25 @@ function Buffer (subject, encoding, noZero) { return buf } -// STATIC METHODS -// ============== +Buffer.isBuffer = function (b) { + return !!(b != null && b._isBuffer) +} + +Buffer.compare = function (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) + throw new TypeError('Arguments must be Buffers') + + var x = a.length + var y = b.length + for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {} + if (i !== len) { + x = a[i] + y = b[i] + } + if (x < y) return -1 + if (y < x) return 1 + return 0 +} Buffer.isEncoding = function (encoding) { switch (String(encoding).toLowerCase()) { @@ -129,43 +507,8 @@ Buffer.isEncoding = function (encoding) { } } -Buffer.isBuffer = function (b) { - return !!(b != null && b._isBuffer) -} - -Buffer.byteLength = function (str, encoding) { - var ret - str = str.toString() - switch (encoding || 'utf8') { - case 'hex': - ret = str.length / 2 - break - case 'utf8': - case 'utf-8': - ret = utf8ToBytes(str).length - break - case 'ascii': - case 'binary': - case 'raw': - ret = str.length - break - case 'base64': - ret = base64ToBytes(str).length - break - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - ret = str.length * 2 - break - default: - throw new Error('Unknown encoding') - } - return ret -} - Buffer.concat = function (list, totalLength) { - assert(isArray(list), 'Usage: Buffer.concat(list[, length])') + if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])') if (list.length === 0) { return new Buffer(0) @@ -191,26 +534,118 @@ Buffer.concat = function (list, totalLength) { return buf } -Buffer.compare = function (a, b) { - assert(Buffer.isBuffer(a) && Buffer.isBuffer(b), 'Arguments must be Buffers') - var x = a.length - var y = b.length - for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {} - if (i !== len) { - x = a[i] - y = b[i] +Buffer.byteLength = function (str, encoding) { + var ret + str = str + '' + switch (encoding || 'utf8') { + case 'ascii': + case 'binary': + case 'raw': + ret = str.length + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = str.length * 2 + break + case 'hex': + ret = str.length >>> 1 + break + case 'utf8': + case 'utf-8': + ret = utf8ToBytes(str).length + break + case 'base64': + ret = base64ToBytes(str).length + break + default: + ret = str.length } - if (x < y) { - return -1 + return ret +} + +// pre-set for values that may exist in the future +Buffer.prototype.length = undefined +Buffer.prototype.parent = undefined + +// toString(encoding, start=0, end=buffer.length) +Buffer.prototype.toString = function (encoding, start, end) { + var loweredCase = false + + start = start >>> 0 + end = end === undefined || end === Infinity ? this.length : end >>> 0 + + if (!encoding) encoding = 'utf8' + if (start < 0) start = 0 + if (end > this.length) end = this.length + if (end <= start) return '' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'binary': + return binarySlice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) + throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } } - if (y < x) { - return 1 +} + +Buffer.prototype.equals = function (b) { + if(!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) + str += ' ... ' } - return 0 + return '<Buffer ' + str + '>' +} + +Buffer.prototype.compare = function (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) +} + +// `get` will be removed in Node 0.13+ +Buffer.prototype.get = function (offset) { + console.log('.get() is deprecated. Access using array indexes instead.') + return this.readUInt8(offset) } -// BUFFER INSTANCE METHODS -// ======================= +// `set` will be removed in Node 0.13+ +Buffer.prototype.set = function (v, offset) { + console.log('.set() is deprecated. Access using array indexes instead.') + return this.writeUInt8(v, offset) +} function hexWrite (buf, string, offset, length) { offset = Number(offset) || 0 @@ -226,14 +661,14 @@ function hexWrite (buf, string, offset, length) { // must be an even number of digits var strLen = string.length - assert(strLen % 2 === 0, 'Invalid hex string') + if (strLen % 2 !== 0) throw new Error('Invalid hex string') if (length > strLen / 2) { length = strLen / 2 } for (var i = 0; i < length; i++) { var byte = parseInt(string.substr(i * 2, 2), 16) - assert(!isNaN(byte), 'Invalid hex string') + if (isNaN(byte)) throw new Error('Invalid hex string') buf[offset + i] = byte } return i @@ -315,48 +750,7 @@ Buffer.prototype.write = function (string, offset, length, encoding) { ret = utf16leWrite(this, string, offset, length) break default: - throw new Error('Unknown encoding') - } - return ret -} - -Buffer.prototype.toString = function (encoding, start, end) { - var self = this - - encoding = String(encoding || 'utf8').toLowerCase() - start = Number(start) || 0 - end = (end === undefined) ? self.length : Number(end) - - // Fastpath empty strings - if (end === start) - return '' - - var ret - switch (encoding) { - case 'hex': - ret = hexSlice(self, start, end) - break - case 'utf8': - case 'utf-8': - ret = utf8Slice(self, start, end) - break - case 'ascii': - ret = asciiSlice(self, start, end) - break - case 'binary': - ret = binarySlice(self, start, end) - break - case 'base64': - ret = base64Slice(self, start, end) - break - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - ret = utf16leSlice(self, start, end) - break - default: - throw new Error('Unknown encoding') + throw new TypeError('Unknown encoding: ' + encoding) } return ret } @@ -368,52 +762,6 @@ Buffer.prototype.toJSON = function () { } } -Buffer.prototype.equals = function (b) { - assert(Buffer.isBuffer(b), 'Argument must be a Buffer') - return Buffer.compare(this, b) === 0 -} - -Buffer.prototype.compare = function (b) { - assert(Buffer.isBuffer(b), 'Argument must be a Buffer') - return Buffer.compare(this, b) -} - -// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -Buffer.prototype.copy = function (target, target_start, start, end) { - var source = this - - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (!target_start) target_start = 0 - - // Copy 0 bytes; we're done - if (end === start) return - if (target.length === 0 || source.length === 0) return - - // Fatal error conditions - assert(end >= start, 'sourceEnd < sourceStart') - assert(target_start >= 0 && target_start < target.length, - 'targetStart out of bounds') - assert(start >= 0 && start < source.length, 'sourceStart out of bounds') - assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds') - - // Are we oob? - if (end > this.length) - end = this.length - if (target.length - target_start < end - start) - end = target.length - target_start + start - - var len = end - start - - if (len < 100 || !Buffer._useTypedArrays) { - for (var i = 0; i < len; i++) { - target[i + target_start] = this[i + start] - } - } else { - target._set(this.subarray(start, start + len), target_start) - } -} - function base64Slice (buf, start, end) { if (start === 0 && end === buf.length) { return base64.fromByteArray(buf) @@ -499,7 +847,7 @@ Buffer.prototype.slice = function (start, end) { if (end < start) end = start - if (Buffer._useTypedArrays) { + if (Buffer.TYPED_ARRAY_SUPPORT) { return Buffer._augment(this.subarray(start, end)) } else { var sliceLen = end - start @@ -511,365 +859,275 @@ Buffer.prototype.slice = function (start, end) { } } -// `get` will be removed in Node 0.13+ -Buffer.prototype.get = function (offset) { - console.log('.get() is deprecated. Access using array indexes instead.') - return this.readUInt8(offset) -} - -// `set` will be removed in Node 0.13+ -Buffer.prototype.set = function (v, offset) { - console.log('.set() is deprecated. Access using array indexes instead.') - return this.writeUInt8(v, offset) +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) + throw new RangeError('offset is not uint') + if (offset + ext > length) + throw new RangeError('Trying to access beyond buffer length') } Buffer.prototype.readUInt8 = function (offset, noAssert) { - if (!noAssert) { - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset < this.length, 'Trying to read beyond buffer length') - } - - if (offset >= this.length) - return - + if (!noAssert) + checkOffset(offset, 1, this.length) return this[offset] } -function readUInt16 (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') - } - - var len = buf.length - if (offset >= len) - return - - var val - if (littleEndian) { - val = buf[offset] - if (offset + 1 < len) - val |= buf[offset + 1] << 8 - } else { - val = buf[offset] << 8 - if (offset + 1 < len) - val |= buf[offset + 1] - } - return val -} - Buffer.prototype.readUInt16LE = function (offset, noAssert) { - return readUInt16(this, offset, true, noAssert) + if (!noAssert) + checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) } Buffer.prototype.readUInt16BE = function (offset, noAssert) { - return readUInt16(this, offset, false, noAssert) -} - -function readUInt32 (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') - } - - var len = buf.length - if (offset >= len) - return - - var val - if (littleEndian) { - if (offset + 2 < len) - val = buf[offset + 2] << 16 - if (offset + 1 < len) - val |= buf[offset + 1] << 8 - val |= buf[offset] - if (offset + 3 < len) - val = val + (buf[offset + 3] << 24 >>> 0) - } else { - if (offset + 1 < len) - val = buf[offset + 1] << 16 - if (offset + 2 < len) - val |= buf[offset + 2] << 8 - if (offset + 3 < len) - val |= buf[offset + 3] - val = val + (buf[offset] << 24 >>> 0) - } - return val + if (!noAssert) + checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] } Buffer.prototype.readUInt32LE = function (offset, noAssert) { - return readUInt32(this, offset, true, noAssert) -} + if (!noAssert) + checkOffset(offset, 4, this.length) -Buffer.prototype.readUInt32BE = function (offset, noAssert) { - return readUInt32(this, offset, false, noAssert) + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) } -Buffer.prototype.readInt8 = function (offset, noAssert) { - if (!noAssert) { - assert(offset !== undefined && offset !== null, - 'missing offset') - assert(offset < this.length, 'Trying to read beyond buffer length') - } - - if (offset >= this.length) - return +Buffer.prototype.readUInt32BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) - var neg = this[offset] & 0x80 - if (neg) - return (0xff - this[offset] + 1) * -1 - else - return this[offset] + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) } -function readInt16 (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') - } - - var len = buf.length - if (offset >= len) - return - - var val = readUInt16(buf, offset, littleEndian, true) - var neg = val & 0x8000 - if (neg) - return (0xffff - val + 1) * -1 - else - return val +Buffer.prototype.readInt8 = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) + return (this[offset]) + return ((0xff - this[offset] + 1) * -1) } Buffer.prototype.readInt16LE = function (offset, noAssert) { - return readInt16(this, offset, true, noAssert) + if (!noAssert) + checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt16BE = function (offset, noAssert) { - return readInt16(this, offset, false, noAssert) -} - -function readInt32 (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') - } - - var len = buf.length - if (offset >= len) - return - - var val = readUInt32(buf, offset, littleEndian, true) - var neg = val & 0x80000000 - if (neg) - return (0xffffffff - val + 1) * -1 - else - return val + if (!noAssert) + checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt32LE = function (offset, noAssert) { - return readInt32(this, offset, true, noAssert) -} + if (!noAssert) + checkOffset(offset, 4, this.length) -Buffer.prototype.readInt32BE = function (offset, noAssert) { - return readInt32(this, offset, false, noAssert) + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) } -function readFloat (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') - } +Buffer.prototype.readInt32BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) - return ieee754.read(buf, offset, littleEndian, 23, 4) + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) } Buffer.prototype.readFloatLE = function (offset, noAssert) { - return readFloat(this, offset, true, noAssert) + if (!noAssert) + checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) } Buffer.prototype.readFloatBE = function (offset, noAssert) { - return readFloat(this, offset, false, noAssert) -} - -function readDouble (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset + 7 < buf.length, 'Trying to read beyond buffer length') - } - - return ieee754.read(buf, offset, littleEndian, 52, 8) + if (!noAssert) + checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) } Buffer.prototype.readDoubleLE = function (offset, noAssert) { - return readDouble(this, offset, true, noAssert) + if (!noAssert) + checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) } Buffer.prototype.readDoubleBE = function (offset, noAssert) { - return readDouble(this, offset, false, noAssert) + if (!noAssert) + checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) } -Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset < this.length, 'trying to write beyond buffer length') - verifuint(value, 0xff) - } - - if (offset >= this.length) return +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') +} +Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 1, 0xff, 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) this[offset] = value return offset + 1 } -function writeUInt16 (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 1 < buf.length, 'trying to write beyond buffer length') - verifuint(value, 0xffff) - } - - var len = buf.length - if (offset >= len) - return - - for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) { - buf[offset + i] = - (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> - (littleEndian ? i : 1 - i) * 8 +function objectWriteUInt16 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 } - return offset + 2 } Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { - return writeUInt16(this, value, offset, true, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else objectWriteUInt16(this, value, offset, true) + return offset + 2 } Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { - return writeUInt16(this, value, offset, false, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else objectWriteUInt16(this, value, offset, false) + return offset + 2 } -function writeUInt32 (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'trying to write beyond buffer length') - verifuint(value, 0xffffffff) - } - - var len = buf.length - if (offset >= len) - return - - for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) { - buf[offset + i] = - (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff +function objectWriteUInt32 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff } - return offset + 4 } Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { - return writeUInt32(this, value, offset, true, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = value + } else objectWriteUInt32(this, value, offset, true) + return offset + 4 } Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { - return writeUInt32(this, value, offset, false, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else objectWriteUInt32(this, value, offset, false) + return offset + 4 } Buffer.prototype.writeInt8 = function (value, offset, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset < this.length, 'Trying to write beyond buffer length') - verifsint(value, 0x7f, -0x80) - } - - if (offset >= this.length) - return - - if (value >= 0) - this.writeUInt8(value, offset, noAssert) - else - this.writeUInt8(0xff + value + 1, offset, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 1, 0x7f, -0x80) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + if (value < 0) value = 0xff + value + 1 + this[offset] = value return offset + 1 } -function writeInt16 (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 1 < buf.length, 'Trying to write beyond buffer length') - verifsint(value, 0x7fff, -0x8000) - } - - var len = buf.length - if (offset >= len) - return - - if (value >= 0) - writeUInt16(buf, value, offset, littleEndian, noAssert) - else - writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert) - return offset + 2 -} - Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { - return writeInt16(this, value, offset, true, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else objectWriteUInt16(this, value, offset, true) + return offset + 2 } Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { - return writeInt16(this, value, offset, false, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else objectWriteUInt16(this, value, offset, false) + return offset + 2 } -function writeInt32 (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') - verifsint(value, 0x7fffffff, -0x80000000) - } - - var len = buf.length - if (offset >= len) - return - - if (value >= 0) - writeUInt32(buf, value, offset, littleEndian, noAssert) - else - writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert) +Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + } else objectWriteUInt32(this, value, offset, true) return offset + 4 } -Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { - return writeInt32(this, value, offset, true, noAssert) +Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else objectWriteUInt32(this, value, offset, false) + return offset + 4 } -Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { - return writeInt32(this, value, offset, false, noAssert) +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') } function writeFloat (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') - verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38) - } - - var len = buf.length - if (offset >= len) - return - + if (!noAssert) + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) ieee754.write(buf, value, offset, littleEndian, 23, 4) return offset + 4 } @@ -883,19 +1141,8 @@ Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { } function writeDouble (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 7 < buf.length, - 'Trying to write beyond buffer length') - verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308) - } - - var len = buf.length - if (offset >= len) - return - + if (!noAssert) + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) ieee754.write(buf, value, offset, littleEndian, 52, 8) return offset + 8 } @@ -908,20 +1155,56 @@ Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { return writeDouble(this, value, offset, false, noAssert) } +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function (target, target_start, start, end) { + var source = this + + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (!target_start) target_start = 0 + + // Copy 0 bytes; we're done + if (end === start) return + if (target.length === 0 || source.length === 0) return + + // Fatal error conditions + if (end < start) throw new TypeError('sourceEnd < sourceStart') + if (target_start < 0 || target_start >= target.length) + throw new TypeError('targetStart out of bounds') + if (start < 0 || start >= source.length) throw new TypeError('sourceStart out of bounds') + if (end < 0 || end > source.length) throw new TypeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) + end = this.length + if (target.length - target_start < end - start) + end = target.length - target_start + start + + var len = end - start + + if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < len; i++) { + target[i + target_start] = this[i + start] + } + } else { + target._set(this.subarray(start, start + len), target_start) + } +} + // fill(value, start=0, end=buffer.length) Buffer.prototype.fill = function (value, start, end) { if (!value) value = 0 if (!start) start = 0 if (!end) end = this.length - assert(end >= start, 'end < start') + if (end < start) throw new TypeError('end < start') // Fill 0 bytes; we're done if (end === start) return if (this.length === 0) return - assert(start >= 0 && start < this.length, 'start out of bounds') - assert(end >= 0 && end <= this.length, 'end out of bounds') + if (start < 0 || start >= this.length) throw new TypeError('start out of bounds') + if (end < 0 || end > this.length) throw new TypeError('end out of bounds') var i if (typeof value === 'number') { @@ -939,26 +1222,13 @@ Buffer.prototype.fill = function (value, start, end) { return this } -Buffer.prototype.inspect = function () { - var out = [] - var len = this.length - for (var i = 0; i < len; i++) { - out[i] = toHex(this[i]) - if (i === exports.INSPECT_MAX_BYTES) { - out[i + 1] = '...' - break - } - } - return '<Buffer ' + out.join(' ') + '>' -} - /** * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. * Added in Node 0.12. Only available in browsers that support ArrayBuffer. */ Buffer.prototype.toArrayBuffer = function () { if (typeof Uint8Array !== 'undefined') { - if (Buffer._useTypedArrays) { + if (Buffer.TYPED_ARRAY_SUPPORT) { return (new Buffer(this)).buffer } else { var buf = new Uint8Array(this.length) @@ -968,7 +1238,7 @@ Buffer.prototype.toArrayBuffer = function () { return buf.buffer } } else { - throw new Error('Buffer.toArrayBuffer not supported in this browser') + throw new TypeError('Buffer.toArrayBuffer not supported in this browser') } } @@ -981,6 +1251,7 @@ var BP = Buffer.prototype * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods */ Buffer._augment = function (arr) { + arr.constructor = Buffer arr._isBuffer = true // save reference to original Uint8Array get/set methods before overwriting @@ -1051,12 +1322,6 @@ function stringtrim (str) { return str.replace(/^\s+|\s+$/g, '') } -function isArray (subject) { - return (Array.isArray || function (subject) { - return Object.prototype.toString.call(subject) === '[object Array]' - })(subject) -} - function isArrayish (subject) { return isArray(subject) || Buffer.isBuffer(subject) || subject && typeof subject === 'object' && @@ -1130,36 +1395,7 @@ function decodeUtf8Char (str) { } } -/* - * We have to make sure that the value is a valid integer. This means that it - * is non-negative. It has no fractional component and that it does not - * exceed the maximum allowed value. - */ -function verifuint (value, max) { - assert(typeof value === 'number', 'cannot write a non-number as a number') - assert(value >= 0, 'specified a negative value for writing an unsigned value') - assert(value <= max, 'value is larger than maximum value for type') - assert(Math.floor(value) === value, 'value has a fractional component') -} - -function verifsint (value, max, min) { - assert(typeof value === 'number', 'cannot write a non-number as a number') - assert(value <= max, 'value larger than maximum allowed value') - assert(value >= min, 'value smaller than minimum allowed value') - assert(Math.floor(value) === value, 'value has a fractional component') -} - -function verifIEEE754 (value, max, min) { - assert(typeof value === 'number', 'cannot write a non-number as a number') - assert(value <= max, 'value larger than maximum allowed value') - assert(value >= min, 'value smaller than minimum allowed value') -} - -function assert (test, message) { - if (!test) throw new Error(message || 'Failed assertion') -} - -},{"base64-js":2,"ieee754":3}],2:[function(_dereq_,module,exports){ +},{"base64-js":3,"ieee754":4,"is-array":5}],3:[function(_dereq_,module,exports){ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; ;(function (exports) { @@ -1281,7 +1517,7 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; exports.fromByteArray = uint8ToBase64 }(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) -},{}],3:[function(_dereq_,module,exports){ +},{}],4:[function(_dereq_,module,exports){ exports.read = function(buffer, offset, isLE, mLen, nBytes) { var e, m, eLen = nBytes * 8 - mLen - 1, @@ -1367,7 +1603,42 @@ exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128; }; -},{}],4:[function(_dereq_,module,exports){ +},{}],5:[function(_dereq_,module,exports){ + +/** + * isArray + */ + +var isArray = Array.isArray; + +/** + * toString + */ + +var str = Object.prototype.toString; + +/** + * Whether or not the given `val` + * is an array. + * + * example: + * + * isArray([]); + * // > true + * isArray(arguments); + * // > false + * isArray(''); + * // > false + * + * @param {mixed} val + * @return {bool} + */ + +module.exports = isArray || function (val) { + return !! val && '[object Array]' == str.call(val); +}; + +},{}],6:[function(_dereq_,module,exports){ (function (process){ // Copyright Joyent, Inc. and other Node contributors. // @@ -1594,8 +1865,8 @@ var substr = 'ab'.substr(-1) === 'b' } ; -}).call(this,_dereq_("FWaASH")) -},{"FWaASH":5}],5:[function(_dereq_,module,exports){ +}).call(this,_dereq_('_process')) +},{"_process":7}],7:[function(_dereq_,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -1603,6 +1874,8 @@ var process = module.exports = {}; process.nextTick = (function () { var canSetImmediate = typeof window !== 'undefined' && window.setImmediate; + var canMutationObserver = typeof window !== 'undefined' + && window.MutationObserver; var canPost = typeof window !== 'undefined' && window.postMessage && window.addEventListener ; @@ -1611,8 +1884,29 @@ process.nextTick = (function () { return function (f) { return window.setImmediate(f) }; } + var queue = []; + + if (canMutationObserver) { + var hiddenDiv = document.createElement("div"); + var observer = new MutationObserver(function () { + var queueList = queue.slice(); + queue.length = 0; + queueList.forEach(function (fn) { + fn(); + }); + }); + + observer.observe(hiddenDiv, { attributes: true }); + + return function nextTick(fn) { + if (!queue.length) { + hiddenDiv.setAttribute('yes', 'no'); + } + queue.push(fn); + }; + } + if (canPost) { - var queue = []; window.addEventListener('message', function (ev) { var source = ev.source; if ((source === window || source === null) && ev.data === 'process-tick') { @@ -1652,7 +1946,7 @@ process.emit = noop; process.binding = function (name) { throw new Error('process.binding is not supported'); -} +}; // TODO(shtylman) process.cwd = function () { return '/' }; @@ -1660,7 +1954,35 @@ process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; -},{}],6:[function(_dereq_,module,exports){ +},{}],8:[function(_dereq_,module,exports){ +var Base62 = (function (my) { + my.chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] + + my.encode = function(i){ + if (i === 0) {return '0'} + var s = '' + while (i > 0) { + s = this.chars[i % 62] + s + i = Math.floor(i/62) + } + return s + }; + my.decode = function(a,b,c,d){ + for ( + b = c = ( + a === (/\W|_|^$/.test(a += "") || a) + ) - 1; + d = a.charCodeAt(c++); + ) + b = b * 62 + d - [, 48, 29, 87][d >> 5]; + return b + }; + + return my; +}({})); + +module.exports = Base62 +},{}],9:[function(_dereq_,module,exports){ /* Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com> Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com> @@ -1698,18 +2020,23 @@ process.chdir = function (dir) { throwError: true, generateStatement: true, peek: true, parseAssignmentExpression: true, parseBlock: true, parseClassExpression: true, parseClassDeclaration: true, parseExpression: true, +parseDeclareClass: true, parseDeclareFunction: true, +parseDeclareModule: true, parseDeclareVariable: true, parseForStatement: true, parseFunctionDeclaration: true, parseFunctionExpression: true, parseFunctionSourceElements: true, parseVariableIdentifier: true, -parseImportSpecifier: true, +parseImportSpecifier: true, parseInterface: true, parseLeftHandSideExpression: true, parseParams: true, validateParam: true, parseSpreadOrAssignmentExpression: true, -parseStatement: true, parseSourceElement: true, parseModuleBlock: true, parseConciseBody: true, +parseStatement: true, parseSourceElement: true, parseConciseBody: true, advanceXJSChild: true, isXJSIdentifierStart: true, isXJSIdentifierPart: true, scanXJSStringLiteral: true, scanXJSIdentifier: true, parseXJSAttributeValue: true, parseXJSChild: true, parseXJSElement: true, parseXJSExpressionContainer: true, parseXJSEmptyExpression: true, -parseTypeAnnotation: true, parseTypeAnnotatableIdentifier: true, -parseYieldExpression: true +parseFunctionTypeParam: true, +parsePrimaryType: true, +parseTypeAlias: true, +parseType: true, parseTypeAnnotatableIdentifier: true, parseTypeAnnotation: true, +parseYieldExpression: true, parseAwaitExpression: true */ (function (root, factory) { @@ -1788,24 +2115,32 @@ parseYieldExpression: true '<=', '<', '>', '!=', '!==']; Syntax = { + AnyTypeAnnotation: 'AnyTypeAnnotation', ArrayExpression: 'ArrayExpression', ArrayPattern: 'ArrayPattern', + ArrayTypeAnnotation: 'ArrayTypeAnnotation', ArrowFunctionExpression: 'ArrowFunctionExpression', AssignmentExpression: 'AssignmentExpression', BinaryExpression: 'BinaryExpression', BlockStatement: 'BlockStatement', + BooleanTypeAnnotation: 'BooleanTypeAnnotation', BreakStatement: 'BreakStatement', CallExpression: 'CallExpression', CatchClause: 'CatchClause', ClassBody: 'ClassBody', ClassDeclaration: 'ClassDeclaration', ClassExpression: 'ClassExpression', + ClassImplements: 'ClassImplements', ClassProperty: 'ClassProperty', ComprehensionBlock: 'ComprehensionBlock', ComprehensionExpression: 'ComprehensionExpression', ConditionalExpression: 'ConditionalExpression', ContinueStatement: 'ContinueStatement', DebuggerStatement: 'DebuggerStatement', + DeclareClass: 'DeclareClass', + DeclareFunction: 'DeclareFunction', + DeclareModule: 'DeclareModule', + DeclareVariable: 'DeclareVariable', DoWhileStatement: 'DoWhileStatement', EmptyStatement: 'EmptyStatement', ExportDeclaration: 'ExportDeclaration', @@ -1817,29 +2152,42 @@ parseYieldExpression: true ForStatement: 'ForStatement', FunctionDeclaration: 'FunctionDeclaration', FunctionExpression: 'FunctionExpression', + FunctionTypeAnnotation: 'FunctionTypeAnnotation', + FunctionTypeParam: 'FunctionTypeParam', + GenericTypeAnnotation: 'GenericTypeAnnotation', Identifier: 'Identifier', IfStatement: 'IfStatement', ImportDeclaration: 'ImportDeclaration', + ImportDefaultSpecifier: 'ImportDefaultSpecifier', + ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', ImportSpecifier: 'ImportSpecifier', + InterfaceDeclaration: 'InterfaceDeclaration', + InterfaceExtends: 'InterfaceExtends', + IntersectionTypeAnnotation: 'IntersectionTypeAnnotation', LabeledStatement: 'LabeledStatement', Literal: 'Literal', LogicalExpression: 'LogicalExpression', MemberExpression: 'MemberExpression', MethodDefinition: 'MethodDefinition', - ModuleDeclaration: 'ModuleDeclaration', + ModuleSpecifier: 'ModuleSpecifier', NewExpression: 'NewExpression', + NullableTypeAnnotation: 'NullableTypeAnnotation', + NumberTypeAnnotation: 'NumberTypeAnnotation', ObjectExpression: 'ObjectExpression', ObjectPattern: 'ObjectPattern', ObjectTypeAnnotation: 'ObjectTypeAnnotation', - OptionalParameter: 'OptionalParameter', - ParametricTypeAnnotation: 'ParametricTypeAnnotation', - ParametricallyTypedIdentifier: 'ParametricallyTypedIdentifier', + ObjectTypeCallProperty: 'ObjectTypeCallProperty', + ObjectTypeIndexer: 'ObjectTypeIndexer', + ObjectTypeProperty: 'ObjectTypeProperty', Program: 'Program', Property: 'Property', + QualifiedTypeIdentifier: 'QualifiedTypeIdentifier', ReturnStatement: 'ReturnStatement', SequenceExpression: 'SequenceExpression', SpreadElement: 'SpreadElement', SpreadProperty: 'SpreadProperty', + StringLiteralTypeAnnotation: 'StringLiteralTypeAnnotation', + StringTypeAnnotation: 'StringTypeAnnotation', SwitchCase: 'SwitchCase', SwitchStatement: 'SwitchStatement', TaggedTemplateExpression: 'TaggedTemplateExpression', @@ -1847,10 +2195,15 @@ parseYieldExpression: true TemplateLiteral: 'TemplateLiteral', ThisExpression: 'ThisExpression', ThrowStatement: 'ThrowStatement', + TupleTypeAnnotation: 'TupleTypeAnnotation', TryStatement: 'TryStatement', - TypeAnnotatedIdentifier: 'TypeAnnotatedIdentifier', + TypeAlias: 'TypeAlias', TypeAnnotation: 'TypeAnnotation', + TypeofTypeAnnotation: 'TypeofTypeAnnotation', + TypeParameterDeclaration: 'TypeParameterDeclaration', + TypeParameterInstantiation: 'TypeParameterInstantiation', UnaryExpression: 'UnaryExpression', + UnionTypeAnnotation: 'UnionTypeAnnotation', UpdateExpression: 'UpdateExpression', VariableDeclaration: 'VariableDeclaration', VariableDeclarator: 'VariableDeclarator', @@ -1868,7 +2221,8 @@ parseYieldExpression: true XJSAttribute: 'XJSAttribute', XJSSpreadAttribute: 'XJSSpreadAttribute', XJSText: 'XJSText', - YieldExpression: 'YieldExpression' + YieldExpression: 'YieldExpression', + AwaitExpression: 'AwaitExpression' }; PropertyKind = { @@ -1905,7 +2259,6 @@ parseYieldExpression: true IllegalBreak: 'Illegal break statement', IllegalDuplicateClassProperty: 'Illegal duplicate property in class definition', IllegalReturn: 'Illegal return statement', - IllegalYield: 'Illegal yield expression', IllegalSpread: 'Illegal spread element', StrictModeWith: 'Strict mode code may not include a with statement', StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', @@ -1928,23 +2281,29 @@ parseYieldExpression: true StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', StrictReservedWord: 'Use of future reserved word in strict mode', - NewlineAfterModule: 'Illegal newline after module', - NoFromAfterImport: 'Missing from after import', + MissingFromClause: 'Missing from clause', + NoAsAfterImportNamespace: 'Missing as after import *', InvalidModuleSpecifier: 'Invalid module specifier', - NestedModule: 'Module declaration can not be nested', NoUnintializedConst: 'Const must be initialized', ComprehensionRequiresBlock: 'Comprehension must have at least one block', ComprehensionError: 'Comprehension Error', EachNotAllowed: 'Each is not supported', InvalidXJSAttributeValue: 'XJS value should be either an expression or a quoted XJS text', ExpectedXJSClosingTag: 'Expected corresponding XJS closing tag for %0', - AdjacentXJSElements: 'Adjacent XJS elements must be wrapped in an enclosing tag' + AdjacentXJSElements: 'Adjacent XJS elements must be wrapped in an enclosing tag', + ConfusedAboutFunctionType: 'Unexpected token =>. It looks like ' + + 'you are trying to write a function type, but you ended up ' + + 'writing a grouped type followed by an =>, which is a syntax ' + + 'error. Remember, function type parameters are named so function ' + + 'types look like (name1: type1, name2: type2) => returnType. You ' + + 'probably wrote (type1) => returnType' }; // See also tools/generate-unicode-regex.py. Regex = { NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), - NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]') + NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), + LeadingZeros: new RegExp('^0+(?!$)') }; // Ensure the condition is true, otherwise throw an error. @@ -2106,14 +2465,16 @@ parseYieldExpression: true } } else if (blockComment) { if (isLineTerminator(ch)) { - if (ch === 13 && source.charCodeAt(index + 1) === 10) { + if (ch === 13) { ++index; } - ++lineNumber; - ++index; - lineStart = index; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + if (ch !== 13 || source.charCodeAt(index) === 10) { + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } } } else { ch = source.charCodeAt(index++); @@ -2461,7 +2822,9 @@ parseYieldExpression: true // Other 2-character punctuators: ++ -- << >> && || - if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) { + // Don't match these tokens if we're in a type, since they never can + // occur and can mess up types like Map<string, Array<string>> + if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0) && !state.inType) { index += 2; return { type: Token.Punctuator, @@ -2769,6 +3132,7 @@ parseYieldExpression: true if (ch === '\r' && source[index] === '\n') { ++index; } + lineStart = index; } } else if (isLineTerminator(ch.charCodeAt(0))) { break; @@ -2884,12 +3248,14 @@ parseYieldExpression: true if (ch === '\r' && source[index] === '\n') { ++index; } + lineStart = index; } } else if (isLineTerminator(ch.charCodeAt(0))) { ++lineNumber; if (ch === '\r' && source[index] === '\n') { ++index; } + lineStart = index; cooked += '\n'; } else { cooked += ch; @@ -2934,7 +3300,7 @@ parseYieldExpression: true } function scanRegExp() { - var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false; + var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false, tmp; lookahead = null; skipComment(); @@ -3010,19 +3376,43 @@ parseYieldExpression: true } } + tmp = pattern; + if (flags.indexOf('u') >= 0) { + // Replace each astral symbol and every Unicode code point + // escape sequence that represents such a symbol with a single + // ASCII symbol to avoid throwing on regular expressions that + // are only valid in combination with the `/u` flag. + tmp = tmp + .replace(/\\u\{([0-9a-fA-F]{5,6})\}/g, 'x') + .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x'); + } + + // First, detect invalid regular expressions. try { - value = new RegExp(pattern, flags); + value = new RegExp(tmp); } catch (e) { throwError({}, Messages.InvalidRegExp); } - peek(); + // Return a regular expression object for this pattern-flag pair, or + // `null` in case the current environment doesn't support the flags it + // uses. + try { + value = new RegExp(pattern, flags); + } catch (exception) { + value = null; + } + peek(); if (extra.tokenize) { return { type: Token.RegularExpression, value: value, + regex: { + pattern: pattern, + flags: flags + }, lineNumber: lineNumber, lineStart: lineStart, range: [start, index] @@ -3031,6 +3421,10 @@ parseYieldExpression: true return { literal: str, value: value, + regex: { + pattern: pattern, + flags: flags + }, range: [start, index] }; } @@ -3225,6 +3619,13 @@ parseYieldExpression: true return result; } + function rewind(token) { + index = token.range[0]; + lineNumber = token.lineNumber; + lineStart = token.lineStart; + lookahead = token; + } + function markerCreate() { if (!extra.loc && !extra.range) { return undefined; @@ -3240,6 +3641,57 @@ parseYieldExpression: true return {offset: index, line: lineNumber, col: index - lineStart}; } + function processComment(node) { + var lastChild, + trailingComments, + bottomRight = extra.bottomRightStack, + last = bottomRight[bottomRight.length - 1]; + + if (node.type === Syntax.Program) { + if (node.body.length > 0) { + return; + } + } + + if (extra.trailingComments.length > 0) { + if (extra.trailingComments[0].range[0] >= node.range[1]) { + trailingComments = extra.trailingComments; + extra.trailingComments = []; + } else { + extra.trailingComments.length = 0; + } + } else { + if (last && last.trailingComments && last.trailingComments[0].range[0] >= node.range[1]) { + trailingComments = last.trailingComments; + delete last.trailingComments; + } + } + + // Eating the stack. + if (last) { + while (last && last.range[0] >= node.range[0]) { + lastChild = last; + last = bottomRight.pop(); + } + } + + if (lastChild) { + if (lastChild.leadingComments && lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] <= node.range[0]) { + node.leadingComments = lastChild.leadingComments; + delete lastChild.leadingComments; + } + } else if (extra.leadingComments.length > 0 && extra.leadingComments[extra.leadingComments.length - 1].range[1] <= node.range[0]) { + node.leadingComments = extra.leadingComments; + extra.leadingComments = []; + } + + if (trailingComments) { + node.trailingComments = trailingComments; + } + + bottomRight.push(node); + } + function markerApply(marker, node) { if (extra.range) { node.range = [marker.offset, index]; @@ -3257,6 +3709,9 @@ parseYieldExpression: true }; node = delegate.postProcess(node); } + if (extra.attachComment) { + processComment(node); + } return node; } @@ -3398,8 +3853,8 @@ parseYieldExpression: true }, createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression, - returnType, parametricType) { - return { + isAsync, returnType, typeParameters) { + var funDecl = { type: Syntax.FunctionDeclaration, id: id, params: params, @@ -3409,13 +3864,19 @@ parseYieldExpression: true generator: generator, expression: expression, returnType: returnType, - parametricType: parametricType + typeParameters: typeParameters }; + + if (isAsync) { + funDecl.async = true; + } + + return funDecl; }, createFunctionExpression: function (id, params, defaults, body, rest, generator, expression, - returnType, parametricType) { - return { + isAsync, returnType, typeParameters) { + var funExpr = { type: Syntax.FunctionExpression, id: id, params: params, @@ -3425,8 +3886,14 @@ parseYieldExpression: true generator: generator, expression: expression, returnType: returnType, - parametricType: parametricType + typeParameters: typeParameters }; + + if (isAsync) { + funExpr.async = true; + } + + return funExpr; }, createIdentifier: function (name) { @@ -3438,25 +3905,110 @@ parseYieldExpression: true // are added later (like 'loc' and 'range'). This just helps // keep the shape of Identifier nodes consistent with everything // else. - typeAnnotation: undefined + typeAnnotation: undefined, + optional: undefined }; }, - createTypeAnnotation: function (typeIdentifier, parametricType, params, returnType, nullable) { + createTypeAnnotation: function (typeAnnotation) { return { type: Syntax.TypeAnnotation, - id: typeIdentifier, - parametricType: parametricType, + typeAnnotation: typeAnnotation + }; + }, + + createFunctionTypeAnnotation: function (params, returnType, rest, typeParameters) { + return { + type: Syntax.FunctionTypeAnnotation, params: params, returnType: returnType, - nullable: nullable + rest: rest, + typeParameters: typeParameters + }; + }, + + createFunctionTypeParam: function (name, typeAnnotation, optional) { + return { + type: Syntax.FunctionTypeParam, + name: name, + typeAnnotation: typeAnnotation, + optional: optional + }; + }, + + createNullableTypeAnnotation: function (typeAnnotation) { + return { + type: Syntax.NullableTypeAnnotation, + typeAnnotation: typeAnnotation + }; + }, + + createArrayTypeAnnotation: function (elementType) { + return { + type: Syntax.ArrayTypeAnnotation, + elementType: elementType + }; + }, + + createGenericTypeAnnotation: function (id, typeParameters) { + return { + type: Syntax.GenericTypeAnnotation, + id: id, + typeParameters: typeParameters + }; + }, + + createQualifiedTypeIdentifier: function (qualification, id) { + return { + type: Syntax.QualifiedTypeIdentifier, + qualification: qualification, + id: id }; }, - createParametricTypeAnnotation: function (parametricTypes) { + createTypeParameterDeclaration: function (params) { return { - type: Syntax.ParametricTypeAnnotation, - params: parametricTypes + type: Syntax.TypeParameterDeclaration, + params: params + }; + }, + + createTypeParameterInstantiation: function (params) { + return { + type: Syntax.TypeParameterInstantiation, + params: params + }; + }, + + createAnyTypeAnnotation: function () { + return { + type: Syntax.AnyTypeAnnotation + }; + }, + + createBooleanTypeAnnotation: function () { + return { + type: Syntax.BooleanTypeAnnotation + }; + }, + + createNumberTypeAnnotation: function () { + return { + type: Syntax.NumberTypeAnnotation + }; + }, + + createStringTypeAnnotation: function () { + return { + type: Syntax.StringTypeAnnotation + }; + }, + + createStringLiteralTypeAnnotation: function (token) { + return { + type: Syntax.StringLiteralTypeAnnotation, + value: token.value, + raw: source.slice(token.range[0], token.range[1]) }; }, @@ -3466,25 +4018,117 @@ parseYieldExpression: true }; }, - createObjectTypeAnnotation: function (properties) { + createTypeofTypeAnnotation: function (argument) { + return { + type: Syntax.TypeofTypeAnnotation, + argument: argument + }; + }, + + createTupleTypeAnnotation: function (types) { + return { + type: Syntax.TupleTypeAnnotation, + types: types + }; + }, + + createObjectTypeAnnotation: function (properties, indexers, callProperties) { return { type: Syntax.ObjectTypeAnnotation, - properties: properties + properties: properties, + indexers: indexers, + callProperties: callProperties + }; + }, + + createObjectTypeIndexer: function (id, key, value, isStatic) { + return { + type: Syntax.ObjectTypeIndexer, + id: id, + key: key, + value: value, + "static": isStatic }; }, - createTypeAnnotatedIdentifier: function (identifier, annotation, isOptionalParam) { + createObjectTypeCallProperty: function (value, isStatic) { return { - type: Syntax.TypeAnnotatedIdentifier, - id: identifier, - annotation: annotation + type: Syntax.ObjectTypeCallProperty, + value: value, + "static": isStatic }; }, - createOptionalParameter: function (identifier) { + createObjectTypeProperty: function (key, value, optional, isStatic) { return { - type: Syntax.OptionalParameter, - id: identifier + type: Syntax.ObjectTypeProperty, + key: key, + value: value, + optional: optional, + "static": isStatic + }; + }, + + createUnionTypeAnnotation: function (types) { + return { + type: Syntax.UnionTypeAnnotation, + types: types + }; + }, + + createIntersectionTypeAnnotation: function (types) { + return { + type: Syntax.IntersectionTypeAnnotation, + types: types + }; + }, + + createTypeAlias: function (id, typeParameters, right) { + return { + type: Syntax.TypeAlias, + id: id, + typeParameters: typeParameters, + right: right + }; + }, + + createInterface: function (id, typeParameters, body, extended) { + return { + type: Syntax.InterfaceDeclaration, + id: id, + typeParameters: typeParameters, + body: body, + "extends": extended + }; + }, + + createInterfaceExtends: function (id, typeParameters) { + return { + type: Syntax.InterfaceExtends, + id: id, + typeParameters: typeParameters + }; + }, + + createDeclareFunction: function (id) { + return { + type: Syntax.DeclareFunction, + id: id + }; + }, + + createDeclareVariable: function (id) { + return { + type: Syntax.DeclareVariable, + id: id + }; + }, + + createDeclareModule: function (id, body) { + return { + type: Syntax.DeclareModule, + id: id, + body: body }; }, @@ -3492,7 +4136,7 @@ parseYieldExpression: true return { type: Syntax.XJSAttribute, name: name, - value: value + value: value || null }; }, @@ -3582,11 +4226,15 @@ parseYieldExpression: true }, createLiteral: function (token) { - return { + var object = { type: Syntax.Literal, value: token.value, raw: source.slice(token.range[0], token.range[1]) }; + if (token.regex) { + object.regex = token.regex; + } + return object; }, createMemberExpression: function (accessor, object, property) { @@ -3781,8 +4429,8 @@ parseYieldExpression: true }; }, - createArrowFunctionExpression: function (params, defaults, body, rest, expression) { - return { + createArrowFunctionExpression: function (params, defaults, body, rest, expression, isAsync) { + var arrowExpr = { type: Syntax.ArrowFunctionExpression, id: null, params: params, @@ -3792,6 +4440,12 @@ parseYieldExpression: true generator: false, expression: expression }; + + if (isAsync) { + arrowExpr.async = true; + } + + return arrowExpr; }, createMethodDefinition: function (propertyType, kind, key, value) { @@ -3804,10 +4458,13 @@ parseYieldExpression: true }; }, - createClassProperty: function (propertyIdentifier) { + createClassProperty: function (key, typeAnnotation, computed, isStatic) { return { type: Syntax.ClassProperty, - id: propertyIdentifier + key: key, + typeAnnotation: typeAnnotation, + computed: computed, + "static": isStatic }; }, @@ -3818,24 +4475,43 @@ parseYieldExpression: true }; }, - createClassExpression: function (id, superClass, body, parametricType) { + createClassImplements: function (id, typeParameters) { + return { + type: Syntax.ClassImplements, + id: id, + typeParameters: typeParameters + }; + }, + + createClassExpression: function (id, superClass, body, typeParameters, superTypeParameters, implemented) { return { type: Syntax.ClassExpression, id: id, superClass: superClass, body: body, - parametricType: parametricType + typeParameters: typeParameters, + superTypeParameters: superTypeParameters, + "implements": implemented }; }, - createClassDeclaration: function (id, superClass, body, parametricType, superParametricType) { + createClassDeclaration: function (id, superClass, body, typeParameters, superTypeParameters, implemented) { return { type: Syntax.ClassDeclaration, id: id, superClass: superClass, body: body, - parametricType: parametricType, - superParametricType: superParametricType + typeParameters: typeParameters, + superTypeParameters: superTypeParameters, + "implements": implemented + }; + }, + + createModuleSpecifier: function (token) { + return { + type: Syntax.ModuleSpecifier, + value: token.value, + raw: source.slice(token.range[0], token.range[1]) }; }, @@ -3853,9 +4529,24 @@ parseYieldExpression: true }; }, - createExportDeclaration: function (declaration, specifiers, source) { + createImportDefaultSpecifier: function (id) { + return { + type: Syntax.ImportDefaultSpecifier, + id: id + }; + }, + + createImportNamespaceSpecifier: function (id) { + return { + type: Syntax.ImportNamespaceSpecifier, + id: id + }; + }, + + createExportDeclaration: function (isDefault, declaration, specifiers, source) { return { type: Syntax.ExportDeclaration, + 'default': !!isDefault, declaration: declaration, specifiers: specifiers, source: source @@ -3870,11 +4561,10 @@ parseYieldExpression: true }; }, - createImportDeclaration: function (specifiers, kind, source) { + createImportDeclaration: function (specifiers, source) { return { type: Syntax.ImportDeclaration, specifiers: specifiers, - kind: kind, source: source }; }, @@ -3887,12 +4577,10 @@ parseYieldExpression: true }; }, - createModuleDeclaration: function (id, source, body) { + createAwaitExpression: function (argument) { return { - type: Syntax.ModuleDeclaration, - id: id, - source: source, - body: body + type: Syntax.AwaitExpression, + argument: argument }; }, @@ -4016,13 +4704,21 @@ parseYieldExpression: true // Expect the next token to match the specified keyword. // If not, an exception will be thrown. - function expectKeyword(keyword) { + function expectKeyword(keyword, contextual) { var token = lex(); - if (token.type !== Token.Keyword || token.value !== keyword) { + if (token.type !== (contextual ? Token.Identifier : Token.Keyword) || + token.value !== keyword) { throwUnexpected(token); } } + // Expect the next token to match the specified contextual keyword. + // If not, an exception will be thrown. + + function expectContextualKeyword(keyword) { + return expectKeyword(keyword, true); + } + // Return true if the next token matches the specified punctuator. function match(value) { @@ -4031,15 +4727,15 @@ parseYieldExpression: true // Return true if the next token matches the specified keyword - function matchKeyword(keyword) { - return lookahead.type === Token.Keyword && lookahead.value === keyword; + function matchKeyword(keyword, contextual) { + var expectedType = contextual ? Token.Identifier : Token.Keyword; + return lookahead.type === expectedType && lookahead.value === keyword; } - // Return true if the next token matches the specified contextual keyword function matchContextualKeyword(keyword) { - return lookahead.type === Token.Identifier && lookahead.value === keyword; + return matchKeyword(keyword, true); } // Return true if the next token is an assignment operator @@ -4065,8 +4761,33 @@ parseYieldExpression: true op === '|='; } + // Note that 'yield' is treated as a keyword in strict mode, but a + // contextual keyword (identifier) in non-strict mode, so we need to + // use matchKeyword('yield', false) and matchKeyword('yield', true) + // (i.e. matchContextualKeyword) appropriately. + function matchYield() { + return state.yieldAllowed && matchKeyword('yield', !strict); + } + + function matchAsync() { + var backtrackToken = lookahead, matches = false; + + if (matchContextualKeyword('async')) { + lex(); // Make sure peekLineTerminator() starts after 'async'. + matches = !peekLineTerminator(); + rewind(backtrackToken); // Revert the lex(). + } + + return matches; + } + + function matchAwait() { + return state.awaitAllowed && matchContextualKeyword('await'); + } + function consumeSemicolon() { - var line; + var line, oldIndex = index, oldLineNumber = lineNumber, + oldLineStart = lineStart, oldLookahead = lookahead; // Catch the very common case first: immediately a semicolon (char #59). if (source.charCodeAt(index) === 59) { @@ -4077,6 +4798,10 @@ parseYieldExpression: true line = lineNumber; skipComment(); if (lineNumber !== line) { + index = oldIndex; + lineNumber = oldLineNumber; + lineStart = oldLineStart; + lookahead = oldLookahead; return; } @@ -4167,12 +4892,14 @@ parseYieldExpression: true // 11.1.5 Object Initialiser function parsePropertyFunction(options) { - var previousStrict, previousYieldAllowed, params, defaults, body, - marker = markerCreate(); + var previousStrict, previousYieldAllowed, previousAwaitAllowed, + params, defaults, body, marker = markerCreate(); previousStrict = strict; previousYieldAllowed = state.yieldAllowed; state.yieldAllowed = options.generator; + previousAwaitAllowed = state.awaitAllowed; + state.awaitAllowed = options.async; params = options.params || []; defaults = options.defaults || []; @@ -4182,6 +4909,7 @@ parseYieldExpression: true } strict = previousStrict; state.yieldAllowed = previousYieldAllowed; + state.awaitAllowed = previousAwaitAllowed; return markerApply(marker, delegate.createFunctionExpression( null, @@ -4191,8 +4919,9 @@ parseYieldExpression: true options.rest || null, options.generator, body.type !== Syntax.BlockStatement, + options.async, options.returnType, - options.parametricType + options.typeParameters )); } @@ -4209,14 +4938,14 @@ parseYieldExpression: true throwErrorTolerant(tmp.stricted, tmp.message); } - method = parsePropertyFunction({ params: tmp.params, defaults: tmp.defaults, rest: tmp.rest, generator: options.generator, + async: options.async, returnType: tmp.returnType, - parametricType: options.parametricType + typeParameters: options.typeParameters }); strict = previousStrict; @@ -4256,46 +4985,138 @@ parseYieldExpression: true function parseObjectProperty() { var token, key, id, value, param, expr, computed, - marker = markerCreate(); + marker = markerCreate(), returnType; token = lookahead; computed = (token.value === '['); - if (token.type === Token.Identifier || computed) { - + if (token.type === Token.Identifier || computed || matchAsync()) { id = parseObjectPropertyKey(); + if (match(':')) { + lex(); + + return markerApply( + marker, + delegate.createProperty( + 'init', + id, + parseAssignmentExpression(), + false, + false, + computed + ) + ); + } + + if (match('(')) { + return markerApply( + marker, + delegate.createProperty( + 'init', + id, + parsePropertyMethodFunction({ + generator: false, + async: false + }), + true, + false, + computed + ) + ); + } + // Property Assignment: Getter and Setter. - if (token.value === 'get' && !(match(':') || match('('))) { + if (token.value === 'get') { computed = (lookahead.value === '['); key = parseObjectPropertyKey(); + expect('('); expect(')'); - return markerApply(marker, delegate.createProperty('get', key, parsePropertyFunction({ generator: false }), false, false, computed)); + if (match(':')) { + returnType = parseTypeAnnotation(); + } + + return markerApply( + marker, + delegate.createProperty( + 'get', + key, + parsePropertyFunction({ + generator: false, + async: false, + returnType: returnType + }), + false, + false, + computed + ) + ); } - if (token.value === 'set' && !(match(':') || match('('))) { + + if (token.value === 'set') { computed = (lookahead.value === '['); key = parseObjectPropertyKey(); + expect('('); token = lookahead; param = [ parseTypeAnnotatableIdentifier() ]; expect(')'); - return markerApply(marker, delegate.createProperty('set', key, parsePropertyFunction({ params: param, generator: false, name: token }), false, false, computed)); - } - if (match(':')) { - lex(); - return markerApply(marker, delegate.createProperty('init', id, parseAssignmentExpression(), false, false, computed)); + if (match(':')) { + returnType = parseTypeAnnotation(); + } + + return markerApply( + marker, + delegate.createProperty( + 'set', + key, + parsePropertyFunction({ + params: param, + generator: false, + async: false, + name: token, + returnType: returnType + }), + false, + false, + computed + ) + ); } - if (match('(')) { - return markerApply(marker, delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: false }), true, false, computed)); + + if (token.value === 'async') { + computed = (lookahead.value === '['); + key = parseObjectPropertyKey(); + + return markerApply( + marker, + delegate.createProperty( + 'init', + key, + parsePropertyMethodFunction({ + generator: false, + async: true + }), + true, + false, + computed + ) + ); } + if (computed) { // Computed properties can only be used with full notation. throwUnexpected(lookahead); } - return markerApply(marker, delegate.createProperty('init', id, id, false, true, false)); + + return markerApply( + marker, + delegate.createProperty('init', id, id, false, true, false) + ); } + if (token.type === Token.EOF || token.type === Token.Punctuator) { if (!match('*')) { throwUnexpected(token); @@ -4422,6 +5243,18 @@ parseYieldExpression: true return expr; } + function matchAsyncFuncExprOrDecl() { + var token; + + if (matchAsync()) { + token = lookahead2(); + if (token.type === Token.Keyword && token.value === 'function') { + return true; + } + } + + return false; + } // 11.1 Primary Expressions @@ -4998,13 +5831,15 @@ parseYieldExpression: true } function parseArrowFunctionExpression(options, marker) { - var previousStrict, previousYieldAllowed, body; + var previousStrict, previousYieldAllowed, previousAwaitAllowed, body; expect('=>'); previousStrict = strict; previousYieldAllowed = state.yieldAllowed; state.yieldAllowed = false; + previousAwaitAllowed = state.awaitAllowed; + state.awaitAllowed = !!options.async; body = parseConciseBody(); if (strict && options.firstRestricted) { @@ -5016,30 +5851,47 @@ parseYieldExpression: true strict = previousStrict; state.yieldAllowed = previousYieldAllowed; + state.awaitAllowed = previousAwaitAllowed; return markerApply(marker, delegate.createArrowFunctionExpression( options.params, options.defaults, body, options.rest, - body.type !== Syntax.BlockStatement + body.type !== Syntax.BlockStatement, + !!options.async )); } function parseAssignmentExpression() { - var marker, expr, token, params, oldParenthesizedCount; + var marker, expr, token, params, oldParenthesizedCount, + backtrackToken = lookahead, possiblyAsync = false; - // Note that 'yield' is treated as a keyword in strict mode, but a - // contextual keyword (identifier) in non-strict mode, so we need - // to use matchKeyword and matchContextualKeyword appropriately. - if ((state.yieldAllowed && matchContextualKeyword('yield')) || (strict && matchKeyword('yield'))) { + if (matchYield()) { return parseYieldExpression(); } + if (matchAwait()) { + return parseAwaitExpression(); + } + oldParenthesizedCount = state.parenthesizedCount; marker = markerCreate(); + if (matchAsyncFuncExprOrDecl()) { + return parseFunctionExpression(); + } + + if (matchAsync()) { + // We can't be completely sure that this 'async' token is + // actually a contextual keyword modifying a function + // expression, so we might have to un-lex() it later by + // calling rewind(backtrackToken). + possiblyAsync = true; + lex(); + } + if (match('(')) { token = lookahead2(); if ((token.type === Token.Punctuator && token.value === ')') || token.value === '...') { @@ -5047,11 +5899,21 @@ parseYieldExpression: true if (!match('=>')) { throwUnexpected(lex()); } + params.async = possiblyAsync; return parseArrowFunctionExpression(params, marker); } } token = lookahead; + + // If the 'async' keyword is not followed by a '(' character or an + // identifier, then it can't be an arrow function modifier, and we + // should interpret it as a normal identifer. + if (possiblyAsync && !match('(') && token.type !== Token.Identifier) { + possiblyAsync = false; + rewind(backtrackToken); + } + expr = parseConditionalExpression(); if (match('=>') && @@ -5063,10 +5925,20 @@ parseYieldExpression: true params = reinterpretAsCoverFormalsList(expr.expressions); } if (params) { + params.async = possiblyAsync; return parseArrowFunctionExpression(params, marker); } } + // If we haven't returned by now, then the 'async' keyword was not + // a function modifier, and we should rewind and interpret it as a + // normal identifier. + if (possiblyAsync) { + possiblyAsync = false; + rewind(backtrackToken); + expr = parseConditionalExpression(); + } + if (matchAssign()) { // 11.13.1 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { @@ -5172,118 +6044,446 @@ parseYieldExpression: true // 12.2 Variable Statement - function parseObjectTypeAnnotation() { - var isMethod, marker, properties = [], property, propertyKey, - propertyTypeAnnotation; + function parseTypeParameterDeclaration() { + var marker = markerCreate(), paramTypes = []; + + expect('<'); + while (!match('>')) { + paramTypes.push(parseVariableIdentifier()); + if (!match('>')) { + expect(','); + } + } + expect('>'); + + return markerApply(marker, delegate.createTypeParameterDeclaration( + paramTypes + )); + } + + function parseTypeParameterInstantiation() { + var marker = markerCreate(), oldInType = state.inType, paramTypes = []; + + state.inType = true; + + expect('<'); + while (!match('>')) { + paramTypes.push(parseType()); + if (!match('>')) { + expect(','); + } + } + expect('>'); + + state.inType = oldInType; + + return markerApply(marker, delegate.createTypeParameterInstantiation( + paramTypes + )); + } + + function parseObjectTypeIndexer(marker, isStatic) { + var id, key, value; + + expect('['); + id = parseObjectPropertyKey(); + expect(':'); + key = parseType(); + expect(']'); + expect(':'); + value = parseType(); + + return markerApply(marker, delegate.createObjectTypeIndexer( + id, + key, + value, + isStatic + )); + } + + function parseObjectTypeMethodish(marker) { + var params = [], rest = null, returnType, typeParameters = null; + if (match('<')) { + typeParameters = parseTypeParameterDeclaration(); + } + + expect('('); + while (lookahead.type === Token.Identifier) { + params.push(parseFunctionTypeParam()); + if (!match(')')) { + expect(','); + } + } + + if (match('...')) { + lex(); + rest = parseFunctionTypeParam(); + } + expect(')'); + expect(':'); + returnType = parseType(); + + return markerApply(marker, delegate.createFunctionTypeAnnotation( + params, + returnType, + rest, + typeParameters + )); + } + + function parseObjectTypeMethod(marker, isStatic, key) { + var optional = false, value; + value = parseObjectTypeMethodish(marker); + + return markerApply(marker, delegate.createObjectTypeProperty( + key, + value, + optional, + isStatic + )); + } + + function parseObjectTypeCallProperty(marker, isStatic) { + var valueMarker = markerCreate(); + return markerApply(marker, delegate.createObjectTypeCallProperty( + parseObjectTypeMethodish(valueMarker), + isStatic + )); + } + + function parseObjectType(allowStatic) { + var callProperties = [], indexers = [], marker, optional = false, + properties = [], property, propertyKey, propertyTypeAnnotation, + token, isStatic; expect('{'); while (!match('}')) { marker = markerCreate(); - propertyKey = parseObjectPropertyKey(); - isMethod = match('('); - propertyTypeAnnotation = parseTypeAnnotation(); - properties.push(markerApply(marker, delegate.createProperty( - 'init', - propertyKey, - propertyTypeAnnotation, - isMethod, - false - ))); + if (allowStatic && matchContextualKeyword('static')) { + token = lex(); + isStatic = true; + } - if (!match('}')) { - if (match(',') || match(';')) { - lex(); + if (match('[')) { + indexers.push(parseObjectTypeIndexer(marker, isStatic)); + } else if (match('(') || match('<')) { + callProperties.push(parseObjectTypeCallProperty(marker, allowStatic)); + } else { + if (isStatic && match(':')) { + propertyKey = markerApply(marker, delegate.createIdentifier(token)); + throwErrorTolerant(token, Messages.StrictReservedWord); } else { - throwUnexpected(lookahead); + propertyKey = parseObjectPropertyKey(); } + if (match('<') || match('(')) { + // This is a method property + properties.push(parseObjectTypeMethod(marker, isStatic, propertyKey)); + } else { + if (match('?')) { + lex(); + optional = true; + } + expect(':'); + propertyTypeAnnotation = parseType(); + properties.push(markerApply(marker, delegate.createObjectTypeProperty( + propertyKey, + propertyTypeAnnotation, + optional, + isStatic + ))); + } + } + + if (match(';')) { + lex(); + } else if (!match('}')) { + throwUnexpected(lookahead); } } expect('}'); - return delegate.createObjectTypeAnnotation(properties); + return delegate.createObjectTypeAnnotation( + properties, + indexers, + callProperties + ); + } + + function parseGenericType() { + var marker = markerCreate(), returnType = null, + typeParameters = null, typeIdentifier, + typeIdentifierMarker = markerCreate; + + typeIdentifier = parseVariableIdentifier(); + + while (match('.')) { + expect('.'); + typeIdentifier = markerApply(marker, delegate.createQualifiedTypeIdentifier( + typeIdentifier, + parseVariableIdentifier() + )); + } + + if (match('<')) { + typeParameters = parseTypeParameterInstantiation(); + } + + return markerApply(marker, delegate.createGenericTypeAnnotation( + typeIdentifier, + typeParameters + )); } - function parseVoidTypeAnnotation() { + function parseVoidType() { var marker = markerCreate(); expectKeyword('void'); return markerApply(marker, delegate.createVoidTypeAnnotation()); } - function parseParametricTypeAnnotation() { - var marker = markerCreate(), typeIdentifier, paramTypes = []; + function parseTypeofType() { + var argument, marker = markerCreate(); + expectKeyword('typeof'); + argument = parsePrimaryType(); + return markerApply(marker, delegate.createTypeofTypeAnnotation( + argument + )); + } - expect('<'); - while (!match('>')) { - paramTypes.push(parseVariableIdentifier()); - if (!match('>')) { - expect(','); + function parseTupleType() { + var marker = markerCreate(), types = []; + expect('['); + // We allow trailing commas + while (index < length && !match(']')) { + types.push(parseType()); + if (match(']')) { + break; } + expect(','); } - expect('>'); + expect(']'); + return markerApply(marker, delegate.createTupleTypeAnnotation( + types + )); + } - return markerApply(marker, delegate.createParametricTypeAnnotation( - paramTypes + function parseFunctionTypeParam() { + var marker = markerCreate(), name, optional = false, typeAnnotation; + name = parseVariableIdentifier(); + if (match('?')) { + lex(); + optional = true; + } + expect(':'); + typeAnnotation = parseType(); + return markerApply(marker, delegate.createFunctionTypeParam( + name, + typeAnnotation, + optional )); } - function parseTypeAnnotation(dontExpectColon) { + function parseFunctionTypeParams() { + var ret = { params: [], rest: null }; + while (lookahead.type === Token.Identifier) { + ret.params.push(parseFunctionTypeParam()); + if (!match(')')) { + expect(','); + } + } + + if (match('...')) { + lex(); + ret.rest = parseFunctionTypeParam(); + } + return ret; + } + + // The parsing of types roughly parallels the parsing of expressions, and + // primary types are kind of like primary expressions...they're the + // primitives with which other types are constructed. + function parsePrimaryType() { var typeIdentifier = null, params = null, returnType = null, - nullable = false, marker = markerCreate(), returnTypeMarker = null, - parametricType, annotation; + marker = markerCreate(), rest = null, tmp, + typeParameters, token, type, isGroupedType = false; - if (!dontExpectColon) { - expect(':'); + switch (lookahead.type) { + case Token.Identifier: + switch (lookahead.value) { + case 'any': + lex(); + return markerApply(marker, delegate.createAnyTypeAnnotation()); + case 'bool': // fallthrough + case 'boolean': + lex(); + return markerApply(marker, delegate.createBooleanTypeAnnotation()); + case 'number': + lex(); + return markerApply(marker, delegate.createNumberTypeAnnotation()); + case 'string': + lex(); + return markerApply(marker, delegate.createStringTypeAnnotation()); + } + return markerApply(marker, parseGenericType()); + case Token.Punctuator: + switch (lookahead.value) { + case '{': + return markerApply(marker, parseObjectType()); + case '[': + return parseTupleType(); + case '<': + typeParameters = parseTypeParameterDeclaration(); + expect('('); + tmp = parseFunctionTypeParams(); + params = tmp.params; + rest = tmp.rest; + expect(')'); + + expect('=>'); + + returnType = parseType(); + + return markerApply(marker, delegate.createFunctionTypeAnnotation( + params, + returnType, + rest, + typeParameters + )); + case '(': + lex(); + // Check to see if this is actually a grouped type + if (!match(')') && !match('...')) { + if (lookahead.type === Token.Identifier) { + token = lookahead2(); + isGroupedType = token.value !== '?' && token.value !== ':'; + } else { + isGroupedType = true; + } + } + + if (isGroupedType) { + type = parseType(); + expect(')'); + + // If we see a => next then someone was probably confused about + // function types, so we can provide a better error message + if (match('=>')) { + throwError({}, Messages.ConfusedAboutFunctionType); + } + + return type; + } + + tmp = parseFunctionTypeParams(); + params = tmp.params; + rest = tmp.rest; + + expect(')'); + + expect('=>'); + + returnType = parseType(); + + return markerApply(marker, delegate.createFunctionTypeAnnotation( + params, + returnType, + rest, + null /* typeParameters */ + )); + } + break; + case Token.Keyword: + switch (lookahead.value) { + case 'void': + return markerApply(marker, parseVoidType()); + case 'typeof': + return markerApply(marker, parseTypeofType()); + } + break; + case Token.StringLiteral: + token = lex(); + if (token.octal) { + throwError(token, Messages.StrictOctalLiteral); + } + return markerApply(marker, delegate.createStringLiteralTypeAnnotation( + token + )); } - if (match('{')) { - return markerApply(marker, parseObjectTypeAnnotation()); + throwUnexpected(lookahead); + } + + function parsePostfixType() { + var marker = markerCreate(), t = parsePrimaryType(); + if (match('[')) { + expect('['); + expect(']'); + return markerApply(marker, delegate.createArrayTypeAnnotation(t)); } + return t; + } + function parsePrefixType() { + var marker = markerCreate(); if (match('?')) { lex(); - nullable = true; + return markerApply(marker, delegate.createNullableTypeAnnotation( + parsePrefixType() + )); } + return parsePostfixType(); + } - if (lookahead.type === Token.Identifier) { - typeIdentifier = parseVariableIdentifier(); - if (match('<')) { - parametricType = parseParametricTypeAnnotation(); - } - } else if (match('(')) { + + function parseIntersectionType() { + var marker = markerCreate(), type, types; + type = parsePrefixType(); + types = [type]; + while (match('&')) { lex(); - params = []; - while (lookahead.type === Token.Identifier || match('?')) { - params.push(parseTypeAnnotatableIdentifier( - true, /* requireTypeAnnotation */ - true /* canBeOptionalParam */ - )); - if (!match(')')) { - expect(','); - } - } - expect(')'); + types.push(parsePrefixType()); + } - returnTypeMarker = markerCreate(); - expect('=>'); + return types.length === 1 ? + type : + markerApply(marker, delegate.createIntersectionTypeAnnotation( + types + )); + } - returnType = parseTypeAnnotation(true); - } else { - if (!matchKeyword('void')) { - throwUnexpected(lookahead); - } else { - return parseVoidTypeAnnotation(); - } + function parseUnionType() { + var marker = markerCreate(), type, types; + type = parseIntersectionType(); + types = [type]; + while (match('|')) { + lex(); + types.push(parseIntersectionType()); } + return types.length === 1 ? + type : + markerApply(marker, delegate.createUnionTypeAnnotation( + types + )); + } - return markerApply(marker, delegate.createTypeAnnotation( - typeIdentifier, - parametricType, - params, - returnType, - nullable - )); + function parseType() { + var oldInType = state.inType, type; + state.inType = true; + + type = parseUnionType(); + + state.inType = oldInType; + return type; + } + + function parseTypeAnnotation() { + var marker = markerCreate(), type; + + expect(':'); + type = parseType(); + + return markerApply(marker, delegate.createTypeAnnotation(type)); } function parseVariableIdentifier() { @@ -5308,14 +6508,13 @@ parseYieldExpression: true } if (requireTypeAnnotation || match(':')) { - ident = markerApply(marker, delegate.createTypeAnnotatedIdentifier( - ident, - parseTypeAnnotation() - )); + ident.typeAnnotation = parseTypeAnnotation(); + ident = markerApply(marker, ident); } if (isOptionalParam) { - ident = markerApply(marker, delegate.createOptionalParameter(ident)); + ident.optional = true; + ident = markerApply(marker, ident); } return ident; @@ -5324,13 +6523,22 @@ parseYieldExpression: true function parseVariableDeclaration(kind) { var id, marker = markerCreate(), - init = null; + init = null, + typeAnnotationMarker = markerCreate(); if (match('{')) { id = parseObjectInitialiser(); reinterpretAsAssignmentBindingPattern(id); + if (match(':')) { + id.typeAnnotation = parseTypeAnnotation(); + markerApply(typeAnnotationMarker, id); + } } else if (match('[')) { id = parseArrayInitialiser(); reinterpretAsAssignmentBindingPattern(id); + if (match(':')) { + id.typeAnnotation = parseTypeAnnotation(); + markerApply(typeAnnotationMarker, id); + } } else { id = state.allowKeyword ? parseNonComputedProperty() : parseTypeAnnotatableIdentifier(); // 12.2.1 @@ -5395,41 +6603,18 @@ parseYieldExpression: true return markerApply(marker, delegate.createVariableDeclaration(declarations, kind)); } - // http://wiki.ecmascript.org/doku.php?id=harmony:modules - - function parseModuleDeclaration() { - var id, src, body, marker = markerCreate(); - - lex(); // 'module' - - if (peekLineTerminator()) { - throwError({}, Messages.NewlineAfterModule); - } - - switch (lookahead.type) { + // people.mozilla.org/~jorendorff/es6-draft.html - case Token.StringLiteral: - id = parsePrimaryExpression(); - body = parseModuleBlock(); - src = null; - break; + function parseModuleSpecifier() { + var marker = markerCreate(), + specifier; - case Token.Identifier: - id = parseVariableIdentifier(); - body = null; - if (!matchContextualKeyword('from')) { - throwUnexpected(lex()); - } - lex(); - src = parsePrimaryExpression(); - if (src.type !== Syntax.Literal) { - throwError({}, Messages.InvalidModuleSpecifier); - } - break; + if (lookahead.type !== Token.StringLiteral) { + throwError({}, Messages.InvalidModuleSpecifier); } - - consumeSemicolon(); - return markerApply(marker, delegate.createModuleDeclaration(id, src, body)); + specifier = delegate.createModuleSpecifier(lookahead); + lex(); + return markerApply(marker, specifier); } function parseExportBatchSpecifier() { @@ -5439,9 +6624,14 @@ parseYieldExpression: true } function parseExportSpecifier() { - var id, name = null, marker = markerCreate(); - - id = parseVariableIdentifier(); + var id, name = null, marker = markerCreate(), from; + if (matchKeyword('default')) { + lex(); + id = markerApply(marker, delegate.createIdentifier('default')); + // export {default} from "something"; + } else { + id = parseVariableIdentifier(); + } if (matchContextualKeyword('as')) { lex(); name = parseNonComputedProperty(); @@ -5451,104 +6641,207 @@ parseYieldExpression: true } function parseExportDeclaration() { - var previousAllowKeyword, decl, def, src, specifiers, + var backtrackToken, id, previousAllowKeyword, declaration = null, + isExportFromIdentifier, + src = null, specifiers = [], marker = markerCreate(); expectKeyword('export'); + if (matchKeyword('default')) { + // covers: + // export default ... + lex(); + if (matchKeyword('function') || matchKeyword('class')) { + backtrackToken = lookahead; + lex(); + if (isIdentifierName(lookahead)) { + // covers: + // export default function foo () {} + // export default class foo {} + id = parseNonComputedProperty(); + rewind(backtrackToken); + return markerApply(marker, delegate.createExportDeclaration(true, parseSourceElement(), [id], null)); + } + // covers: + // export default function () {} + // export default class {} + rewind(backtrackToken); + switch (lookahead.value) { + case 'class': + return markerApply(marker, delegate.createExportDeclaration(true, parseClassExpression(), [], null)); + case 'function': + return markerApply(marker, delegate.createExportDeclaration(true, parseFunctionExpression(), [], null)); + } + } + + if (matchContextualKeyword('from')) { + throwError({}, Messages.UnexpectedToken, lookahead.value); + } + + // covers: + // export default {}; + // export default []; + if (match('{')) { + declaration = parseObjectInitialiser(); + } else if (match('[')) { + declaration = parseArrayInitialiser(); + } else { + declaration = parseAssignmentExpression(); + } + consumeSemicolon(); + return markerApply(marker, delegate.createExportDeclaration(true, declaration, [], null)); + } + + // non-default export if (lookahead.type === Token.Keyword) { + // covers: + // export var f = 1; switch (lookahead.value) { case 'let': case 'const': case 'var': case 'class': case 'function': - return markerApply(marker, delegate.createExportDeclaration(parseSourceElement(), null, null)); + return markerApply(marker, delegate.createExportDeclaration(false, parseSourceElement(), specifiers, null)); } } - if (isIdentifierName(lookahead)) { - previousAllowKeyword = state.allowKeyword; - state.allowKeyword = true; - decl = parseVariableDeclarationList('let'); - state.allowKeyword = previousAllowKeyword; - return markerApply(marker, delegate.createExportDeclaration(decl, null, null)); + if (match('*')) { + // covers: + // export * from "foo"; + specifiers.push(parseExportBatchSpecifier()); + + if (!matchContextualKeyword('from')) { + throwError({}, lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); + } + lex(); + src = parseModuleSpecifier(); + consumeSemicolon(); + + return markerApply(marker, delegate.createExportDeclaration(false, null, specifiers, src)); } - specifiers = []; - src = null; + expect('{'); + do { + isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default'); + specifiers.push(parseExportSpecifier()); + } while (match(',') && lex()); + expect('}'); - if (match('*')) { - specifiers.push(parseExportBatchSpecifier()); + if (matchContextualKeyword('from')) { + // covering: + // export {default} from "foo"; + // export {foo} from "foo"; + lex(); + src = parseModuleSpecifier(); + consumeSemicolon(); + } else if (isExportFromIdentifier) { + // covering: + // export {default}; // missing fromClause + throwError({}, lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); } else { - expect('{'); - do { - specifiers.push(parseExportSpecifier()); - } while (match(',') && lex()); - expect('}'); + // cover + // export {foo}; + consumeSemicolon(); } + return markerApply(marker, delegate.createExportDeclaration(false, declaration, specifiers, src)); + } - if (matchContextualKeyword('from')) { + + function parseImportSpecifier() { + // import {<foo as bar>} ...; + var id, name = null, marker = markerCreate(); + + id = parseNonComputedProperty(); + if (matchContextualKeyword('as')) { lex(); - src = parsePrimaryExpression(); - if (src.type !== Syntax.Literal) { - throwError({}, Messages.InvalidModuleSpecifier); - } + name = parseVariableIdentifier(); } - consumeSemicolon(); + return markerApply(marker, delegate.createImportSpecifier(id, name)); + } + + function parseNamedImports() { + var specifiers = []; + // {foo, bar as bas} + expect('{'); + do { + specifiers.push(parseImportSpecifier()); + } while (match(',') && lex()); + expect('}'); + return specifiers; + } + + function parseImportDefaultSpecifier() { + // import <foo> ...; + var id, marker = markerCreate(); + + id = parseNonComputedProperty(); + + return markerApply(marker, delegate.createImportDefaultSpecifier(id)); + } + + function parseImportNamespaceSpecifier() { + // import <* as foo> ...; + var id, marker = markerCreate(); + + expect('*'); + if (!matchContextualKeyword('as')) { + throwError({}, Messages.NoAsAfterImportNamespace); + } + lex(); + id = parseNonComputedProperty(); - return markerApply(marker, delegate.createExportDeclaration(null, specifiers, src)); + return markerApply(marker, delegate.createImportNamespaceSpecifier(id)); } function parseImportDeclaration() { - var specifiers, kind, src, marker = markerCreate(); + var specifiers, src, marker = markerCreate(); expectKeyword('import'); specifiers = []; - if (isIdentifierName(lookahead)) { - kind = 'default'; - specifiers.push(parseImportSpecifier()); + if (lookahead.type === Token.StringLiteral) { + // covers: + // import "foo"; + src = parseModuleSpecifier(); + consumeSemicolon(); + return markerApply(marker, delegate.createImportDeclaration(specifiers, src)); + } - if (!matchContextualKeyword('from')) { - throwError({}, Messages.NoFromAfterImport); + if (!matchKeyword('default') && isIdentifierName(lookahead)) { + // covers: + // import foo + // import foo, ... + specifiers.push(parseImportDefaultSpecifier()); + if (match(',')) { + lex(); } - lex(); + } + if (match('*')) { + // covers: + // import foo, * as foo + // import * as foo + specifiers.push(parseImportNamespaceSpecifier()); } else if (match('{')) { - kind = 'named'; - lex(); - do { - specifiers.push(parseImportSpecifier()); - } while (match(',') && lex()); - expect('}'); - - if (!matchContextualKeyword('from')) { - throwError({}, Messages.NoFromAfterImport); - } - lex(); + // covers: + // import foo, {bar} + // import {bar} + specifiers = specifiers.concat(parseNamedImports()); } - src = parsePrimaryExpression(); - if (src.type !== Syntax.Literal) { - throwError({}, Messages.InvalidModuleSpecifier); + if (!matchContextualKeyword('from')) { + throwError({}, lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); } - + lex(); + src = parseModuleSpecifier(); consumeSemicolon(); - return markerApply(marker, delegate.createImportDeclaration(specifiers, kind, src)); - } - - function parseImportSpecifier() { - var id, name = null, marker = markerCreate(); - - id = parseNonComputedProperty(); - if (matchContextualKeyword('as')) { - lex(); - name = parseVariableIdentifier(); - } - - return markerApply(marker, delegate.createImportSpecifier(id, name)); + return markerApply(marker, delegate.createImportDeclaration(specifiers, src)); } // 12.3 Empty Statement @@ -6101,6 +7394,10 @@ parseYieldExpression: true } } + if (matchAsyncFuncExprOrDecl()) { + return parseFunctionDeclaration(); + } + marker = markerCreate(); expr = parseExpression(); @@ -6226,7 +7523,7 @@ parseYieldExpression: true } function parseParam(options) { - var token, rest, param, def; + var marker, token, rest, param, def; token = lookahead; if (token.value === '...') { @@ -6235,19 +7532,31 @@ parseYieldExpression: true } if (match('[')) { + marker = markerCreate(); param = parseArrayInitialiser(); reinterpretAsDestructuredParameter(options, param); + if (match(':')) { + param.typeAnnotation = parseTypeAnnotation(); + markerApply(marker, param); + } } else if (match('{')) { + marker = markerCreate(); if (rest) { throwError({}, Messages.ObjectPatternAsRestParameter); } param = parseObjectInitialiser(); reinterpretAsDestructuredParameter(options, param); + if (match(':')) { + param.typeAnnotation = parseTypeAnnotation(); + markerApply(marker, param); + } } else { - // Typing rest params is awkward, so punting on that for now param = rest - ? parseVariableIdentifier() + ? parseTypeAnnotatableIdentifier( + false, /* requireTypeAnnotation */ + false /* canBeOptionalParam */ + ) : parseTypeAnnotatableIdentifier( false, /* requireTypeAnnotation */ true /* canBeOptionalParam */ @@ -6315,8 +7624,15 @@ parseYieldExpression: true } function parseFunctionDeclaration() { - var id, body, token, tmp, firstRestricted, message, previousStrict, previousYieldAllowed, generator, - marker = markerCreate(), parametricType; + var id, body, token, tmp, firstRestricted, message, generator, isAsync, + previousStrict, previousYieldAllowed, previousAwaitAllowed, + marker = markerCreate(), typeParameters; + + isAsync = false; + if (matchAsync()) { + lex(); + isAsync = true; + } expectKeyword('function'); @@ -6331,7 +7647,7 @@ parseYieldExpression: true id = parseVariableIdentifier(); if (match('<')) { - parametricType = parseParametricTypeAnnotation(); + typeParameters = parseTypeParameterDeclaration(); } if (strict) { @@ -6357,6 +7673,8 @@ parseYieldExpression: true previousStrict = strict; previousYieldAllowed = state.yieldAllowed; state.yieldAllowed = generator; + previousAwaitAllowed = state.awaitAllowed; + state.awaitAllowed = isAsync; body = parseFunctionSourceElements(); @@ -6368,14 +7686,35 @@ parseYieldExpression: true } strict = previousStrict; state.yieldAllowed = previousYieldAllowed; + state.awaitAllowed = previousAwaitAllowed; - return markerApply(marker, delegate.createFunctionDeclaration(id, tmp.params, tmp.defaults, body, tmp.rest, generator, false, - tmp.returnType, parametricType)); + return markerApply( + marker, + delegate.createFunctionDeclaration( + id, + tmp.params, + tmp.defaults, + body, + tmp.rest, + generator, + false, + isAsync, + tmp.returnType, + typeParameters + ) + ); } function parseFunctionExpression() { - var token, id = null, firstRestricted, message, tmp, body, previousStrict, previousYieldAllowed, generator, - marker = markerCreate(), parametricType; + var token, id = null, firstRestricted, message, tmp, body, generator, isAsync, + previousStrict, previousYieldAllowed, previousAwaitAllowed, + marker = markerCreate(), typeParameters; + + isAsync = false; + if (matchAsync()) { + lex(); + isAsync = true; + } expectKeyword('function'); @@ -6407,7 +7746,7 @@ parseYieldExpression: true } if (match('<')) { - parametricType = parseParametricTypeAnnotation(); + typeParameters = parseTypeParameterDeclaration(); } } @@ -6420,6 +7759,8 @@ parseYieldExpression: true previousStrict = strict; previousYieldAllowed = state.yieldAllowed; state.yieldAllowed = generator; + previousAwaitAllowed = state.awaitAllowed; + state.awaitAllowed = isAsync; body = parseFunctionSourceElements(); @@ -6431,20 +7772,29 @@ parseYieldExpression: true } strict = previousStrict; state.yieldAllowed = previousYieldAllowed; + state.awaitAllowed = previousAwaitAllowed; - return markerApply(marker, delegate.createFunctionExpression(id, tmp.params, tmp.defaults, body, tmp.rest, generator, false, - tmp.returnType, parametricType)); + return markerApply( + marker, + delegate.createFunctionExpression( + id, + tmp.params, + tmp.defaults, + body, + tmp.rest, + generator, + false, + isAsync, + tmp.returnType, + typeParameters + ) + ); } function parseYieldExpression() { - var yieldToken, delegateFlag, expr, marker = markerCreate(); + var delegateFlag, expr, marker = markerCreate(); - yieldToken = lex(); - assert(yieldToken.value === 'yield', 'Called parseYieldExpression with non-yield lookahead.'); - - if (!state.yieldAllowed) { - throwErrorTolerant({}, Messages.IllegalYield); - } + expectKeyword('yield', !strict); delegateFlag = false; if (match('*')) { @@ -6457,35 +7807,34 @@ parseYieldExpression: true return markerApply(marker, delegate.createYieldExpression(expr, delegateFlag)); } + function parseAwaitExpression() { + var expr, marker = markerCreate(); + expectContextualKeyword('await'); + expr = parseAssignmentExpression(); + return markerApply(marker, delegate.createAwaitExpression(expr)); + } + // 14 Classes - function parseMethodDefinition(existingPropNames) { - var token, key, param, propType, isValidDuplicateProp = false, - marker = markerCreate(), token2, parametricType, - parametricTypeMarker, annotationMarker; + function parseMethodDefinition(existingPropNames, key, isStatic, generator, computed) { + var token, param, propType, isValidDuplicateProp = false, + isAsync, typeParameters, tokenValue, returnType, + annotationMarker; - if (lookahead.value === 'static') { - propType = ClassPropertyType["static"]; - lex(); - } else { - propType = ClassPropertyType.prototype; - } + propType = isStatic ? ClassPropertyType["static"] : ClassPropertyType.prototype; - if (match('*')) { - lex(); - return markerApply(marker, delegate.createMethodDefinition( + if (generator) { + return delegate.createMethodDefinition( propType, '', - parseObjectPropertyKey(), + key, parsePropertyMethodFunction({ generator: true }) - )); + ); } - token = lookahead; - //parametricTypeMarker = markerCreate(); - key = parseObjectPropertyKey(); + tokenValue = key.type === 'Identifier' && key.name; - if (token.value === 'get' && !match('(')) { + if (tokenValue === 'get' && !match('(')) { key = parseObjectPropertyKey(); // It is a syntax error if any other properties have a name @@ -6508,14 +7857,17 @@ parseYieldExpression: true expect('('); expect(')'); - return markerApply(marker, delegate.createMethodDefinition( + if (match(':')) { + returnType = parseTypeAnnotation(); + } + return delegate.createMethodDefinition( propType, 'get', key, - parsePropertyFunction({ generator: false }) - )); + parsePropertyFunction({ generator: false, returnType: returnType }) + ); } - if (token.value === 'set' && !match('(')) { + if (tokenValue === 'set' && !match('(')) { key = parseObjectPropertyKey(); // It is a syntax error if any other properties have a name @@ -6540,16 +7892,29 @@ parseYieldExpression: true token = lookahead; param = [ parseTypeAnnotatableIdentifier() ]; expect(')'); - return markerApply(marker, delegate.createMethodDefinition( + if (match(':')) { + returnType = parseTypeAnnotation(); + } + return delegate.createMethodDefinition( propType, 'set', key, - parsePropertyFunction({ params: param, generator: false, name: token }) - )); + parsePropertyFunction({ + params: param, + generator: false, + name: token, + returnType: returnType + }) + ); } if (match('<')) { - parametricType = parseParametricTypeAnnotation(); + typeParameters = parseTypeParameterDeclaration(); + } + + isAsync = tokenValue === 'async' && !match('('); + if (isAsync) { + key = parseObjectPropertyKey(); } // It is a syntax error if any other properties have the same name as a @@ -6561,42 +7926,64 @@ parseYieldExpression: true } existingPropNames[propType][key.name].data = true; - return markerApply(marker, delegate.createMethodDefinition( + return delegate.createMethodDefinition( propType, '', key, parsePropertyMethodFunction({ generator: false, - parametricType: parametricType + async: isAsync, + typeParameters: typeParameters }) - )); + ); } - function parseClassProperty(existingPropNames) { - var marker = markerCreate(), propertyIdentifier; + function parseClassProperty(existingPropNames, key, computed, isStatic) { + var typeAnnotation; - propertyIdentifier = parseTypeAnnotatableIdentifier(); + typeAnnotation = parseTypeAnnotation(); expect(';'); - return markerApply(marker, delegate.createClassProperty( - propertyIdentifier - )); + return delegate.createClassProperty( + key, + typeAnnotation, + computed, + isStatic + ); } function parseClassElement(existingProps) { + var computed, generator = false, key, marker = markerCreate(), + isStatic = false; if (match(';')) { lex(); return; } - var doubleLookahead = lookahead2(); - if (doubleLookahead.type === Token.Punctuator) { - if (doubleLookahead.value === ':') { - return parseClassProperty(existingProps); - } + if (lookahead.value === 'static') { + lex(); + isStatic = true; + } + + if (match('*')) { + lex(); + generator = true; + } + + computed = (lookahead.value === '['); + key = parseObjectPropertyKey(); + + if (!generator && lookahead.value === ':') { + return markerApply(marker, parseClassProperty(existingProps, key, computed, isStatic)); } - return parseMethodDefinition(existingProps); + return markerApply(marker, parseMethodDefinition( + existingProps, + key, + isStatic, + generator, + computed + )); } function parseClassBody() { @@ -6623,66 +8010,109 @@ parseYieldExpression: true return markerApply(marker, delegate.createClassBody(classElements)); } + function parseClassImplements() { + var id, implemented = [], marker, typeParameters; + expectContextualKeyword('implements'); + while (index < length) { + marker = markerCreate(); + id = parseVariableIdentifier(); + if (match('<')) { + typeParameters = parseTypeParameterInstantiation(); + } else { + typeParameters = null; + } + implemented.push(markerApply(marker, delegate.createClassImplements( + id, + typeParameters + ))); + if (!match(',')) { + break; + } + expect(','); + } + return implemented; + } + function parseClassExpression() { - var id, previousYieldAllowed, superClass = null, marker = markerCreate(), - parametricType; + var id, implemented, previousYieldAllowed, superClass = null, + superTypeParameters, marker = markerCreate(), typeParameters; expectKeyword('class'); - if (!matchKeyword('extends') && !match('{')) { + if (!matchKeyword('extends') && !matchContextualKeyword('implements') && !match('{')) { id = parseVariableIdentifier(); } if (match('<')) { - parametricType = parseParametricTypeAnnotation(); + typeParameters = parseTypeParameterDeclaration(); } if (matchKeyword('extends')) { expectKeyword('extends'); previousYieldAllowed = state.yieldAllowed; state.yieldAllowed = false; - superClass = parseAssignmentExpression(); + superClass = parseLeftHandSideExpressionAllowCall(); + if (match('<')) { + superTypeParameters = parseTypeParameterInstantiation(); + } state.yieldAllowed = previousYieldAllowed; } - return markerApply(marker, delegate.createClassExpression(id, superClass, parseClassBody(), parametricType)); + if (matchContextualKeyword('implements')) { + implemented = parseClassImplements(); + } + + return markerApply(marker, delegate.createClassExpression( + id, + superClass, + parseClassBody(), + typeParameters, + superTypeParameters, + implemented + )); } function parseClassDeclaration() { - var id, previousYieldAllowed, superClass = null, marker = markerCreate(), - parametricType, superParametricType; + var id, implemented, previousYieldAllowed, superClass = null, + superTypeParameters, marker = markerCreate(), typeParameters; expectKeyword('class'); id = parseVariableIdentifier(); if (match('<')) { - parametricType = parseParametricTypeAnnotation(); + typeParameters = parseTypeParameterDeclaration(); } if (matchKeyword('extends')) { expectKeyword('extends'); previousYieldAllowed = state.yieldAllowed; state.yieldAllowed = false; - superClass = parseAssignmentExpression(); + superClass = parseLeftHandSideExpressionAllowCall(); + if (match('<')) { + superTypeParameters = parseTypeParameterInstantiation(); + } state.yieldAllowed = previousYieldAllowed; } - return markerApply(marker, delegate.createClassDeclaration(id, superClass, parseClassBody(), parametricType, superParametricType)); + if (matchContextualKeyword('implements')) { + implemented = parseClassImplements(); + } + + return markerApply(marker, delegate.createClassDeclaration( + id, + superClass, + parseClassBody(), + typeParameters, + superTypeParameters, + implemented + )); } // 15 Program - function matchModuleDeclaration() { - var id; - if (matchContextualKeyword('module')) { - id = lookahead2(); - return id.type === Token.StringLiteral || id.type === Token.Identifier; - } - return false; - } - function parseSourceElement() { + var token; if (lookahead.type === Token.Keyword) { switch (lookahead.value) { case 'const': @@ -6690,17 +8120,36 @@ parseYieldExpression: true return parseConstLetDeclaration(lookahead.value); case 'function': return parseFunctionDeclaration(); - case 'export': - return parseExportDeclaration(); - case 'import': - return parseImportDeclaration(); default: return parseStatement(); } } - if (matchModuleDeclaration()) { - throwError({}, Messages.NestedModule); + if (matchContextualKeyword('type') + && lookahead2().type === Token.Identifier) { + return parseTypeAlias(); + } + + if (matchContextualKeyword('interface') + && lookahead2().type === Token.Identifier) { + return parseInterface(); + } + + if (matchContextualKeyword('declare')) { + token = lookahead2(); + if (token.type === Token.Keyword) { + switch (token.value) { + case 'class': + return parseDeclareClass(); + case 'function': + return parseDeclareFunction(); + case 'var': + return parseDeclareVariable(); + } + } else if (token.type === Token.Identifier + && token.value === 'module') { + return parseDeclareModule(); + } } if (lookahead.type !== Token.EOF) { @@ -6718,10 +8167,6 @@ parseYieldExpression: true } } - if (matchModuleDeclaration()) { - return parseModuleDeclaration(); - } - return parseSourceElement(); } @@ -6763,40 +8208,6 @@ parseYieldExpression: true return sourceElements; } - function parseModuleElement() { - return parseSourceElement(); - } - - function parseModuleElements() { - var list = [], - statement; - - while (index < length) { - if (match('}')) { - break; - } - statement = parseModuleElement(); - if (typeof statement === 'undefined') { - break; - } - list.push(statement); - } - - return list; - } - - function parseModuleBlock() { - var block, marker = markerCreate(); - - expect('{'); - - block = parseModuleElements(); - - expect('}'); - - return markerApply(marker, delegate.createBlockStatement(block)); - } - function parseProgram() { var body, marker = markerCreate(); strict = false; @@ -6833,6 +8244,10 @@ parseYieldExpression: true comment.loc = loc; } extra.comments.push(comment); + if (extra.attachComment) { + extra.leadingComments.push(comment); + extra.trailingComments.push(comment); + } } function scanComment() { @@ -6873,17 +8288,18 @@ parseYieldExpression: true } } else if (blockComment) { if (isLineTerminator(ch.charCodeAt(0))) { - if (ch === '\r' && source[index + 1] === '\n') { + if (ch === '\r') { ++index; - comment += '\r\n'; - } else { - comment += ch; + comment += '\r'; } - ++lineNumber; - ++index; - lineStart = index; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + if (ch !== '\r' || source[index] === '\n') { + comment += source[index]; + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } } } else { ch = source[index++]; @@ -7262,7 +8678,7 @@ parseYieldExpression: true } function scanXJSEntity() { - var ch, str = '', count = 0, entity; + var ch, str = '', start = index, count = 0, code; ch = source[index]; assert(ch === '&', 'Entity must start with an ampersand'); index++; @@ -7274,14 +8690,28 @@ parseYieldExpression: true str += ch; } - if (str[0] === '#' && str[1] === 'x') { - entity = String.fromCharCode(parseInt(str.substr(2), 16)); - } else if (str[0] === '#') { - entity = String.fromCharCode(parseInt(str.substr(1), 10)); - } else { - entity = XHTMLEntities[str]; + // Well-formed entity (ending was found). + if (ch === ';') { + // Numeric entity. + if (str[0] === '#') { + if (str[1] === 'x') { + code = +('0' + str.substr(1)); + } else { + // Removing leading zeros in order to avoid treating as octal in old browsers. + code = +str.substr(1).replace(Regex.LeadingZeros, ''); + } + + if (!isNaN(code)) { + return String.fromCharCode(code); + } + } else if (XHTMLEntities[str]) { + return XHTMLEntities[str]; + } } - return entity; + + // Treat non-entity sequences as regular text. + index = start + 1; + return '&'; } function scanXJSText(stopChars) { @@ -7296,6 +8726,11 @@ parseYieldExpression: true str += scanXJSEntity(); } else { index++; + if (ch === '\r' && source[index] === '\n') { + str += ch; + ch = source[index]; + index++; + } if (isLineTerminator(ch.charCodeAt(0))) { ++lineNumber; lineStart = index; @@ -7564,7 +8999,7 @@ parseYieldExpression: true } function parseXJSElement() { - var openingElement, closingElement, children = [], origInXJSChild, origInXJSTag, marker = markerCreate(); + var openingElement, closingElement = null, children = [], origInXJSChild, origInXJSTag, marker = markerCreate(); origInXJSChild = state.inXJSChild; origInXJSTag = state.inXJSTag; @@ -7603,8 +9038,181 @@ parseYieldExpression: true return markerApply(marker, delegate.createXJSElement(openingElement, closingElement, children)); } + function parseTypeAlias() { + var id, marker = markerCreate(), typeParameters = null, right; + expectContextualKeyword('type'); + id = parseVariableIdentifier(); + if (match('<')) { + typeParameters = parseTypeParameterDeclaration(); + } + expect('='); + right = parseType(); + consumeSemicolon(); + return markerApply(marker, delegate.createTypeAlias(id, typeParameters, right)); + } + + function parseInterfaceExtends() { + var marker = markerCreate(), id, typeParameters = null; + + id = parseVariableIdentifier(); + if (match('<')) { + typeParameters = parseTypeParameterInstantiation(); + } + + return markerApply(marker, delegate.createInterfaceExtends( + id, + typeParameters + )); + } + + function parseInterfaceish(marker, allowStatic) { + var body, bodyMarker, extended = [], id, + typeParameters = null; + + id = parseVariableIdentifier(); + if (match('<')) { + typeParameters = parseTypeParameterDeclaration(); + } + + if (matchKeyword('extends')) { + expectKeyword('extends'); + + while (index < length) { + extended.push(parseInterfaceExtends()); + if (!match(',')) { + break; + } + expect(','); + } + } + + bodyMarker = markerCreate(); + body = markerApply(bodyMarker, parseObjectType(allowStatic)); + + return markerApply(marker, delegate.createInterface( + id, + typeParameters, + body, + extended + )); + } + + function parseInterface() { + var body, bodyMarker, extended = [], id, marker = markerCreate(), + typeParameters = null; + + expectContextualKeyword('interface'); + return parseInterfaceish(marker, /* allowStatic */false); + } + + function parseDeclareClass() { + var marker = markerCreate(), ret; + expectContextualKeyword('declare'); + expectKeyword('class'); + + ret = parseInterfaceish(marker, /* allowStatic */true); + ret.type = Syntax.DeclareClass; + return ret; + } + + function parseDeclareFunction() { + var id, idMarker, + marker = markerCreate(), params, returnType, rest, tmp, + typeParameters = null, value, valueMarker; + + expectContextualKeyword('declare'); + expectKeyword('function'); + idMarker = markerCreate(); + id = parseVariableIdentifier(); + + valueMarker = markerCreate(); + if (match('<')) { + typeParameters = parseTypeParameterDeclaration(); + } + expect('('); + tmp = parseFunctionTypeParams(); + params = tmp.params; + rest = tmp.rest; + expect(')'); + + expect(':'); + returnType = parseType(); + + value = markerApply(valueMarker, delegate.createFunctionTypeAnnotation( + params, + returnType, + rest, + typeParameters + )); + + id.typeAnnotation = markerApply(valueMarker, delegate.createTypeAnnotation( + value + )); + markerApply(idMarker, id); + + consumeSemicolon(); + + return markerApply(marker, delegate.createDeclareFunction( + id + )); + } + + function parseDeclareVariable() { + var id, marker = markerCreate(); + expectContextualKeyword('declare'); + expectKeyword('var'); + id = parseTypeAnnotatableIdentifier(); + + consumeSemicolon(); + + return markerApply(marker, delegate.createDeclareVariable( + id + )); + } + + function parseDeclareModule() { + var body = [], bodyMarker, id, idMarker, marker = markerCreate(), token; + expectContextualKeyword('declare'); + expectContextualKeyword('module'); + + if (lookahead.type === Token.StringLiteral) { + if (strict && lookahead.octal) { + throwErrorTolerant(lookahead, Messages.StrictOctalLiteral); + } + idMarker = markerCreate(); + id = markerApply(idMarker, delegate.createLiteral(lex())); + } else { + id = parseVariableIdentifier(); + } + + bodyMarker = markerCreate(); + expect('{'); + while (index < length && !match('}')) { + token = lookahead2(); + switch (token.value) { + case 'class': + body.push(parseDeclareClass()); + break; + case 'function': + body.push(parseDeclareFunction()); + break; + case 'var': + body.push(parseDeclareVariable()); + break; + default: + throwUnexpected(lookahead); + } + } + expect('}'); + + return markerApply(marker, delegate.createDeclareModule( + id, + markerApply(bodyMarker, delegate.createBlockStatement(body)) + )); + } + function collectToken() { - var start, loc, token, range, value; + var start, loc, token, range, value, entry; if (!state.inXJSChild) { skipComment(); @@ -7627,12 +9235,19 @@ parseYieldExpression: true if (token.type !== Token.EOF) { range = [token.range[0], token.range[1]]; value = source.slice(token.range[0], token.range[1]); - extra.tokens.push({ + entry = { type: TokenName[token.type], value: value, range: range, loc: loc - }); + }; + if (token.regex) { + entry.regex = { + pattern: token.regex.pattern, + flags: token.regex.flags + }; + } + extra.tokens.push(entry); } return token; @@ -7671,6 +9286,7 @@ parseYieldExpression: true extra.tokens.push({ type: 'RegularExpression', value: regex.literal, + regex: regex.regex, range: [pos, index], loc: loc }); @@ -7688,6 +9304,12 @@ parseYieldExpression: true type: entry.type, value: entry.value }; + if (entry.regex) { + token.regex = { + pattern: entry.regex.pattern, + flags: entry.regex.flags + }; + } if (extra.range) { token.range = entry.range; } @@ -7874,14 +9496,17 @@ parseYieldExpression: true inSwitch: false, inXJSChild: false, inXJSTag: false, + inType: false, lastCommentStart: -1, - yieldAllowed: false + yieldAllowed: false, + awaitAllowed: false }; extra = {}; if (typeof options !== 'undefined') { extra.range = (typeof options.range === 'boolean') && options.range; extra.loc = (typeof options.loc === 'boolean') && options.loc; + extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment; if (extra.loc && options.source !== null && options.source !== undefined) { delegate = extend(delegate, { @@ -7901,6 +9526,13 @@ parseYieldExpression: true if (typeof options.tolerant === 'boolean' && options.tolerant) { extra.errors = []; } + if (extra.attachComment) { + extra.range = true; + extra.comments = []; + extra.bottomRightStack = []; + extra.trailingComments = []; + extra.leadingComments = []; + } } if (length > 0) { @@ -7938,7 +9570,7 @@ parseYieldExpression: true } // Sync with *.json manifests. - exports.version = '4001.3001.0000-dev-harmony-fb'; + exports.version = '8001.1001.0-dev-harmony-fb'; exports.tokenize = tokenize; @@ -7968,35 +9600,7 @@ parseYieldExpression: true })); /* vim: set sw=4 ts=4 et tw=80 : */ -},{}],7:[function(_dereq_,module,exports){ -var Base62 = (function (my) { - my.chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] - - my.encode = function(i){ - if (i === 0) {return '0'} - var s = '' - while (i > 0) { - s = this.chars[i % 62] + s - i = Math.floor(i/62) - } - return s - }; - my.decode = function(a,b,c,d){ - for ( - b = c = ( - a === (/\W|_|^$/.test(a += "") || a) - ) - 1; - d = a.charCodeAt(c++); - ) - b = b * 62 + d - [, 48, 29, 87][d >> 5]; - return b - }; - - return my; -}({})); - -module.exports = Base62 -},{}],8:[function(_dereq_,module,exports){ +},{}],10:[function(_dereq_,module,exports){ /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: @@ -8006,7 +9610,7 @@ exports.SourceMapGenerator = _dereq_('./source-map/source-map-generator').Source exports.SourceMapConsumer = _dereq_('./source-map/source-map-consumer').SourceMapConsumer; exports.SourceNode = _dereq_('./source-map/source-node').SourceNode; -},{"./source-map/source-map-consumer":13,"./source-map/source-map-generator":14,"./source-map/source-node":15}],9:[function(_dereq_,module,exports){ +},{"./source-map/source-map-consumer":15,"./source-map/source-map-generator":16,"./source-map/source-node":17}],11:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -8105,7 +9709,7 @@ define(function (_dereq_, exports, module) { }); -},{"./util":16,"amdefine":17}],10:[function(_dereq_,module,exports){ +},{"./util":18,"amdefine":19}],12:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -8251,7 +9855,7 @@ define(function (_dereq_, exports, module) { }); -},{"./base64":11,"amdefine":17}],11:[function(_dereq_,module,exports){ +},{"./base64":13,"amdefine":19}],13:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -8295,7 +9899,7 @@ define(function (_dereq_, exports, module) { }); -},{"amdefine":17}],12:[function(_dereq_,module,exports){ +},{"amdefine":19}],14:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -8378,7 +9982,7 @@ define(function (_dereq_, exports, module) { }); -},{"amdefine":17}],13:[function(_dereq_,module,exports){ +},{"amdefine":19}],15:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -8857,7 +10461,7 @@ define(function (_dereq_, exports, module) { }); -},{"./array-set":9,"./base64-vlq":10,"./binary-search":12,"./util":16,"amdefine":17}],14:[function(_dereq_,module,exports){ +},{"./array-set":11,"./base64-vlq":12,"./binary-search":14,"./util":18,"amdefine":19}],16:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -9239,7 +10843,7 @@ define(function (_dereq_, exports, module) { }); -},{"./array-set":9,"./base64-vlq":10,"./util":16,"amdefine":17}],15:[function(_dereq_,module,exports){ +},{"./array-set":11,"./base64-vlq":12,"./util":18,"amdefine":19}],17:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -9612,7 +11216,7 @@ define(function (_dereq_, exports, module) { }); -},{"./source-map-generator":14,"./util":16,"amdefine":17}],16:[function(_dereq_,module,exports){ +},{"./source-map-generator":16,"./util":18,"amdefine":19}],18:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -9819,7 +11423,7 @@ define(function (_dereq_, exports, module) { }); -},{"amdefine":17}],17:[function(_dereq_,module,exports){ +},{"amdefine":19}],19:[function(_dereq_,module,exports){ (function (process,__filename){ /** vim: et:ts=4:sw=4:sts=4 * @license amdefine 0.1.0 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. @@ -10121,8 +11725,8 @@ function amdefine(module, requireFn) { module.exports = amdefine; -}).call(this,_dereq_("FWaASH"),"/../node_modules/jstransform/node_modules/source-map/node_modules/amdefine/amdefine.js") -},{"FWaASH":5,"path":4}],18:[function(_dereq_,module,exports){ +}).call(this,_dereq_('_process'),"/node_modules/jstransform/node_modules/source-map/node_modules/amdefine/amdefine.js") +},{"_process":7,"path":6}],20:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -10210,7 +11814,7 @@ exports.extract = extract; exports.parse = parse; exports.parseAsObject = parseAsObject; -},{}],19:[function(_dereq_,module,exports){ +},{}],21:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -10268,7 +11872,6 @@ function _nodeIsBlockScopeBoundary(node, parentNode) { /** * @param {object} node - * @param {function} visitor * @param {array} path * @param {object} state */ @@ -10464,8 +12067,9 @@ function transform(visitors, source, options) { } exports.transform = transform; +exports.Syntax = Syntax; -},{"./utils":20,"esprima-fb":6,"source-map":8}],20:[function(_dereq_,module,exports){ +},{"./utils":22,"esprima-fb":9,"source-map":10}],22:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -10916,8 +12520,8 @@ function initScopeMetadata(boundaryNode, path, node) { function declareIdentInLocalScope(identName, metaData, state) { state.localScope.identifiers[identName] = { boundaryNode: metaData.boundaryNode, - path: metaData.path, - node: metaData.node, + path: metaData.bindingPath, + node: metaData.bindingNode, state: Object.create(state) }; } @@ -10934,7 +12538,6 @@ function getLexicalBindingMetadata(identName, state) { * @param {function} analyzer * @param {function} traverser * @param {object} node - * @param {function} visitor * @param {array} path * @param {object} state */ @@ -11011,16 +12614,22 @@ function enqueueNodeWithStartIndex(queue, node) { * @param {string} type - node type to lookup. */ function containsChildOfType(node, type) { + return containsChildMatching(node, function(node) { + return node.type === type; + }); +} + +function containsChildMatching(node, matcher) { var foundMatchingChild = false; function nodeTypeAnalyzer(node) { - if (node.type === type) { + if (matcher(node) === true) { foundMatchingChild = true; return false; } } function nodeTypeTraverser(child, path, state) { if (!foundMatchingChild) { - foundMatchingChild = containsChildOfType(child, type); + foundMatchingChild = containsChildMatching(child, matcher); } } analyzeAndTraverse( @@ -11049,11 +12658,20 @@ function getBoundaryNode(path) { ); } +function getTempVar(tempVarIndex) { + return '$__' + tempVarIndex; +} + +function getTempVarWithValue(tempVarIndex, tempVarValue) { + return getTempVar(tempVarIndex) + '=' + tempVarValue; +} + exports.append = append; exports.catchup = catchup; exports.catchupWhiteOut = catchupWhiteOut; exports.catchupWhiteSpace = catchupWhiteSpace; exports.catchupNewlines = catchupNewlines; +exports.containsChildMatching = containsChildMatching; exports.containsChildOfType = containsChildOfType; exports.createState = createState; exports.declareIdentInLocalScope = declareIdentInLocalScope; @@ -11071,8 +12689,10 @@ exports.updateState = updateState; exports.analyzeAndTraverse = analyzeAndTraverse; exports.getOrderedChildren = getOrderedChildren; exports.getNodeSourceText = getNodeSourceText; +exports.getTempVar = getTempVar; +exports.getTempVarWithValue = getTempVarWithValue; -},{"./docblock":18,"esprima-fb":6}],21:[function(_dereq_,module,exports){ +},{"./docblock":20,"esprima-fb":9}],23:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -11147,7 +12767,14 @@ function visitArrowFunction(traverse, node, path, state) { // Bind the function only if `this` value is used // inside it or inside any sub-expression. - if (utils.containsChildOfType(node.body, Syntax.ThisExpression)) { + var containsBindingSyntax = + utils.containsChildMatching(node.body, function(node) { + return node.type === Syntax.ThisExpression + || (node.type === Syntax.Identifier + && node.name === "super"); + }); + + if (containsBindingSyntax) { utils.append('.bind(this)', state); } @@ -11188,7 +12815,7 @@ function renderExpressionBody(traverse, node, path, state) { // Special handling of rest param. if (node.rest) { utils.append( - restParamVisitors.renderRestParamSetup(node), + restParamVisitors.renderRestParamSetup(node, state), state ); } @@ -11225,7 +12852,7 @@ exports.visitorList = [ ]; -},{"../src/utils":20,"./es6-destructuring-visitors":23,"./es6-rest-param-visitors":26,"esprima-fb":6}],22:[function(_dereq_,module,exports){ +},{"../src/utils":22,"./es6-destructuring-visitors":25,"./es6-rest-param-visitors":28,"esprima-fb":9}],24:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -11252,6 +12879,7 @@ exports.visitorList = [ var base62 = _dereq_('base62'); var Syntax = _dereq_('esprima-fb').Syntax; var utils = _dereq_('../src/utils'); +var reservedWordsHelper = _dereq_('./reserved-words-helper'); var declareIdentInLocalScope = utils.declareIdentInLocalScope; var initScopeMetadata = utils.initScopeMetadata; @@ -11370,7 +12998,7 @@ function _shouldMungeIdentifier(node, state) { * @param {object} state */ function visitClassMethod(traverse, node, path, state) { - if (node.kind === 'get' || node.kind === 'set') { + if (!state.g.opts.es5 && (node.kind === 'get' || node.kind === 'set')) { throw new Error( 'This transform does not support ' + node.kind + 'ter methods for ES6 ' + 'classes. (line: ' + node.loc.start.line + ', col: ' + @@ -11398,6 +13026,8 @@ visitClassMethod.test = function(node, path, state) { */ function visitClassFunctionExpression(traverse, node, path, state) { var methodNode = path[0]; + var isGetter = methodNode.kind === 'get'; + var isSetter = methodNode.kind === 'set'; state = utils.updateState(state, { methodFuncNode: node @@ -11408,6 +13038,7 @@ function visitClassFunctionExpression(traverse, node, path, state) { } else { var methodAccessor; var prototypeOrStatic = methodNode["static"] ? '' : '.prototype'; + var objectAccessor = state.className + prototypeOrStatic; if (methodNode.key.type === Syntax.Identifier) { // foo() {} @@ -11415,24 +13046,44 @@ function visitClassFunctionExpression(traverse, node, path, state) { if (_shouldMungeIdentifier(methodNode.key, state)) { methodAccessor = _getMungedName(methodAccessor, state); } - methodAccessor = '.' + methodAccessor; + if (isGetter || isSetter) { + methodAccessor = JSON.stringify(methodAccessor); + } else if (reservedWordsHelper.isReservedWord(methodAccessor)) { + methodAccessor = '[' + JSON.stringify(methodAccessor) + ']'; + } else { + methodAccessor = '.' + methodAccessor; + } } else if (methodNode.key.type === Syntax.Literal) { - // 'foo bar'() {} - methodAccessor = '[' + JSON.stringify(methodNode.key.value) + ']'; + // 'foo bar'() {} | get 'foo bar'() {} | set 'foo bar'() {} + methodAccessor = JSON.stringify(methodNode.key.value); + if (!(isGetter || isSetter)) { + methodAccessor = '[' + methodAccessor + ']'; + } } - utils.append( - state.className + prototypeOrStatic + - methodAccessor + '=function', - state - ); + if (isSetter || isGetter) { + utils.append( + 'Object.defineProperty(' + + objectAccessor + ',' + + methodAccessor + ',' + + '{enumerable:true,configurable:true,' + + methodNode.kind + ':function', + state + ); + } else { + utils.append( + objectAccessor + + methodAccessor + '=function' + (node.generator ? '*' : ''), + state + ); + } } utils.move(methodNode.key.range[1], state); utils.append('(', state); var params = node.params; if (params.length > 0) { - utils.move(params[0].range[0], state); + utils.catchupNewlines(params[0].range[0], state); for (var i = 0; i < params.length; i++) { utils.catchup(node.params[i].range[0], state); path.unshift(node); @@ -11457,6 +13108,9 @@ function visitClassFunctionExpression(traverse, node, path, state) { utils.catchup(node.body.range[1], state); if (methodNode.key.name !== 'constructor') { + if (isGetter || isSetter) { + utils.append('})', state); + } utils.append(';', state); } return false; @@ -11767,7 +13421,7 @@ exports.visitorList = [ visitSuperMemberExpression ]; -},{"../src/utils":20,"base62":7,"esprima-fb":6}],23:[function(_dereq_,module,exports){ +},{"../src/utils":22,"./reserved-words-helper":32,"base62":8,"esprima-fb":9}],25:[function(_dereq_,module,exports){ /** * Copyright 2014 Facebook, Inc. * @@ -11810,7 +13464,9 @@ exports.visitorList = [ var Syntax = _dereq_('esprima-fb').Syntax; var utils = _dereq_('../src/utils'); +var reservedWordsHelper = _dereq_('./reserved-words-helper'); var restParamVisitors = _dereq_('./es6-rest-param-visitors'); +var restPropertyHelpers = _dereq_('./es7-rest-property-helpers'); // ------------------------------------------------------- // 1. Structured variable declarations. @@ -11821,7 +13477,7 @@ var restParamVisitors = _dereq_('./es6-rest-param-visitors'); function visitStructuredVariable(traverse, node, path, state) { // Allocate new temp for the pattern. - utils.append(getTmpVar(state.localScope.tempVarIndex) + '=', state); + utils.append(utils.getTempVar(state.localScope.tempVarIndex) + '=', state); // Skip the pattern and assign the init to the temp. utils.catchupWhiteSpace(node.init.range[0], state); traverse(node.init, path, state); @@ -11855,6 +13511,26 @@ function getDestructuredComponents(node, state) { continue; } + if (item.type === Syntax.SpreadElement) { + // Spread/rest of an array. + // TODO(dmitrys): support spread in the middle of a pattern + // and also for function param patterns: [x, ...xs, y] + components.push(item.argument.name + + '=Array.prototype.slice.call(' + + utils.getTempVar(tmpIndex) + ',' + idx + ')' + ); + continue; + } + + if (item.type === Syntax.SpreadProperty) { + var restExpression = restPropertyHelpers.renderRestExpression( + utils.getTempVar(tmpIndex), + patternItems + ); + components.push(item.argument.name + '=' + restExpression); + continue; + } + // Depending on pattern type (Array or Object), we get // corresponding pattern item parts. var accessor = getPatternItemAccessor(node, item, tmpIndex, idx); @@ -11864,19 +13540,11 @@ function getDestructuredComponents(node, state) { if (value.type === Syntax.Identifier) { // Simple pattern item. components.push(value.name + '=' + accessor); - } else if (value.type === Syntax.SpreadElement) { - // Spread/rest of an array. - // TODO(dmitrys): support spread in the middle of a pattern - // and also for function param patterns: [x, ...xs, y] - components.push(value.argument.name + - '=Array.prototype.slice.call(' + - getTmpVar(tmpIndex) + ',' + idx + ')' - ); } else { // Complex sub-structure. components.push( - getInitialValue(++state.localScope.tempVarIndex, accessor) + ',' + - getDestructuredComponents(value, state) + utils.getTempVarWithValue(++state.localScope.tempVarIndex, accessor) + + ',' + getDestructuredComponents(value, state) ); } } @@ -11889,10 +13557,18 @@ function getPatternItems(node) { } function getPatternItemAccessor(node, patternItem, tmpIndex, idx) { - var tmpName = getTmpVar(tmpIndex); - return node.type === Syntax.ObjectPattern - ? tmpName + '.' + patternItem.key.name - : tmpName + '[' + idx + ']'; + var tmpName = utils.getTempVar(tmpIndex); + if (node.type === Syntax.ObjectPattern) { + if (reservedWordsHelper.isReservedWord(patternItem.key.name)) { + return tmpName + '["' + patternItem.key.name + '"]'; + } else if (patternItem.key.type === Syntax.Literal) { + return tmpName + '[' + JSON.stringify(patternItem.key.value) + ']'; + } else if (patternItem.key.type === Syntax.Identifier) { + return tmpName + '.' + patternItem.key.name; + } + } else if (node.type === Syntax.ArrayPattern) { + return tmpName + '[' + idx + ']'; + } } function getPatternItemValue(node, patternItem) { @@ -11901,14 +13577,6 @@ function getPatternItemValue(node, patternItem) { : patternItem; } -function getInitialValue(index, value) { - return getTmpVar(index) + '=' + value; -} - -function getTmpVar(index) { - return '$__' + index; -} - // ------------------------------------------------------- // 2. Assignment expression. // @@ -11918,14 +13586,14 @@ function getTmpVar(index) { function visitStructuredAssignment(traverse, node, path, state) { var exprNode = node.expression; - utils.append('var ' + getTmpVar(state.localScope.tempVarIndex) + '=', state); + utils.append('var ' + utils.getTempVar(state.localScope.tempVarIndex) + '=', state); utils.catchupWhiteSpace(exprNode.right.range[0], state); traverse(exprNode.right, path, state); utils.catchup(exprNode.right.range[1], state); utils.append( - ',' + getDestructuredComponents(exprNode.left, state) + ';', + ';' + getDestructuredComponents(exprNode.left, state) + ';', state ); @@ -11950,7 +13618,7 @@ visitStructuredAssignment.test = function(node, path, state) { // ------------------------------------------------------- function visitStructuredParameter(traverse, node, path, state) { - utils.append(getTmpVar(getParamIndex(node, path)), state); + utils.append(utils.getTempVar(getParamIndex(node, path)), state); utils.catchupWhiteSpace(node.range[1], state); return true; } @@ -11995,7 +13663,7 @@ function visitFunctionBodyForStructuredParameter(traverse, node, path, state) { if (funcNode.rest) { utils.append( - restParamVisitors.renderRestParamSetup(funcNode), + restParamVisitors.renderRestParamSetup(funcNode, state), state ); } @@ -12035,7 +13703,7 @@ exports.visitorList = [ exports.renderDestructuredComponents = renderDestructuredComponents; -},{"../src/utils":20,"./es6-rest-param-visitors":26,"esprima-fb":6}],24:[function(_dereq_,module,exports){ +},{"../src/utils":22,"./es6-rest-param-visitors":28,"./es7-rest-property-helpers":30,"./reserved-words-helper":32,"esprima-fb":9}],26:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -12055,7 +13723,7 @@ exports.renderDestructuredComponents = renderDestructuredComponents; /*jslint node:true*/ /** - * Desugars concise methods of objects to ES3 function expressions. + * Desugars concise methods of objects to function expressions. * * var foo = { * method(x, y) { ... } @@ -12069,10 +13737,27 @@ exports.renderDestructuredComponents = renderDestructuredComponents; var Syntax = _dereq_('esprima-fb').Syntax; var utils = _dereq_('../src/utils'); +var reservedWordsHelper = _dereq_('./reserved-words-helper'); function visitObjectConciseMethod(traverse, node, path, state) { + var isGenerator = node.value.generator; + if (isGenerator) { + utils.catchupWhiteSpace(node.range[0] + 1, state); + } + if (node.computed) { // [<expr>]() { ...} + utils.catchup(node.key.range[1] + 1, state); + } else if (reservedWordsHelper.isReservedWord(node.key.name)) { + utils.catchup(node.key.range[0], state); + utils.append('"', state); + utils.catchup(node.key.range[1], state); + utils.append('"', state); + } + utils.catchup(node.key.range[1], state); - utils.append(':function', state); + utils.append( + ':function' + (isGenerator ? '*' : ''), + state + ); path.unshift(node); traverse(node.value, path, state); path.shift(); @@ -12089,7 +13774,7 @@ exports.visitorList = [ visitObjectConciseMethod ]; -},{"../src/utils":20,"esprima-fb":6}],25:[function(_dereq_,module,exports){ +},{"../src/utils":22,"./reserved-words-helper":32,"esprima-fb":9}],27:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -12116,7 +13801,7 @@ exports.visitorList = [ * return {x, y}; // {x: x, y: y} * }; * - * // Destrucruting. + * // Destructuring. * function init({port, ip, coords: {x, y}}) { ... } * */ @@ -12144,7 +13829,7 @@ exports.visitorList = [ ]; -},{"../src/utils":20,"esprima-fb":6}],26:[function(_dereq_,module,exports){ +},{"../src/utils":22,"esprima-fb":9}],28:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -12164,16 +13849,20 @@ exports.visitorList = [ /*jslint node:true*/ /** - * Desugars ES6 rest parameters into ES3 arguments slicing. + * Desugars ES6 rest parameters into an ES3 arguments array. * * function printf(template, ...args) { * args.forEach(...); - * }; + * } + * + * We could use `Array.prototype.slice.call`, but that usage of arguments causes + * functions to be deoptimized in V8, so instead we use a for-loop. * * function printf(template) { - * var args = [].slice.call(arguments, 1); + * for (var args = [], $__0 = 1, $__1 = arguments.length; $__0 < $__1; $__0++) + * args.push(arguments[$__0]); * args.forEach(...); - * }; + * } * */ var Syntax = _dereq_('esprima-fb').Syntax; @@ -12218,17 +13907,22 @@ visitFunctionParamsWithRestParam.test = function(node, path, state) { return _nodeIsFunctionWithRestParam(node); }; -function renderRestParamSetup(functionNode) { - return 'var ' + functionNode.rest.name + '=Array.prototype.slice.call(' + - 'arguments,' + - functionNode.params.length + - ');'; +function renderRestParamSetup(functionNode, state) { + var idx = state.localScope.tempVarIndex++; + var len = state.localScope.tempVarIndex++; + + return 'for (var ' + functionNode.rest.name + '=[],' + + utils.getTempVarWithValue(idx, functionNode.params.length) + ',' + + utils.getTempVarWithValue(len, 'arguments.length') + ';' + + utils.getTempVar(idx) + '<' + utils.getTempVar(len) + ';' + + utils.getTempVar(idx) + '++) ' + + functionNode.rest.name + '.push(arguments[' + utils.getTempVar(idx) + ']);'; } function visitFunctionBodyWithRestParam(traverse, node, path, state) { utils.catchup(node.range[0] + 1, state); var parentNode = path[0]; - utils.append(renderRestParamSetup(parentNode), state); + utils.append(renderRestParamSetup(parentNode, state), state); return true; } @@ -12243,7 +13937,7 @@ exports.visitorList = [ visitFunctionBodyWithRestParam ]; -},{"../src/utils":20,"esprima-fb":6}],27:[function(_dereq_,module,exports){ +},{"../src/utils":22,"esprima-fb":9}],29:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -12401,9 +14095,9 @@ exports.visitorList = [ visitTaggedTemplateExpression ]; -},{"../src/utils":20,"esprima-fb":6}],28:[function(_dereq_,module,exports){ +},{"../src/utils":22,"esprima-fb":9}],30:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12417,319 +14111,186 @@ exports.visitorList = [ * See the License for the specific language governing permissions and * limitations under the License. */ -/* jshint browser: true */ -/* jslint evil: true */ - -'use strict'; -var buffer = _dereq_('buffer'); -var docblock = _dereq_('jstransform/src/docblock'); -var transform = _dereq_('jstransform').transform; -var visitors = _dereq_('./fbtransform/visitors'); - -var headEl; -var dummyAnchor; -var inlineScriptCount = 0; - -// The source-map library relies on Object.defineProperty, but IE8 doesn't -// support it fully even with es5-sham. Indeed, es5-sham's defineProperty -// throws when Object.prototype.__defineGetter__ is missing, so we skip building -// the source map in that case. -var supportsAccessors = Object.prototype.hasOwnProperty('__defineGetter__'); +/*jslint node:true*/ /** - * Run provided code through jstransform. - * - * @param {string} source Original source code - * @param {object?} options Options to pass to jstransform - * @return {object} object as returned from jstransform + * Desugars ES7 rest properties into ES5 object iteration. */ -function transformReact(source, options) { - // TODO: just use react-tools - var visitorList; - if (options && options.harmony) { - visitorList = visitors.getAllVisitors(); - } else { - visitorList = visitors.transformVisitors.react; + +var Syntax = _dereq_('esprima-fb').Syntax; +var utils = _dereq_('../src/utils'); + +// TODO: This is a pretty massive helper, it should only be defined once, in the +// transform's runtime environment. We don't currently have a runtime though. +var restFunction = + '(function(source, exclusion) {' + + 'var rest = {};' + + 'var hasOwn = Object.prototype.hasOwnProperty;' + + 'if (source == null) {' + + 'throw new TypeError();' + + '}' + + 'for (var key in source) {' + + 'if (hasOwn.call(source, key) && !hasOwn.call(exclusion, key)) {' + + 'rest[key] = source[key];' + + '}' + + '}' + + 'return rest;' + + '})'; + +function getPropertyNames(properties) { + var names = []; + for (var i = 0; i < properties.length; i++) { + var property = properties[i]; + if (property.type === Syntax.SpreadProperty) { + continue; + } + if (property.type === Syntax.Identifier) { + names.push(property.name); + } else { + names.push(property.key.name); + } } + return names; +} - return transform(visitorList, source, { - sourceMap: supportsAccessors - }); +function getRestFunctionCall(source, exclusion) { + return restFunction + '(' + source + ',' + exclusion + ')'; +} + +function getSimpleShallowCopy(accessorExpression) { + // This could be faster with 'Object.assign({}, ' + accessorExpression + ')' + // but to unify code paths and avoid a ES6 dependency we use the same + // helper as for the exclusion case. + return getRestFunctionCall(accessorExpression, '{}'); +} + +function renderRestExpression(accessorExpression, excludedProperties) { + var excludedNames = getPropertyNames(excludedProperties); + if (!excludedNames.length) { + return getSimpleShallowCopy(accessorExpression); + } + return getRestFunctionCall( + accessorExpression, + '{' + excludedNames.join(':1,') + ':1}' + ); } +exports.renderRestExpression = renderRestExpression; + +},{"../src/utils":22,"esprima-fb":9}],31:[function(_dereq_,module,exports){ /** - * Eval provided source after transforming it. - * - * @param {string} source Original source code - * @param {object?} options Options to pass to jstransform + * Copyright 2004-present Facebook. All Rights Reserved. */ -function exec(source, options) { - return eval(transformReact(source, options).code); -} +/*global exports:true*/ /** - * This method returns a nicely formated line of code pointing to the exact - * location of the error `e`. The line is limited in size so big lines of code - * are also shown in a readable way. + * Implements ES7 object spread property. + * https://gist.github.com/sebmarkbage/aa849c7973cb4452c547 * - * Example: - * ... x', overflow:'scroll'}} id={} onScroll={this.scroll} class=" ... - * ^ + * { ...a, x: 1 } + * + * Object.assign({}, a, {x: 1 }) * - * @param {string} code The full string of code - * @param {Error} e The error being thrown - * @return {string} formatted message - * @internal */ -function createSourceCodeErrorMessage(code, e) { - var sourceLines = code.split('\n'); - var erroneousLine = sourceLines[e.lineNumber - 1]; - // Removes any leading indenting spaces and gets the number of - // chars indenting the `erroneousLine` - var indentation = 0; - erroneousLine = erroneousLine.replace(/^\s+/, function(leadingSpaces) { - indentation = leadingSpaces.length; - return ''; - }); +var Syntax = _dereq_('esprima-fb').Syntax; +var utils = _dereq_('../src/utils'); - // Defines the number of characters that are going to show - // before and after the erroneous code - var LIMIT = 30; - var errorColumn = e.column - indentation; +function visitObjectLiteralSpread(traverse, node, path, state) { + utils.catchup(node.range[0], state); - if (errorColumn > LIMIT) { - erroneousLine = '... ' + erroneousLine.slice(errorColumn - LIMIT); - errorColumn = 4 + LIMIT; - } - if (erroneousLine.length - errorColumn > LIMIT) { - erroneousLine = erroneousLine.slice(0, errorColumn + LIMIT) + ' ...'; - } - var message = '\n\n' + erroneousLine + '\n'; - message += new Array(errorColumn - 1).join(' ') + '^'; - return message; -} + utils.append('Object.assign({', state); -/** - * Actually transform the code. - * - * @param {string} code - * @param {string?} url - * @param {object?} options - * @return {string} The transformed code. - * @internal - */ -function transformCode(code, url, options) { - var jsx = docblock.parseAsObject(docblock.extract(code)).jsx; - - if (jsx) { - try { - var transformed = transformReact(code, options); - } catch(e) { - e.message += '\n at '; - if (url) { - if ('fileName' in e) { - // We set `fileName` if it's supported by this error object and - // a `url` was provided. - // The error will correctly point to `url` in Firefox. - e.fileName = url; - } - e.message += url + ':' + e.lineNumber + ':' + e.column; - } else { - e.message += location.href; - } - e.message += createSourceCodeErrorMessage(code, e); - throw e; - } + // Skip the original { + utils.move(node.range[0] + 1, state); - if (!transformed.sourceMap) { - return transformed.code; - } + var previousWasSpread = false; + + for (var i = 0; i < node.properties.length; i++) { + var property = node.properties[i]; + if (property.type === Syntax.SpreadProperty) { - var map = transformed.sourceMap.toJSON(); - var source; - if (url == null) { - source = "Inline JSX script"; - inlineScriptCount++; - if (inlineScriptCount > 1) { - source += ' (' + inlineScriptCount + ')'; + // Close the previous object or initial object + if (!previousWasSpread) { + utils.append('}', state); } - } else if (dummyAnchor) { - // Firefox has problems when the sourcemap source is a proper URL with a - // protocol and hostname, so use the pathname. We could use just the - // filename, but hopefully using the full path will prevent potential - // issues where the same filename exists in multiple directories. - dummyAnchor.href = url; - source = dummyAnchor.pathname.substr(1); - } - map.sources = [source]; - map.sourcesContent = [code]; - - return ( - transformed.code + - '\n//# sourceMappingURL=data:application/json;base64,' + - buffer.Buffer(JSON.stringify(map)).toString('base64') - ); - } else { - // TODO: warn that we found a script tag missing the docblock? - // or warn and proceed anyway? - // or warn, add it ourselves, and proceed anyway? - return code; - } -} + if (i === 0) { + // Normally there will be a comma when we catch up, but not before + // the first property. + utils.append(',', state); + } -/** - * Appends a script element at the end of the <head> with the content of code, - * after transforming it. - * - * @param {string} code The original source code - * @param {string?} url Where the code came from. null if inline - * @param {object?} options Options to pass to jstransform - * @internal - */ -function run(code, url, options) { - var scriptEl = document.createElement('script'); - scriptEl.text = transformCode(code, url, options); - headEl.appendChild(scriptEl); -} + utils.catchup(property.range[0], state); -/** - * Load script from the provided url and pass the content to the callback. - * - * @param {string} url The location of the script src - * @param {function} callback Function to call with the content of url - * @internal - */ -function load(url, callback) { - var xhr; - xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') - : new XMLHttpRequest(); + // skip ... + utils.move(property.range[0] + 3, state); - // async, however scripts will be executed in the order they are in the - // DOM to mirror normal script loading. - xhr.open('GET', url, true); - if ('overrideMimeType' in xhr) { - xhr.overrideMimeType('text/plain'); - } - xhr.onreadystatechange = function() { - if (xhr.readyState === 4) { - if (xhr.status === 0 || xhr.status === 200) { - callback(xhr.responseText, url); - } else { - throw new Error("Could not load " + url); - } - } - }; - return xhr.send(null); -} + traverse(property.argument, path, state); -/** - * Loop over provided script tags and get the content, via innerHTML if an - * inline script, or by using XHR. Transforms are applied if needed. The scripts - * are executed in the order they are found on the page. - * - * @param {array} scripts The <script> elements to load and run. - * @internal - */ -function loadScripts(scripts) { - var result = scripts.map(function() { - return false; - }); - var count = result.length; + utils.catchup(property.range[1], state); - function check() { - var script, i; + previousWasSpread = true; - for (i = 0; i < count; i++) { - script = result[i]; + } else { - if (script && !script.executed) { - run(script.content, script.url, script.options); - script.executed = true; - } else if (!script) { - break; + utils.catchup(property.range[0], state); + + if (previousWasSpread) { + utils.append('{', state); } - } - } - scripts.forEach(function(script, i) { - var options; - if (script.type.indexOf('harmony=true') !== -1) { - options = { - harmony: true - }; - } + traverse(property, path, state); - if (script.src) { - load(script.src, function(content, url) { - result[i] = { - executed: false, - content: content, - url: url, - options: options - }; - check(); - }); - } else { - result[i] = { - executed: false, - content: script.innerHTML, - url: null, - options: options - }; - check(); - } - }); -} + utils.catchup(property.range[1], state); -/** - * Find and run all script tags with type="text/jsx". - * - * @internal - */ -function runScripts() { - var scripts = document.getElementsByTagName('script'); + previousWasSpread = false; - // Array.prototype.slice cannot be used on NodeList on IE8 - var jsxScripts = []; - for (var i = 0; i < scripts.length; i++) { - if (scripts.item(i).type.indexOf('text/jsx') !== -1) { - jsxScripts.push(scripts.item(i)); } } - console.warn( - 'You are using the in-browser JSX transformer. Be sure to precompile ' + - 'your JSX for production - ' + - 'http://facebook.github.io/react/docs/tooling-integration.html#jsx' - ); - - loadScripts(jsxScripts); -} + // Strip any non-whitespace between the last item and the end. + // We only catch up on whitespace so that we ignore any trailing commas which + // are stripped out for IE8 support. Unfortunately, this also strips out any + // trailing comments. + utils.catchupWhiteSpace(node.range[1] - 1, state); -// Listen for load event if we're in a browser and then kick off finding and -// running of scripts. -if (typeof window !== "undefined" && window !== null) { - headEl = document.getElementsByTagName('head')[0]; - dummyAnchor = document.createElement('a'); + // Skip the trailing } + utils.move(node.range[1], state); - if (window.addEventListener) { - window.addEventListener('DOMContentLoaded', runScripts, false); - } else { - window.attachEvent('onload', runScripts); + if (!previousWasSpread) { + utils.append('}', state); } + + utils.append(')', state); + return false; } -module.exports = { - transform: transformReact, - exec: exec +visitObjectLiteralSpread.test = function(node, path, state) { + if (node.type !== Syntax.ObjectExpression) { + return false; + } + // Tight loop optimization + var hasAtLeastOneSpreadProperty = false; + for (var i = 0; i < node.properties.length; i++) { + var property = node.properties[i]; + if (property.type === Syntax.SpreadProperty) { + hasAtLeastOneSpreadProperty = true; + } else if (property.kind !== 'init') { + return false; + } + } + return hasAtLeastOneSpreadProperty; }; -},{"./fbtransform/visitors":32,"buffer":1,"jstransform":19,"jstransform/src/docblock":18}],29:[function(_dereq_,module,exports){ +exports.visitorList = [ + visitObjectLiteralSpread +]; + +},{"../src/utils":22,"esprima-fb":9}],32:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2014 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12743,10 +14304,203 @@ module.exports = { * See the License for the specific language governing permissions and * limitations under the License. */ + +var KEYWORDS = [ + 'break', 'do', 'in', 'typeof', 'case', 'else', 'instanceof', 'var', 'catch', + 'export', 'new', 'void', 'class', 'extends', 'return', 'while', 'const', + 'finally', 'super', 'with', 'continue', 'for', 'switch', 'yield', 'debugger', + 'function', 'this', 'default', 'if', 'throw', 'delete', 'import', 'try' +]; + +var FUTURE_RESERVED_WORDS = [ + 'enum', 'await', 'implements', 'package', 'protected', 'static', 'interface', + 'private', 'public' +]; + +var LITERALS = [ + 'null', + 'true', + 'false' +]; + +// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-reserved-words +var RESERVED_WORDS = [].concat( + KEYWORDS, + FUTURE_RESERVED_WORDS, + LITERALS +); + +var reservedWordsMap = Object.create(null); +RESERVED_WORDS.forEach(function(k) { + reservedWordsMap[k] = true; +}); + +exports.isReservedWord = function(word) { + return !!reservedWordsMap[word]; +}; + +},{}],33:[function(_dereq_,module,exports){ +var esprima = _dereq_('esprima-fb'); +var utils = _dereq_('../src/utils'); + +var Syntax = esprima.Syntax; + +function _isFunctionNode(node) { + return node.type === Syntax.FunctionDeclaration + || node.type === Syntax.FunctionExpression + || node.type === Syntax.ArrowFunctionExpression; +} + +function visitClassProperty(traverse, node, path, state) { + utils.catchup(node.range[0], state); + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitClassProperty.test = function(node, path, state) { + return node.type === Syntax.ClassProperty; +}; + +function visitTypeAlias(traverse, node, path, state) { + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitTypeAlias.test = function(node, path, state) { + return node.type === Syntax.TypeAlias; +}; + +function visitInterfaceDeclaration(traverse, node, path, state) { + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitInterfaceDeclaration.test = function(node, path, state) { + return node.type === Syntax.InterfaceDeclaration; +}; + +function visitDeclare(traverse, node, path, state) { + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitDeclare.test = function(node, path, state) { + switch (node.type) { + case Syntax.DeclareVariable: + case Syntax.DeclareFunction: + case Syntax.DeclareClass: + case Syntax.DeclareModule: return true + } + return false; +} + +function visitFunctionParametricAnnotation(traverse, node, path, state) { + utils.catchup(node.range[0], state); + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitFunctionParametricAnnotation.test = function(node, path, state) { + return node.type === Syntax.TypeParameterDeclaration + && path[0] + && _isFunctionNode(path[0]) + && node === path[0].typeParameters; +}; + +function visitFunctionReturnAnnotation(traverse, node, path, state) { + utils.catchup(node.range[0], state); + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitFunctionReturnAnnotation.test = function(node, path, state) { + return path[0] && _isFunctionNode(path[0]) && node === path[0].returnType; +}; + +function visitOptionalFunctionParameterAnnotation(traverse, node, path, state) { + utils.catchup(node.range[0] + node.name.length, state); + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitOptionalFunctionParameterAnnotation.test = function(node, path, state) { + return node.type === Syntax.Identifier + && node.optional + && path[0] + && _isFunctionNode(path[0]); +}; + +function visitTypeAnnotatedIdentifier(traverse, node, path, state) { + utils.catchup(node.typeAnnotation.range[0], state); + utils.catchupWhiteOut(node.typeAnnotation.range[1], state); + return false; +} +visitTypeAnnotatedIdentifier.test = function(node, path, state) { + return node.type === Syntax.Identifier && node.typeAnnotation; +}; + +function visitTypeAnnotatedObjectOrArrayPattern(traverse, node, path, state) { + utils.catchup(node.typeAnnotation.range[0], state); + utils.catchupWhiteOut(node.typeAnnotation.range[1], state); + return false; +} +visitTypeAnnotatedObjectOrArrayPattern.test = function(node, path, state) { + var rightType = node.type === Syntax.ObjectPattern + || node.type === Syntax.ArrayPattern; + return rightType && node.typeAnnotation; +}; + +/** + * Methods cause trouble, since esprima parses them as a key/value pair, where + * the location of the value starts at the method body. For example + * { bar(x:number,...y:Array<number>):number {} } + * is parsed as + * { bar: function(x: number, ...y:Array<number>): number {} } + * except that the location of the FunctionExpression value is 40-something, + * which is the location of the function body. This means that by the time we + * visit the params, rest param, and return type organically, we've already + * catchup()'d passed them. + */ +function visitMethod(traverse, node, path, state) { + path.unshift(node); + traverse(node.key, path, state); + + path.unshift(node.value); + traverse(node.value.params, path, state); + node.value.rest && traverse(node.value.rest, path, state); + node.value.returnType && traverse(node.value.returnType, path, state); + traverse(node.value.body, path, state); + + path.shift(); + + path.shift(); + return false; +} + +visitMethod.test = function(node, path, state) { + return (node.type === "Property" && (node.method || node.kind === "set" || node.kind === "get")) + || (node.type === "MethodDefinition"); +}; + +exports.visitorList = [ + visitClassProperty, + visitDeclare, + visitInterfaceDeclaration, + visitFunctionParametricAnnotation, + visitFunctionReturnAnnotation, + visitMethod, + visitOptionalFunctionParameterAnnotation, + visitTypeAlias, + visitTypeAnnotatedIdentifier, + visitTypeAnnotatedObjectOrArrayPattern +]; + +},{"../src/utils":22,"esprima-fb":9}],34:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ /*global exports:true*/ "use strict"; -var Syntax = _dereq_('esprima-fb').Syntax; +var Syntax = _dereq_('jstransform').Syntax; var utils = _dereq_('jstransform/src/utils'); var FALLBACK_TAGS = _dereq_('./xjs').knownTags; @@ -12758,27 +14512,16 @@ var quoteAttrName = _dereq_('./xjs').quoteAttrName; var trimLeft = _dereq_('./xjs').trimLeft; /** - * Customized desugar processor. - * - * Currently: (Somewhat tailored to React) - * <X> </X> => X(null, null) - * <X prop="1" /> => X({prop: '1'}, null) - * <X prop="2"><Y /></X> => X({prop:'2'}, Y(null, null)) - * <X prop="2"><Y /><Z /></X> => X({prop:'2'}, [Y(null, null), Z(null, null)]) + * Customized desugar processor for React JSX. Currently: * - * Exceptions to the simple rules above: - * if a property is named "class" it will be changed to "className" in the - * javascript since "class" is not a valid object key in javascript. + * <X> </X> => React.createElement(X, null) + * <X prop="1" /> => React.createElement(X, {prop: '1'}, null) + * <X prop="2"><Y /></X> => React.createElement(X, {prop:'2'}, + * React.createElement(Y, null) + * ) + * <div /> => React.createElement("div", null) */ -var JSX_ATTRIBUTE_TRANSFORMS = { - cxName: function(attr) { - throw new Error( - "cxName is no longer supported, use className={cx(...)} instead" - ); - } -}; - /** * Removes all non-whitespace/parenthesis characters */ @@ -12787,8 +14530,12 @@ function stripNonWhiteParen(value) { return value.replace(reNonWhiteParen, ''); } +var tagConvention = /^[a-z]|\-/; +function isTagName(name) { + return tagConvention.test(name); +} + function visitReactTag(traverse, object, path, state) { - var jsxObjIdent = utils.getDocblock(state).jsx; var openingElement = object.openingElement; var nameObject = openingElement.name; var attributesObject = openingElement.attributes; @@ -12799,44 +14546,31 @@ function visitReactTag(traverse, object, path, state) { throw new Error('Namespace tags are not supported. ReactJSX is not XML.'); } - // Only identifiers can be fallback tags or need quoting. We don't need to - // handle quoting for other types. - var didAddTag = false; - - // Only identifiers can be fallback tags. XJSMemberExpressions are not. - if (nameObject.type === Syntax.XJSIdentifier) { - var tagName = nameObject.name; - var quotedTagName = quoteAttrName(tagName); - - if (FALLBACK_TAGS.hasOwnProperty(tagName)) { - // "Properly" handle invalid identifiers, like <font-face>, which needs to - // be enclosed in quotes. - var predicate = - tagName === quotedTagName ? - ('.' + tagName) : - ('[' + quotedTagName + ']'); - utils.append(jsxObjIdent + predicate, state); - utils.move(nameObject.range[1], state); - didAddTag = true; - } else if (tagName !== quotedTagName) { - // If we're in the case where we need to quote and but don't recognize the - // tag, throw. + // We assume that the React runtime is already in scope + utils.append('React.createElement(', state); + + // Identifiers with lower case or hypthens are fallback tags (strings). + // XJSMemberExpressions are not. + if (nameObject.type === Syntax.XJSIdentifier && isTagName(nameObject.name)) { + // This is a temporary error message to assist upgrades + if (!FALLBACK_TAGS.hasOwnProperty(nameObject.name)) { throw new Error( - 'Tags must be valid JS identifiers or a recognized special case. `<' + - tagName + '>` is not one of them.' + 'Lower case component names (' + nameObject.name + ') are no longer ' + + 'supported in JSX: See http://fb.me/react-jsx-lower-case' ); } - } - // Use utils.catchup in this case so we can easily handle XJSMemberExpressions - // which look like Foo.Bar.Baz. This also handles unhyphenated XJSIdentifiers - // that aren't fallback tags. - if (!didAddTag) { + utils.append('"' + nameObject.name + '"', state); + utils.move(nameObject.range[1], state); + } else { + // Use utils.catchup in this case so we can easily handle + // XJSMemberExpressions which look like Foo.Bar.Baz. This also handles + // XJSIdentifiers that aren't fallback tags. utils.move(nameObject.range[0], state); utils.catchup(nameObject.range[1], state); } - utils.append('(', state); + utils.append(', ', state); var hasAttributes = attributesObject.length; @@ -12846,7 +14580,7 @@ function visitReactTag(traverse, object, path, state) { // if we don't have any attributes, pass in null if (hasAtLeastOneSpreadProperty) { - utils.append('Object.assign({', state); + utils.append('React.__spread({', state); } else if (hasAttributes) { utils.append('{', state); } else { @@ -12861,9 +14595,6 @@ function visitReactTag(traverse, object, path, state) { var isLast = index === attributesObject.length - 1; if (attr.type === Syntax.XJSSpreadAttribute) { - // Plus 1 to skip `{`. - utils.move(attr.range[0] + 1, state); - // Close the previous object or initial object if (!previousWasSpread) { utils.append('}, ', state); @@ -12871,6 +14602,9 @@ function visitReactTag(traverse, object, path, state) { // Move to the expression start, ignoring everything except parenthesis // and whitespace. + utils.catchup(attr.range[0], state, stripNonWhiteParen); + // Plus 1 to skip `{`. + utils.move(attr.range[0] + 1, state); utils.catchup(attr.argument.range[0], state, stripNonWhiteParen); traverse(attr.argument, path, state); @@ -12921,13 +14655,7 @@ function visitReactTag(traverse, object, path, state) { utils.move(attr.name.range[1], state); // Use catchupNewlines to skip over the '=' in the attribute utils.catchupNewlines(attr.value.range[0], state); - if (JSX_ATTRIBUTE_TRANSFORMS.hasOwnProperty(attr.name.name)) { - utils.append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state); - utils.move(attr.value.range[1], state); - if (!isLast) { - utils.append(', ', state); - } - } else if (attr.value.type === Syntax.Literal) { + if (attr.value.type === Syntax.Literal) { renderXJSLiteral(attr.value, isLast, state); } else { renderXJSExpressionContainer(traverse, attr.value, isLast, path, state); @@ -13008,35 +14736,26 @@ function visitReactTag(traverse, object, path, state) { } visitReactTag.test = function(object, path, state) { - // only run react when react @jsx namespace is specified in docblock - var jsx = utils.getDocblock(state).jsx; - return object.type === Syntax.XJSElement && jsx && jsx.length; + return object.type === Syntax.XJSElement; }; exports.visitorList = [ visitReactTag ]; -},{"./xjs":31,"esprima-fb":6,"jstransform/src/utils":20}],30:[function(_dereq_,module,exports){ +},{"./xjs":36,"jstransform":21,"jstransform/src/utils":22}],35:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. */ /*global exports:true*/ "use strict"; -var Syntax = _dereq_('esprima-fb').Syntax; +var Syntax = _dereq_('jstransform').Syntax; var utils = _dereq_('jstransform/src/utils'); function addDisplayName(displayName, object, state) { @@ -13107,44 +14826,30 @@ function visitReactDisplayName(traverse, object, path, state) { } } -/** - * Will only run on @jsx files for now. - */ visitReactDisplayName.test = function(object, path, state) { - if (utils.getDocblock(state).jsx) { - return ( - object.type === Syntax.AssignmentExpression || - object.type === Syntax.Property || - object.type === Syntax.VariableDeclarator - ); - } else { - return false; - } + return ( + object.type === Syntax.AssignmentExpression || + object.type === Syntax.Property || + object.type === Syntax.VariableDeclarator + ); }; exports.visitorList = [ visitReactDisplayName ]; -},{"esprima-fb":6,"jstransform/src/utils":20}],31:[function(_dereq_,module,exports){ +},{"jstransform":21,"jstransform/src/utils":22}],36:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. */ /*global exports:true*/ "use strict"; -var Syntax = _dereq_('esprima-fb').Syntax; +var Syntax = _dereq_('jstransform').Syntax; var utils = _dereq_('jstransform/src/utils'); var knownTags = { @@ -13237,6 +14942,7 @@ var knownTags = { param: true, path: true, pattern: false, + picture: true, polygon: true, polyline: true, pre: true, @@ -13381,7 +15087,7 @@ exports.renderXJSLiteral = renderXJSLiteral; exports.quoteAttrName = quoteAttrName; exports.trimLeft = trimLeft; -},{"esprima-fb":6,"jstransform/src/utils":20}],32:[function(_dereq_,module,exports){ +},{"jstransform":21,"jstransform/src/utils":22}],37:[function(_dereq_,module,exports){ /*global exports:true*/ var es6ArrowFunctions = _dereq_('jstransform/visitors/es6-arrow-function-visitors'); var es6Classes = _dereq_('jstransform/visitors/es6-class-visitors'); @@ -13390,6 +15096,7 @@ var es6ObjectConciseMethod = _dereq_('jstransform/visitors/es6-object-concise-me var es6ObjectShortNotation = _dereq_('jstransform/visitors/es6-object-short-notation-visitors'); var es6RestParameters = _dereq_('jstransform/visitors/es6-rest-param-visitors'); var es6Templates = _dereq_('jstransform/visitors/es6-template-visitors'); +var es7SpreadProperty = _dereq_('jstransform/visitors/es7-spread-property-visitors'); var react = _dereq_('./transforms/react'); var reactDisplayName = _dereq_('./transforms/reactDisplayName'); @@ -13404,9 +15111,26 @@ var transformVisitors = { 'es6-object-short-notation': es6ObjectShortNotation.visitorList, 'es6-rest-params': es6RestParameters.visitorList, 'es6-templates': es6Templates.visitorList, + 'es7-spread-property': es7SpreadProperty.visitorList, 'react': react.visitorList.concat(reactDisplayName.visitorList) }; +var transformSets = { + 'harmony': [ + 'es6-arrow-functions', + 'es6-object-concise-method', + 'es6-object-short-notation', + 'es6-classes', + 'es6-rest-params', + 'es6-templates', + 'es6-destructuring', + 'es7-spread-property' + ], + 'react': [ + 'react' + ] +}; + /** * Specifies the order in which each transform should run. */ @@ -13418,6 +15142,7 @@ var transformRunOrder = [ 'es6-rest-params', 'es6-templates', 'es6-destructuring', + 'es7-spread-property', 'react' ]; @@ -13438,9 +15163,37 @@ function getAllVisitors(excludes) { return ret; } +/** + * Given a list of visitor set names, return the ordered list of visitors to be + * passed to jstransform. + * + * @param {array} + * @return {array} + */ +function getVisitorsBySet(sets) { + var visitorsToInclude = sets.reduce(function(visitors, set) { + if (!transformSets.hasOwnProperty(set)) { + throw new Error('Unknown visitor set: ' + set); + } + transformSets[set].forEach(function(visitor) { + visitors[visitor] = true; + }); + return visitors; + }, {}); + + var visitorList = []; + for (var i = 0; i < transformRunOrder.length; i++) { + if (visitorsToInclude.hasOwnProperty(transformRunOrder[i])) { + visitorList = visitorList.concat(transformVisitors[transformRunOrder[i]]); + } + } + + return visitorList; +} + +exports.getVisitorsBySet = getVisitorsBySet; exports.getAllVisitors = getAllVisitors; exports.transformVisitors = transformVisitors; -},{"./transforms/react":29,"./transforms/reactDisplayName":30,"jstransform/visitors/es6-arrow-function-visitors":21,"jstransform/visitors/es6-class-visitors":22,"jstransform/visitors/es6-destructuring-visitors":23,"jstransform/visitors/es6-object-concise-method-visitors":24,"jstransform/visitors/es6-object-short-notation-visitors":25,"jstransform/visitors/es6-rest-param-visitors":26,"jstransform/visitors/es6-template-visitors":27}]},{},[28]) -(28) +},{"./transforms/react":34,"./transforms/reactDisplayName":35,"jstransform/visitors/es6-arrow-function-visitors":23,"jstransform/visitors/es6-class-visitors":24,"jstransform/visitors/es6-destructuring-visitors":25,"jstransform/visitors/es6-object-concise-method-visitors":26,"jstransform/visitors/es6-object-short-notation-visitors":27,"jstransform/visitors/es6-rest-param-visitors":28,"jstransform/visitors/es6-template-visitors":29,"jstransform/visitors/es7-spread-property-visitors":31}]},{},[1])(1) });
\ No newline at end of file |