build/JSXTransformer.js in react-source-0.3.3 vs build/JSXTransformer.js in react-source-0.4.0

- old
+ new

@@ -1,721 +1,270 @@ /** - * JSXTransformer v0.3.3 + * JSXTransformer v0.4.0 */ (function(e){if("function"==typeof bootstrap)bootstrap("jsxtransformer",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeJSXTransformer=e}else"undefined"!=typeof window?window.JSXTransformer=e():global.JSXTransformer=e()})(function(){var define,ses,bootstrap,module,exports; return (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){ -/** - * 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. - * 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. - */ -/* jshint browser: true */ -/* jslint evil: true */ +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"] -'use strict'; -var runScripts; - -var transform = require('./fbtransform/lib/transform').transform; -var visitors = require('./fbtransform/visitors').transformVisitors; -var transform = transform.bind(null, visitors.react); -var docblock = require('./fbtransform/lib/docblock'); - -var headEl = document.getElementsByTagName('head')[0]; - -exports.transform = transform; - -exports.exec = function(code) { - return eval(transform(code)); -}; - -var run = exports.run = function(code) { - var jsx = docblock.parseAsObject(docblock.extract(code)).jsx; - - var functionBody = jsx ? transform(code).code : code; - var scriptEl = document.createElement('script'); - - scriptEl.innerHTML = functionBody; - headEl.appendChild(scriptEl); -}; - -if (typeof window === "undefined" || window === null) { - return; -} - -var load = exports.load = function(url, callback) { - var xhr; - xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') - : new XMLHttpRequest(); - // Disable async since we need to execute scripts in the order they are in the - // DOM to mirror normal script loading. - xhr.open('GET', url, false); - if ('overrideMimeType' in xhr) { - xhr.overrideMimeType('text/plain'); - } - xhr.onreadystatechange = function() { - if (xhr.readyState === 4) { - if (xhr.status === 0 || xhr.status === 200) { - run(xhr.responseText); - } else { - throw new Error("Could not load " + url); - } - if (callback) { - return callback(); - } + 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 }; - return xhr.send(null); -}; + 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 + }; -runScripts = function() { - var scripts = document.getElementsByTagName('script'); - scripts = Array.prototype.slice.call(scripts); - var jsxScripts = scripts.filter(function(script) { - return script.type === 'text/jsx'; - }); + return my; +}({})); - jsxScripts.forEach(function(script) { - if (script.src) { - load(script.src); - } else { - run(script.innerHTML); +module.exports = Base62 +},{}],2:[function(require,module,exports){ +(function(process){function filter (xs, fn) { + var res = []; + for (var i = 0; i < xs.length; i++) { + if (fn(xs[i], i, xs)) res.push(xs[i]); } - }); -}; - -if (window.addEventListener) { - window.addEventListener('DOMContentLoaded', runScripts, false); -} else { - window.attachEvent('onload', runScripts); + return res; } -},{"./fbtransform/lib/transform":2,"./fbtransform/visitors":3,"./fbtransform/lib/docblock":4}],4:[function(require,module,exports){ -/** - * 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. - * 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. - */ +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length; i >= 0; i--) { + var last = parts[i]; + if (last == '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } -var docblockRe = /^\s*(\/\*\*(.|\n)*?\*\/)/; -var ltrimRe = /^\s*/; -/** - * @param {String} contents - * @return {String} - */ -function extract(contents) { - var match = contents.match(docblockRe); - if (match) { - return match[0].replace(ltrimRe, '') || ''; + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } } - return ''; + + return parts; } +// Regex to split a filename into [*, dir, basename, ext] +// posix version +var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/; -var commentStartRe = /^\/\*\*?/; -var commentEndRe = /\*\/$/; -var wsRe = /[\t ]+/g; -var stringStartRe = /(\n|^) *\*/g; -var multilineRe = /(?:^|\n) *(@[^\n]*?) *\n *([^@\n\s][^@\n]+?) *\n/g; -var propertyRe = /(?:^|\n) *@(\S+) *([^\n]*)/g; +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { +var resolvedPath = '', + resolvedAbsolute = false; -/** - * @param {String} contents - * @return {Array} - */ -function parse(docblock) { - docblock = docblock - .replace(commentStartRe, '') - .replace(commentEndRe, '') - .replace(wsRe, ' ') - .replace(stringStartRe, '$1'); +for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) + ? arguments[i] + : process.cwd(); - // Normalize multi-line directives - var prev = ''; - while (prev != docblock) { - prev = docblock; - docblock = docblock.replace(multilineRe, "\n$1 $2\n"); + // Skip empty and invalid entries + if (typeof path !== 'string' || !path) { + continue; } - docblock = docblock.trim(); - var result = []; - var match; - while (match = propertyRe.exec(docblock)) { - result.push([match[1], match[2]]); - } - - return result; + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; } -/** - * Same as parse but returns an object of prop: value instead of array of paris - * If a property appers more than once the last one will be returned - * - * @param {String} contents - * @return {Object} - */ -function parseAsObject(docblock) { - var pairs = parse(docblock); - var result = {}; - for (var i = 0; i < pairs.length; i++) { - result[pairs[i][0]] = pairs[i][1]; - } - return result; -} +// At this point the path should be resolved to a full absolute path, but +// handle relative paths to be safe (might happen when process.cwd() fails) +// Normalize the path +resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); -exports.extract = extract; -exports.parse = parse; -exports.parseAsObject = parseAsObject; - -},{}],3:[function(require,module,exports){ -(function(){/*global exports:true*/ -var classes = require('./transforms/classes'); -var react = require('./transforms/react'); -var reactDisplayName = require('./transforms/reactDisplayName'); - -/** - * Map from transformName => orderedListOfVisitors. - */ -var transformVisitors = { - 'es6-classes': [ - classes.visitClassExpression, - classes.visitClassDeclaration, - classes.visitSuperCall, - classes.visitPrivateProperty - ] + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; }; -transformVisitors.react = transformVisitors[ - "es6-classes" -].concat([ - react.visitReactTag, - reactDisplayName.visitReactDisplayName -]); +// path.normalize(path) +// posix version +exports.normalize = function(path) { +var isAbsolute = path.charAt(0) === '/', + trailingSlash = path.slice(-1) === '/'; -/** - * Specifies the order in which each transform should run. - */ -var transformRunOrder = [ - 'es6-classes', - 'react' -]; +// Normalize the path +path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); -/** - * Given a list of transform names, return the ordered list of visitors to be - * passed to the transform() function. - * - * @param {array?} excludes - * @return {array} - */ -function getVisitorsList(excludes) { - var ret = []; - for (var i = 0, il = transformRunOrder.length; i < il; i++) { - if (!excludes || excludes.indexOf(transformRunOrder[i]) === -1) { - ret = ret.concat(transformVisitors[transformRunOrder[i]]); - } + if (!path && !isAbsolute) { + path = '.'; } - return ret; -} + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; -exports.getVisitorsList = getVisitorsList; -exports.transformVisitors = transformVisitors; -})() -},{"./transforms/classes":5,"./transforms/react":6,"./transforms/reactDisplayName":7}],8:[function(require,module,exports){ -(function(){/** - * 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. - * 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. - */ -/*global exports:true*/ +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + return p && typeof p === 'string'; + }).join('/')); +}; -/** - * State represents the given parser state. It has a local and global parts. - * Global contains parser position, source, etc. Local contains scope based - * properties, like current class name. State should contain all the info - * required for transformation. It's the only mandatory object that is being - * passed to every function in transform chain. - * - * @param {String} source - * @param {Object} transformOptions - * @return {Object} - */ -function createState(source, transformOptions) { - return { - /** - * Name of the super class variable - * @type {String} - */ - superVar: '', - /** - * Name of the enclosing class scope - * @type {String} - */ - scopeName: '', - /** - * Global state (not affected by updateState) - * @type {Object} - */ - g: { - /** - * A set of general options that transformations can consider while doing - * a transformation: - * - * - minify - * Specifies that transformation steps should do their best to minify - * the output source when possible. This is useful for places where - * minification optimizations are possible with higher-level context - * info than what jsxmin can provide. - * - * For example, the ES6 class transform will minify munged private - * variables if this flag is set. - */ - opts: transformOptions, - /** - * Current position in the source code - * @type {Number} - */ - position: 0, - /** - * Buffer containing the result - * @type {String} - */ - buffer: '', - /** - * Indentation offset (only negative offset is supported now) - * @type {Number} - */ - indentBy: 0, - /** - * Source that is being transformed - * @type {String} - */ - source: source, - /** - * Cached parsed docblock (see getDocblock) - * @type {object} - */ - docblock: null, +exports.dirname = function(path) { + var dir = splitPathRe.exec(path)[1] || ''; + var isWindows = false; + if (!dir) { + // No dirname + return '.'; + } else if (dir.length === 1 || + (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) { + // It is just a slash or a drive letter with a slash + return dir; + } else { + // It is a full dirname, strip trailing slash + return dir.substring(0, dir.length - 1); + } +}; - /** - * Whether the thing was used - * @type {Boolean} - */ - tagNamespaceUsed: false, - /** - * If using bolt xjs transformation - * @type {Boolean} - */ - isBolt: undefined, - - /** - * Whether to record source map (expensive) or not - * @type {SourceMapGenerator|null} - */ - sourceMap: null, - - /** - * Filename of the file being processed. Will be returned as a source - * attribute in the source map - */ - sourceMapFilename: 'source.js', - - /** - * Only when source map is used: last line in the source for which - * source map was generated - * @type {Number} - */ - sourceLine: 1, - - /** - * Only when source map is used: last line in the buffer for which - * source map was generated - * @type {Number} - */ - bufferLine: 1, - - /** - * The top-level Program AST for the original file. - */ - originalProgramAST: null, - - sourceColumn: 0, - bufferColumn: 0 - } - }; -} - -/** - * Updates a copy of a given state with "update" and returns an updated state. - * - * @param {Object} state - * @param {Object} update - * @return {Object} - */ -function updateState(state, update) { - return { - g: state.g, - superVar: update.superVar || state.superVar, - scopeName: update.scopeName || state.scopeName - }; -} - -/** - * Given a state fill the resulting buffer from the original source up to - * the end - * @param {Number} end - * @param {Object} state - * @param {Function?} contentTransformer Optional callback to transform newly - * added content. - */ -function catchup(end, state, contentTransformer) { - if (end < state.g.position) { - // cannot move backwards - return; +exports.basename = function(path, ext) { + var f = splitPathRe.exec(path)[2] || ''; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); } - var source = state.g.source.substring(state.g.position, end); - var transformed = updateIndent(source, state); - if (state.g.sourceMap && transformed) { - // record where we are - state.g.sourceMap.addMapping({ - generated: { line: state.g.bufferLine, column: state.g.bufferColumn }, - original: { line: state.g.sourceLine, column: state.g.sourceColumn }, - source: state.g.sourceMapFilename - }); + return f; +}; - // record line breaks in transformed source - var sourceLines = source.split('\n'); - var transformedLines = transformed.split('\n'); - // Add line break mappings between last known mapping and the end of the - // added piece. So for the code piece - // (foo, bar); - // > var x = 2; - // > var b = 3; - // var c = - // only add lines marked with ">": 2, 3. - for (var i = 1; i < sourceLines.length - 1; i++) { - state.g.sourceMap.addMapping({ - generated: { line: state.g.bufferLine, column: 0 }, - original: { line: state.g.sourceLine, column: 0 }, - source: state.g.sourceMapFilename - }); - state.g.sourceLine++; - state.g.bufferLine++; - } - // offset for the last piece - if (sourceLines.length > 1) { - state.g.sourceLine++; - state.g.bufferLine++; - state.g.sourceColumn = 0; - state.g.bufferColumn = 0; - } - state.g.sourceColumn += sourceLines[sourceLines.length - 1].length; - state.g.bufferColumn += - transformedLines[transformedLines.length - 1].length; - } - state.g.buffer += - contentTransformer ? contentTransformer(transformed) : transformed; - state.g.position = end; -} -/** - * Applies `catchup` but passing in a function that removes any non-whitespace - * characters. - */ -var re = /(\S)/g; -function stripNonWhite(value) { - return value.replace(re, function() { - return ''; - }); -} -/** - * Catches up as `catchup` but turns each non-white character into a space. - */ -function catchupWhiteSpace(end, state) { - catchup(end, state, stripNonWhite); -} +exports.extname = function(path) { + return splitPathRe.exec(path)[3] || ''; +}; -/** - * Same as catchup but does not touch the buffer - * @param {Number} end - * @param {Object} state - */ -function move(end, state) { - // move the internal cursors - if (state.g.sourceMap) { - if (end < state.g.position) { - state.g.position = 0; - state.g.sourceLine = 1; - state.g.sourceColumn = 0; - } +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); - var source = state.g.source.substring(state.g.position, end); - var sourceLines = source.split('\n'); - if (sourceLines.length > 1) { - state.g.sourceLine += sourceLines.length - 1; - state.g.sourceColumn = 0; + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; } - state.g.sourceColumn += sourceLines[sourceLines.length - 1].length; - } - state.g.position = end; -} -/** - * Appends a string of text to the buffer - * @param {String} string - * @param {Object} state - */ -function append(string, state) { - if (state.g.sourceMap && string) { - state.g.sourceMap.addMapping({ - generated: { line: state.g.bufferLine, column: state.g.bufferColumn }, - original: { line: state.g.sourceLine, column: state.g.sourceColumn }, - source: state.g.sourceMapFilename - }); - var transformedLines = string.split('\n'); - if (transformedLines.length > 1) { - state.g.bufferLine += transformedLines.length - 1; - state.g.bufferColumn = 0; + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; } - state.g.bufferColumn += - transformedLines[transformedLines.length - 1].length; - } - state.g.buffer += string; -} -/** - * Update indent using state.indentBy property. Indent is measured in - * double spaces. Updates a single line only. - * - * @param {String} str - * @param {Object} state - * @return {String} - */ -function updateIndent(str, state) { - for (var i = 0; i < -state.g.indentBy; i++) { - str = str.replace(/(^|\n)( {2}|\t)/g, '$1'); + if (start > end) return []; + return arr.slice(start, end - start + 1); } - return str; -} -/** - * Calculates indent from the beginning of the line until "start" or the first - * character before start. - * @example - * " foo.bar()" - * ^ - * start - * indent will be 2 - * - * @param {Number} start - * @param {Object} state - * @return {Number} - */ -function indentBefore(start, state) { - var end = start; - start = start - 1; + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); - while (start > 0 && state.g.source[start] != '\n') { - if (!state.g.source[start].match(/[ \t]/)) { - end = start; + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; } - start--; } - return state.g.source.substring(start + 1, end); -} -function getDocblock(state) { - if (!state.g.docblock) { - var docblock = require('./docblock'); - state.g.docblock = - docblock.parseAsObject(docblock.extract(state.g.source)); + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); } - return state.g.docblock; -} -exports.catchup = catchup; -exports.catchupWhiteSpace = catchupWhiteSpace; -exports.append = append; -exports.move = move; -exports.updateIndent = updateIndent; -exports.indentBefore = indentBefore; -exports.updateState = updateState; -exports.createState = createState; -exports.getDocblock = getDocblock; + outputParts = outputParts.concat(toParts.slice(samePartsLength)); -})() -},{"./docblock":4}],2:[function(require,module,exports){ -(function(){/** - * 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. - * 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. - */ -/*global exports:true*/ -/*jslint node: true*/ -"use strict"; + return outputParts.join('/'); +}; -/** - * Syntax transfomer for javascript. Takes the source in, spits the source - * out. Tries to maintain readability and preserve whitespace and line numbers - * where posssible. - * - * Support - * - ES6 class transformation + private property munging, see ./classes.js - * - React XHP style syntax transformations, see ./react.js - * - Bolt XHP style syntax transformations, see ./bolt.js - * - * The general flow is the following: - * - Parse the source with our customized esprima-parser - * https://github.com/voloko/esprima. We have to customize the parser to - * support non-standard XHP-style syntax. We parse the source range: true - * option that forces esprima to return positions in the source within - * resulting parse tree. - * - * - Traverse resulting syntax tree, trying to apply a set of visitors to each - * node. Each visitor should provide a .test() function that tests if the - * visitor can process a given node. - * - * - Visitor is responsible for code generation for a given syntax node. - * Generated code is stored in state.g.buffer that is passed to every - * visitor. It's up to the visitor to process the code the way it sees fit. - * All of the current visitors however use both the node and the original - * source to generate transformed code. They use nodes to generate new - * code and they copy the original source, preserving whitespace and comments, - * for the parts they don't care about. - */ -var esprima = require('esprima'); +})(require("__browserify_process")) +},{"__browserify_process":3}],3:[function(require,module,exports){ +// shim for using process in browser -var createState = require('./utils').createState; -var catchup = require('./utils').catchup; +var process = module.exports = {}; -/** - * @param {object} object - * @param {function} visitor - * @param {array} path - * @param {object} state - */ -function traverse(object, path, state) { - var key, child; +process.nextTick = (function () { + var canSetImmediate = typeof window !== 'undefined' + && window.setImmediate; + var canPost = typeof window !== 'undefined' + && window.postMessage && window.addEventListener + ; - if (walker(traverse, object, path, state) === false) { - return; - } - path.unshift(object); - for (key in object) { - // skip obviously wrong attributes - if (key === 'range' || key === 'loc') { - continue; + if (canSetImmediate) { + return function (f) { return window.setImmediate(f) }; } - if (object.hasOwnProperty(key)) { - child = object[key]; - if (typeof child === 'object' && child !== null) { - child.range && catchup(child.range[0], state); - traverse(child, path, state); - child.range && catchup(child.range[1], state); - } - } - } - path.shift(); -} -function walker(traverse, object, path, state) { - var visitors = state.g.visitors; - for (var i = 0; i < visitors.length; i++) { - if (visitors[i].test(object, path, state)) { - return visitors[i](traverse, object, path, state); + if (canPost) { + var queue = []; + window.addEventListener('message', function (ev) { + if (ev.source === window && ev.data === 'process-tick') { + ev.stopPropagation(); + if (queue.length > 0) { + var fn = queue.shift(); + fn(); + } + } + }, true); + + return function nextTick(fn) { + queue.push(fn); + window.postMessage('process-tick', '*'); + }; } - } -} -function runPass(source, visitors, options) { - var ast = esprima.parse(source, { comment: true, loc: true, range: true }); - var state = createState(source, options); - state.g.originalProgramAST = ast; - state.g.visitors = visitors; + return function nextTick(fn) { + setTimeout(fn, 0); + }; +})(); - if (options.sourceMap) { - var SourceMapGenerator = require('source-map').SourceMapGenerator; - state.g.sourceMap = new SourceMapGenerator({ file: 'transformed.js' }); - } - traverse(ast, [], state); - catchup(source.length, state); - return state; -} +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; -/** - * Applies all available transformations to the source - * @param {array} visitors - * @param {string} source - * @param {?object} options - * @return {object} - */ -function transform(visitors, source, options) { - options = options || {}; - - var state = runPass(source, visitors, options); - var sourceMap = state.g.sourceMap; - - if (sourceMap) { - return { - sourceMap: sourceMap, - sourceMapFilename: options.filename || 'source.js', - code: state.g.buffer - }; - } else { - return { - code: state.g.buffer - }; - } +process.binding = function (name) { + throw new Error('process.binding is not supported'); } +// TODO(shtylman) +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; -exports.transform = transform; - -})() -},{"./utils":8,"esprima":9,"source-map":10}],9:[function(require,module,exports){ +},{}],4:[function(require,module,exports){ (function(){/* Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com> Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com> Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be> Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl> @@ -757,11 +306,11 @@ parseLeftHandSideExpression: true, parseParams: true, validateParam: true, parseSpreadOrAssignmentExpression: true, parseStatement: true, parseSourceElement: true, parseModuleBlock: true, parseConciseBody: true, advanceXJSChild: true, isXJSIdentifierStart: true, isXJSIdentifierPart: true, scanXJSStringLiteral: true, scanXJSIdentifier: true, -parseXJSAttributeValue: true, parseXJSChild: true, parseXJSElement: true, parseXJSExpression: true, +parseXJSAttributeValue: true, parseXJSChild: true, parseXJSElement: true, parseXJSExpressionContainer: true, parseXJSEmptyExpression: true, parseYieldExpression: true */ (function (root, factory) { 'use strict'; @@ -901,11 +450,12 @@ VariableDeclaration: 'VariableDeclaration', VariableDeclarator: 'VariableDeclarator', WhileStatement: 'WhileStatement', WithStatement: 'WithStatement', XJSIdentifier: 'XJSIdentifier', - XJSExpression: 'XJSExpression', + XJSEmptyExpression: 'XJSEmptyExpression', + XJSExpressionContainer: 'XJSExpressionContainer', XJSElement: 'XJSElement', XJSClosingElement: 'XJSClosingElement', XJSOpeningElement: 'XJSOpeningElement', XJSAttribute: 'XJSAttribute', XJSText: 'XJSText', @@ -2454,17 +2004,23 @@ attributes: openingElement.attributes, children: children }; }, - createXJSExpression: function (expression) { + createXJSEmptyExpression: function () { return { - type: Syntax.XJSExpression, - value: expression + type: Syntax.XJSEmptyExpression }; }, + createXJSExpressionContainer: function (expression) { + return { + type: Syntax.XJSExpressionContainer, + expression: expression + }; + }, + createXJSOpeningElement: function (name, attributes, selfClosing) { return { type: Syntax.XJSOpeningElement, name: name, selfClosing: selfClosing, @@ -5958,38 +5514,56 @@ return delegate.createXJSIdentifier(token.value, token.namespace); } function parseXJSAttributeValue() { var value; - if (lookahead.value === '{') { - value = parseXJSExpression(); + if (match('{')) { + value = parseXJSExpressionContainer(); + if (value.expression.type === Syntax.XJSEmptyExpression) { + throwError( + value, + 'XJS attributes must only be assigned a non-empty ' + + 'expression' + ); + } } else if (lookahead.type === Token.XJSText) { value = delegate.createLiteral(lex()); } else { throwError({}, Messages.InvalidXJSAttributeValue); } return value; } - function parseXJSExpression() { - var value, origInXJSChild, origInXJSTag; + function parseXJSEmptyExpression() { + while (source.charAt(index) !== '}') { + index++; + } + return delegate.createXJSEmptyExpression(); + } + function parseXJSExpressionContainer() { + var expression, origInXJSChild, origInXJSTag; + origInXJSChild = state.inXJSChild; origInXJSTag = state.inXJSTag; state.inXJSChild = false; state.inXJSTag = false; expect('{'); - value = parseExpression(); + if (match('}')) { + expression = parseXJSEmptyExpression(); + } else { + expression = parseExpression(); + } state.inXJSChild = origInXJSChild; state.inXJSTag = origInXJSTag; expect('}'); - return delegate.createXJSExpression(value); + return delegate.createXJSExpressionContainer(expression); } function parseXJSAttribute() { var token, name, value; @@ -6004,12 +5578,12 @@ return delegate.createXJSAttribute(name); } function parseXJSChild() { var token; - if (lookahead.value === '{') { - token = parseXJSExpression(); + if (match('{')) { + token = parseXJSExpressionContainer(); } else if (lookahead.type === Token.XJSText) { token = delegate.createLiteral(lex()); } else { state.inXJSChild = false; token = parseXJSElement(); @@ -6491,11 +6065,12 @@ extra.parseClassBody = parseClassBody; extra.parseXJSIdentifier = parseXJSIdentifier; extra.parseXJSChild = parseXJSChild; extra.parseXJSAttribute = parseXJSAttribute; extra.parseXJSAttributeValue = parseXJSAttributeValue; - extra.parseXJSExpression = parseXJSExpression; + extra.parseXJSExpressionContainer = parseXJSExpressionContainer; + extra.parseXJSEmptyExpression = parseXJSEmptyExpression; extra.parseXJSElement = parseXJSElement; extra.parseXJSClosingElement = parseXJSClosingElement; extra.parseXJSOpeningElement = parseXJSOpeningElement; parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression); @@ -6543,11 +6118,12 @@ parseClassBody = wrapTracking(extra.parseClassBody); parseXJSIdentifier = wrapTracking(extra.parseXJSIdentifier); parseXJSChild = wrapTrackingPreserveWhitespace(extra.parseXJSChild); parseXJSAttribute = wrapTracking(extra.parseXJSAttribute); parseXJSAttributeValue = wrapTracking(extra.parseXJSAttributeValue); - parseXJSExpression = wrapTracking(extra.parseXJSExpression); + parseXJSExpressionContainer = wrapTracking(extra.parseXJSExpressionContainer); + parseXJSEmptyExpression = wrapTrackingPreserveWhitespace(extra.parseXJSEmptyExpression); parseXJSElement = wrapTracking(extra.parseXJSElement); parseXJSClosingElement = wrapTracking(extra.parseXJSClosingElement); parseXJSOpeningElement = wrapTracking(extra.parseXJSOpeningElement); } @@ -6612,11 +6188,12 @@ parseClassBody = extra.parseClassBody; parseXJSIdentifier = extra.parseXJSIdentifier; parseXJSChild = extra.parseXJSChild; parseXJSAttribute = extra.parseXJSAttribute; parseXJSAttributeValue = extra.parseXJSAttributeValue; - parseXJSExpression = extra.parseXJSExpression; + parseXJSExpressionContainer = extra.parseXJSExpressionContainer; + parseXJSEmptyExpression = extra.parseXJSEmptyExpression; parseXJSElement = extra.parseXJSElement; parseXJSClosingElement = extra.parseXJSClosingElement; parseXJSOpeningElement = extra.parseXJSOpeningElement; } @@ -6867,1489 +6444,400 @@ })); /* vim: set sw=4 ts=4 et tw=80 : */ })() -},{}],11:[function(require,module,exports){ -(function(){/** - * 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. - * 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. - */ -/*global exports:true*/ -"use strict"; -var catchup = require('../lib/utils').catchup; -var append = require('../lib/utils').append; -var move = require('../lib/utils').move; - -var knownTags = { - a: true, - abbr: true, - address: true, - applet: true, - area: true, - article: true, - aside: true, - audio: true, - b: true, - base: true, - bdi: true, - bdo: true, - blockquote: true, - body: true, - br: true, - button: true, - canvas: true, - circle: true, - ellipse: true, - caption: true, - cite: true, - code: true, - col: true, - colgroup: true, - command: true, - data: true, - datalist: true, - dd: true, - del: true, - details: true, - dfn: true, - dialog: true, - div: true, - dl: true, - dt: true, - em: true, - embed: true, - fieldset: true, - figcaption: true, - figure: true, - footer: true, - form: true, - g: true, - h1: true, - h2: true, - h3: true, - h4: true, - h5: true, - h6: true, - head: true, - header: true, - hgroup: true, - hr: true, - html: true, - i: true, - iframe: true, - img: true, - input: true, - ins: true, - kbd: true, - keygen: true, - label: true, - legend: true, - li: true, - line: true, - link: true, - map: true, - mark: true, - marquee: true, - menu: true, - meta: true, - meter: true, - nav: true, - noscript: true, - object: true, - ol: true, - optgroup: true, - option: true, - output: true, - p: true, - path: true, - param: true, - pre: true, - progress: true, - q: true, - rect: true, - rp: true, - rt: true, - ruby: true, - s: true, - samp: true, - script: true, - section: true, - select: true, - small: true, - source: true, - span: true, - strong: true, - style: true, - sub: true, - summary: true, - sup: true, - svg: true, - table: true, - tbody: true, - td: true, - text: true, - textarea: true, - tfoot: true, - th: true, - thead: true, - time: true, - title: true, - tr: true, - track: true, - u: true, - ul: true, - 'var': true, - video: true, - wbr: true -}; - -function safeTrim(string) { - return string.replace(/^[ \t]+/, '').replace(/[ \t]+$/, ''); -} - -// Replace all trailing whitespace characters with a single space character -function trimWithSingleSpace(string) { - return string.replace(/^[ \t\xA0]{2,}/, ' '). - replace(/[ \t\xA0]{2,}$/, ' ').replace(/^\s+$/, ''); -} - -/** - * Special handling for multiline string literals - * print lines: - * - * line - * line - * - * as: - * - * "line "+ - * "line" - */ -function renderXJSLiteral(object, isLast, state, start, end) { - /** Added blank check filtering and triming*/ - var trimmedChildValue = safeTrim(object.value); - - if (trimmedChildValue) { - // head whitespace - append(object.value.match(/^[\t ]*/)[0], state); - if (start) { - append(start, state); - } - - var trimmedChildValueWithSpace = trimWithSingleSpace(object.value); - - /** - */ - var initialLines = trimmedChildValue.split(/\r\n|\n|\r/); - - var lines = initialLines.filter(function(line) { - return safeTrim(line).length > 0; - }); - - var hasInitialNewLine = initialLines[0] !== lines[0]; - var hasFinalNewLine = - initialLines[initialLines.length - 1] !== lines[lines.length - 1]; - - var numLines = lines.length; - lines.forEach(function (line, ii) { - var lastLine = ii === numLines - 1; - var trimmedLine = safeTrim(line); - if (trimmedLine === '' && !lastLine) { - append(line, state); - } else { - var preString = ''; - var postString = ''; - var leading = ''; - - if (ii === 0) { - if (hasInitialNewLine) { - preString = ' '; - leading = '\n'; - } - if (trimmedChildValueWithSpace.substring(0, 1) === ' ') { - // If this is the first line, and the original content starts with - // whitespace, place a single space at the beginning. - preString = ' '; - } - } else { - leading = line.match(/^[ \t]*/)[0]; - } - if (!lastLine || trimmedChildValueWithSpace.substr( - trimmedChildValueWithSpace.length - 1, 1) === ' ' || - hasFinalNewLine - ) { - // If either not on the last line, or the original content ends with - // whitespace, place a single character at the end. - postString = ' '; - } - - append( - leading + - JSON.stringify( - preString + trimmedLine + postString - ) + - (lastLine ? '' : '+') + - line.match(/[ \t]*$/)[0], - state); - } - if (!lastLine) { - append('\n', state); - } - }); - } else { - if (start) { - append(start, state); - } - append('""', state); - } - if (end) { - append(end, state); - } - - // add comma before trailing whitespace - if (!isLast) { - append(',', state); - } - - // tail whitespace - append(object.value.match(/[ \t]*$/)[0], state); - move(object.range[1], state); -} - -function renderXJSExpression(traverse, object, isLast, path, state) { - // Plus 1 to skip `{`. - move(object.range[0] + 1, state); - traverse(object.value, path, state); - if (!isLast) { - // If we need to append a comma, make sure to do so after the expression. - catchup(object.value.range[1], state); - append(',', state); - } - // Minus 1 to skip `}`. - catchup(object.range[1] - 1, state); - move(object.range[1], state); - return false; -} - -function quoteAttrName(attr) { - // Quote invalid JS identifiers. - if (!/^[a-z_$][a-z\d_$]*$/i.test(attr)) { - return "'" + attr + "'"; - } - return attr; -} - -exports.knownTags = knownTags; -exports.renderXJSExpression = renderXJSExpression; -exports.renderXJSLiteral = renderXJSLiteral; -exports.quoteAttrName = quoteAttrName; - -})() -},{"../lib/utils":8}],10:[function(require,module,exports){ +},{}],5:[function(require,module,exports){ /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; exports.SourceNode = require('./source-map/source-node').SourceNode; -},{"./source-map/source-map-generator":12,"./source-map/source-map-consumer":13,"./source-map/source-node":14}],5:[function(require,module,exports){ -(function(){/** - * 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. - * 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. +},{"./source-map/source-map-consumer":10,"./source-map/source-map-generator":11,"./source-map/source-node":12}],6:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause */ -/*global exports:true*/ -"use strict"; +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { -/** - * Desugarizer for ES6 minimal class proposal. See - * http://wiki.ecmascript.org/doku.php?id=harmony:proposals - * - * Does not require any runtime. Preserves whitespace and comments. - * Supports a class declaration with methods, super calls and inheritance. - * Currently does not support for getters and setters, since there's a very - * low probability we're going to use them anytime soon. - * - * Additional features: - * - Any member with private name (the name with prefix _, such _name) inside - * the class's scope will be munged. This would will to eliminate the case - * of sub-class accidentally overriding the super-class's provate properties - * also discouage people from accessing private members that they should not - * access. However, quoted property names don't get munged. - * - * class SkinnedMesh extends require('THREE').Mesh { - * - * update(camera) { - * camera.code = 'iphone' - * super.update(camera); - * } - * - * / - * * @constructor - * / - * constructor(geometry, materials) { - * super(geometry, materials); - * - * super.update(1); - * - * this.identityMatrix = new THREE.Matrix4(); - * this.bones = []; - * this.boneMatrices = []; - * this._name = 'foo'; - * } - * - * / - * * some other code - * / - * readMore() { - * - * } - * - * _doSomething() { - * - * } - * } - * - * should be converted to - * - * var SkinnedMesh = (function() { - * var __super = require('parent').Mesh; - * - * / - * * @constructor - * / - * function SkinnedMesh(geometry, materials) { - * __super.call(this, geometry, materials); - * - * __super.prototype.update.call(this, 1); - * - * this.identityMatrix = new THREE.Matrix4(); - * this.bones = []; - * this.boneMatrices = []; - * this.$SkinnedMesh_name = 'foo'; - * } - * SkinnedMesh.prototype = Object.create(__super.prototype); - * SkinnedMesh.prototype.constructor = SkinnedMesh; - * - * / - * * @param camera - * / - * SkinnedMesh.prototype.update = function(camera) { - * camera.code = 'iphone' - * __super.prototype.update.call(this, camera); - * }; - * - * SkinnedMesh.prototype.readMore = function() { - * - * }; - * - * SkinnedMesh.prototype.$SkinnedMesh_doSomething = function() { - * - * }; - * - * return SkinnedMesh; - * })(); - * - */ -var Syntax = require('esprima').Syntax; -var base62 = require('base62'); + var util = require('./util'); -var catchup = require('../lib/utils').catchup; -var append = require('../lib/utils').append; -var move = require('../lib/utils').move; -var indentBefore = require('../lib/utils').indentBefore; -var updateIndent = require('../lib/utils').updateIndent; -var updateState = require('../lib/utils').updateState; - -function findConstructorIndex(object) { - var classElements = object.body && object.body.body || []; - for (var i = 0; i < classElements.length; i++) { - if (classElements[i].type === Syntax.MethodDefinition && - classElements[i].key.name === 'constructor') { - return i; - } + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = {}; } - return -1; -} -var _mungedSymbolMaps = {}; -function getMungedName(scopeName, name, minify) { - if (minify) { - if (!_mungedSymbolMaps[scopeName]) { - _mungedSymbolMaps[scopeName] = { - symbolMap: {}, - identifierUUIDCounter: 0 - }; + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i]); } + return set; + }; - var symbolMap = _mungedSymbolMaps[scopeName].symbolMap; - if (!symbolMap[name]) { - symbolMap[name] = - base62.encode(_mungedSymbolMaps[scopeName].identifierUUIDCounter); - _mungedSymbolMaps[scopeName].identifierUUIDCounter++; + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr) { + if (this.has(aStr)) { + // Already a member; nothing to do. + return; } - name = symbolMap[name]; - } - return '$' + scopeName + name; -} + var idx = this._array.length; + this._array.push(aStr); + this._set[util.toSetString(aStr)] = idx; + }; -function shouldMungeName(scopeName, name, state) { - // only run when @preventMunge is not present in the docblock - if (state.g.preventMunge === undefined) { - var docblock = require('../lib/docblock'); - state.g.preventMunge = docblock.parseAsObject( - docblock.extract(state.g.source)).preventMunge !== undefined; - } - // Starts with only a single underscore (i.e. don't count double-underscores) - return !state.g.preventMunge && scopeName ? /^_(?!_)/.test(name) : false; -} + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + return Object.prototype.hasOwnProperty.call(this._set, + util.toSetString(aStr)); + }; - -function getProtoOfPrototypeVariableName(superVar) { - return superVar + 'ProtoOfPrototype'; -} - -function getSuperKeyName(superVar) { - return superVar + 'Key'; -} - -function getSuperProtoOfPrototypeVariable(superVariableName, indent) { - var string = (indent + - 'var $proto = $superName && $superName.prototype ? ' + - '$superName.prototype : $superName;\n' - ).replace(/\$proto/g, getProtoOfPrototypeVariableName(superVariableName)) - .replace(/\$superName/g, superVariableName); - return string; -} - - -function getInheritanceSetup(superClassToken, className, indent, superName) { - var string = ''; - if (superClassToken) { - string += getStaticMethodsOnConstructorSetup(className, indent, superName); - string += getPrototypeOnConstructorSetup(className, indent, superName); - string += getConstructorPropertySetup(className, indent); - } - return string; -} - -function getStaticMethodsOnConstructorSetup(className, indent, superName) { - var string = ( indent + - 'for (var $keyName in $superName) {\n' + indent + - ' if ($superName.hasOwnProperty($keyName)) {\n' + indent + - ' $className[$keyName] = $superName[$keyName];\n' + indent + - ' }\n' + indent + - '}\n') - .replace(/\$className/g, className) - .replace(/\$keyName/g, getSuperKeyName(superName)) - .replace(/\$superName/g, superName); - return string; -} - -function getPrototypeOnConstructorSetup(className, indent, superName) { - var string = ( indent + - '$className.prototype = Object.create($protoPrototype);\n') - .replace(/\$protoPrototype/g, getProtoOfPrototypeVariableName(superName)) - .replace(/\$className/g, className); - return string; -} - -function getConstructorPropertySetup(className, indent) { - var string = ( indent + - '$className.prototype.constructor = $className;\n') - .replace(/\$className/g, className); - - return string; -} - -function getSuperConstructorSetup(superClassToken, indent, superName) { - if (!superClassToken) return ''; - var string = ( '\n' + indent + - ' if ($superName && $superName.prototype) {\n' + indent + - ' $superName.apply(this, arguments);\n' + indent + - ' }\n' + indent) - .replace(/\$superName/g, superName); - return string; -} - -function getMemberFunctionCall(superVar, propertyName, superArgs) { - var string = ( - '$superPrototype.$propertyName.call($superArguments)') - .replace(/\$superPrototype/g, getProtoOfPrototypeVariableName(superVar)) - .replace(/\$propertyName/g, propertyName) - .replace(/\$superArguments/g, superArgs); - return string; -} - -function getCallParams(classElement, state) { - var params = classElement.value.params; - if (!params.length) { - return ''; - } - return state.g.source.substring( - params[0].range[0], - params[params.length - 1].range[1]); -} - -function getSuperArguments(callExpression, state) { - var args = callExpression.arguments; - if (!args.length) { - return 'this'; - } - return 'this, ' + state.g.source.substring( - args[0].range[0], - args[args.length - 1].range[1]); -} - -// The seed is used to generate the name for an anonymous class, -// and this seed should be unique per browser's session. -// The value of the seed looks like this: 1229588505.2969012. -var classIDSeed = Date.now() % (60 * 60 * 1000) + Math.random(); - -/** - * Generates a name for an anonymous class. The generated value looks like - * this: "Classkc6pcn_mniza1yvi" - * @param {String} scopeName - * @return {string} the scope name for Anonymous Class - */ -function generateAnonymousClassName(scopeName) { - classIDSeed++; - return 'Class' + - (classIDSeed).toString(36).replace('.', '_') + - (scopeName || ''); -} - -function renderMethods(traverse, object, name, path, state) { - var classElements = object.body && object.body.body || []; - - move(object.body.range[0] + 1, state); - for (var i = 0; i < classElements.length; i++) { - if (classElements[i].key.name !== 'constructor') { - catchup(classElements[i].range[0], state); - - var memberName = classElements[i].key.name; - if (shouldMungeName(state.scopeName, memberName, state)) { - memberName = getMungedName( - state.scopeName, - memberName, - state.g.opts.minify - ); - } - - var prototypeOrStatic; - if (classElements[i]['static']) { - prototypeOrStatic = ''; - } else { - prototypeOrStatic = 'prototype.'; - } - - append(name + '.' + prototypeOrStatic + memberName + ' = ', state); - renderMethod(traverse, classElements[i], null, path, state); - append(';', state); + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (this.has(aStr)) { + return this._set[util.toSetString(aStr)]; } - move(classElements[i].range[1], state); - } - if (classElements.length) { - append('\n', state); - } - move(object.range[1], state); -} + throw new Error('"' + aStr + '" is not in the set.'); + }; -function renderMethod(traverse, method, name, path, state) { - append(name ? 'function ' + name + '(' : 'function(', state); - append(getCallParams(method, state) + ') {', state); - move(method.value.body.range[0] + 1, state); - traverse(method.value.body, path, state); - catchup(method.value.body.range[1] - 1, state); - append('}', state); -} - -function renderSuperClass(traverse, superClass, path, state) { - append('var ' + state.superVar + ' = ', state); - move(superClass.range[0], state); - traverse(superClass, path, state); - catchup(superClass.range[1], state); - append(';\n', state); -} - -function renderConstructor(traverse, object, name, indent, path, state) { - var classElements = object.body && object.body.body || []; - var constructorIndex = findConstructorIndex(object); - var constructor = constructorIndex === -1 ? - null : - classElements[constructorIndex]; - if (constructor) { - move(constructorIndex === 0 ? - object.body.range[0] + 1 : - classElements[constructorIndex - 1].range[1], state); - catchup(constructor.range[0], state); - renderMethod(traverse, constructor, name, path, state); - append('\n', state); - } else { - if (object.superClass) { - append('\n' + indent, state); + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; } - append('function ', state); - if (object.id) { - move(object.id.range[0], state); - } - append(name, state); - if (object.id) { - move(object.id.range[1], state); - } - append('(){ ', state); - if (object.body) { - move(object.body.range[0], state); - } - append(getSuperConstructorSetup( - object.superClass, - indent, - state.superVar), state); - append('}\n', state); - } -} + throw new Error('No element indexed by ' + aIdx); + }; -var superId = 0; -function renderClassBody(traverse, object, path, state) { - var name = object.id ? object.id.name : 'constructor'; - var superClass = object.superClass; - var indent = updateIndent( - indentBefore(object.range[0], state) + ' ', - state); + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; - state = updateState( - state, - { - scopeName: object.id ? object.id.name : - generateAnonymousClassName(state.scopeName), - superVar: superClass ? '__super' + superId++ : '' - }); + exports.ArraySet = ArraySet; - // super class - if (superClass) { - append(indent, state); - renderSuperClass(traverse, superClass, path, state); - append(getSuperProtoOfPrototypeVariable(state.superVar, indent), state); - } +}); - renderConstructor(traverse, object, name, indent, path, state); - append(getInheritanceSetup(superClass, name, indent, state.superVar), state); - renderMethods(traverse, object, name, path, state); -} - - -/** - * @public - */ -function visitClassExpression(traverse, object, path, state) { - var indent = updateIndent( - indentBefore(object.range[0], state) + ' ', - state); - var name = object.id ? object.id.name : 'constructor'; - - append('(function() {\n', state); - renderClassBody(traverse, object, path, state); - append(indent + 'return ' + name + ';\n', state); - append(indent.substring(0, indent.length - 2) + '})()', state); - return false -} - -visitClassExpression.test = function(object, path, state) { - return object.type === Syntax.ClassExpression; -}; - -/** - * @public - */ -function visitClassDeclaration(traverse, object, path, state) { - state.g.indentBy--; - renderClassBody(traverse, object, path, state); - state.g.indentBy++; - return false; -} - -visitClassDeclaration.test = function(object, path, state) { - return object.type === Syntax.ClassDeclaration; -}; - - -/** - * @public - */ -function visitSuperCall(traverse, object, path, state) { - if (path[0].type === Syntax.CallExpression) { - append(state.superVar + - '.call(' + getSuperArguments(path[0], state) + ')', state); - move(path[0].range[1], state); - } else if (path[0].type === Syntax.MemberExpression) { - append(getMemberFunctionCall( - state.superVar, - path[0].property.name, - getSuperArguments(path[1], state)), state); - move(path[1].range[1], state); - } - return false; -} - -visitSuperCall.test = function(object, path, state) { - return state.superVar && object.type === Syntax.Identifier && - object.name === 'super'; -}; - -/** - * @public - */ -function visitPrivateProperty(traverse, object, path, state) { - var type = path[0] ? path[0].type : null; - if (type !== Syntax.Property) { - if (type === Syntax.MemberExpression) { - type = path[0].object ? path[0].object.type : null; - if (type === Syntax.Identifier && - path[0].object.range[0] === object.range[0]) { - // Identifier is a variable that appears "private". - return; - } - } else { - // Other syntax that are neither Property nor MemberExpression. - return; - } - } - - var oldName = object.name; - var newName = getMungedName( - state.scopeName, - oldName, - state.g.opts.minify - ); - append(newName, state); - move(object.range[1], state); -} - -visitPrivateProperty.test = function(object, path, state) { - return object.type === Syntax.Identifier && - shouldMungeName(state.scopeName, object.name, state); -}; - - -exports.visitClassDeclaration = visitClassDeclaration; -exports.visitClassExpression = visitClassExpression; -exports.visitSuperCall = visitSuperCall; -exports.visitPrivateProperty = visitPrivateProperty; - -})() -},{"../lib/utils":8,"../lib/docblock":4,"esprima":9,"base62":15}],6:[function(require,module,exports){ -(function(){/** - * Copyright 2013 Facebook, Inc. +},{"./util":13,"amdefine":14}],7:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause * - * 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 + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java * - * http://www.apache.org/licenses/LICENSE-2.0 + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: * - * 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. + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/*global exports:true*/ -"use strict"; +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { -var Syntax = require('esprima').Syntax; + var base64 = require('./base64'); -var catchup = require('../lib/utils').catchup; -var append = require('../lib/utils').append; -var move = require('../lib/utils').move; -var getDocblock = require('../lib/utils').getDocblock; + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 -var FALLBACK_TAGS = require('./xjs').knownTags; -var renderXJSExpression = require('./xjs').renderXJSExpression; -var renderXJSLiteral = require('./xjs').renderXJSLiteral; -var quoteAttrName = require('./xjs').quoteAttrName; + var VLQ_BASE_SHIFT = 5; -/** - * 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)]) - * - * 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. - */ + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; -var JSX_ATTRIBUTE_RENAMES = { - 'class': 'className', - cxName: 'className' -}; + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; -var JSX_ATTRIBUTE_TRANSFORMS = { - cxName: function(attr) { - if (attr.value.type !== Syntax.Literal) { - throw new Error("cx only accepts a string literal"); - } else { - var classNames = attr.value.value.split(/\s+/g); - return 'cx(' + classNames.map(JSON.stringify).join(',') + ')'; - } - } -}; + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; -function visitReactTag(traverse, object, path, state) { - var jsxObjIdent = getDocblock(state).jsx; - - catchup(object.openingElement.range[0], state); - - if (object.name.namespace) { - throw new Error( - 'Namespace tags are not supported. ReactJSX is not XML.'); + /** + * Converts from a two-complement value to a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; } - var isFallbackTag = FALLBACK_TAGS[object.name.name]; - append( - (isFallbackTag ? jsxObjIdent + '.' : '') + (object.name.name) + '(', - state - ); - - move(object.name.range[1], state); - - var childrenToRender = object.children.filter(function(child) { - return !(child.type === Syntax.Literal && !child.value.match(/\S/)); - }); - - // if we don't have any attributes, pass in null - if (object.attributes.length === 0) { - append('null', state); + /** + * Converts to a two-complement value from a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; } - // write attributes - object.attributes.forEach(function(attr, index) { - catchup(attr.range[0], state); - if (attr.name.namespace) { - throw new Error( - 'Namespace attributes are not supported. ReactJSX is not XML.'); - } - var name = JSX_ATTRIBUTE_RENAMES[attr.name.name] || attr.name.name; - var isFirst = index === 0; - var isLast = index === object.attributes.length - 1; + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; - if (isFirst) { - append('{', state); - } + var vlq = toVLQSigned(aValue); - append(quoteAttrName(name), state); - append(':', state); - - if (!attr.value) { - state.g.buffer += 'true'; - state.g.position = attr.name.range[1]; - if (!isLast) { - append(',', state); + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; } - } else if (JSX_ATTRIBUTE_TRANSFORMS[attr.name.name]) { - move(attr.value.range[0], state); - append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state); - move(attr.value.range[1], state); - if (!isLast) { - append(',', state); - } - } else if (attr.value.type === Syntax.Literal) { - move(attr.value.range[0], state); - renderXJSLiteral(attr.value, isLast, state); - } else { - move(attr.value.range[0], state); - renderXJSExpression(traverse, attr.value, isLast, path, state); - } + encoded += base64.encode(digit); + } while (vlq > 0); - if (isLast) { - append('}', state); - } + return encoded; + }; - catchup(attr.range[1], state); - }); + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string. + */ + exports.decode = function base64VLQ_decode(aStr) { + var i = 0; + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; - if (!object.selfClosing) { - catchup(object.openingElement.range[1] - 1, state); - move(object.openingElement.range[1], state); - } - - // separate props and children arguments - append(', ', state); - - // filter out whitespace - if (childrenToRender.length > 0) { - if (childrenToRender.length > 1) { - append('[', state); - } - object.children.forEach(function(child) { - if (child.type === Syntax.Literal && !child.value.match(/\S/)) { - return; + do { + if (i >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); } - catchup(child.range[0], state); + digit = base64.decode(aStr.charAt(i++)); + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); - var isLast = child === childrenToRender[childrenToRender.length - 1]; - - if (child.type === Syntax.Literal) { - renderXJSLiteral(child, isLast, state); - } else if (child.type === Syntax.XJSExpression) { - renderXJSExpression(traverse, child, isLast, path, state); - } else { - traverse(child, path, state); - if (!isLast) { - append(',', state); - state.g.buffer = state.g.buffer.replace(/(\s*),$/, ',$1'); - } - } - - catchup(child.range[1], state); - }); - } else { - append('null', state); - } - - if (object.selfClosing) { - // everything up to /> - catchup(object.openingElement.range[1] - 2, state); - move(object.openingElement.range[1], state); - } else { - // everything up to </ sdflksjfd> - catchup(object.closingElement.range[0], state); - move(object.closingElement.range[1], state); - } - - if (childrenToRender.length > 0) { - if (childrenToRender.length > 1) { - append(']', state); - } - } - append(')', state); - return false; -} - -visitReactTag.test = function(object, path, state) { - // only run react when react @jsx namespace is specified in docblock - var jsx = getDocblock(state).jsx; - return object.type === Syntax.XJSElement && jsx && jsx.length; -}; - -exports.visitReactTag = visitReactTag; - -})() -},{"../lib/utils":8,"./xjs":11,"esprima":9}],7:[function(require,module,exports){ -(function(){/** - * 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. - * 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. - */ -/*global exports:true*/ -"use strict"; - -var Syntax = require('esprima').Syntax; -var catchup = require('../lib/utils').catchup; -var append = require('../lib/utils').append; -var getDocblock = require('../lib/utils').getDocblock; - -/** - * Transforms the following: - * - * var MyComponent = React.createClass({ - * render: ... - * }); - * - * into: - * - * var MyComponent = React.createClass({ - * displayName: 'MyComponent', - * render: ... - * }); - */ -function visitReactDisplayName(traverse, object, path, state) { - if (object.id.type === Syntax.Identifier && - object.init && - object.init.type === Syntax.CallExpression && - object.init.callee.type === Syntax.MemberExpression && - object.init.callee.object.type === Syntax.Identifier && - object.init.callee.object.name === 'React' && - object.init.callee.property.type === Syntax.Identifier && - object.init.callee.property.name === 'createClass' && - object.init['arguments'].length === 1 && - object.init['arguments'][0].type === Syntax.ObjectExpression) { - - var displayName = object.id.name; - catchup(object.init['arguments'][0].range[0] + 1, state); - append("displayName: '" + displayName + "',", state); - } -} - -/** - * Will only run on @jsx files for now. - */ -visitReactDisplayName.test = function(object, path, state) { - return object.type === Syntax.VariableDeclarator && !!getDocblock(state).jsx; -}; - -exports.visitReactDisplayName = visitReactDisplayName; - -})() -},{"../lib/utils":8,"esprima":9}],15:[function(require,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 + return { + value: fromVLQSigned(result), + rest: aStr.slice(i) + }; }; - 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 -},{}],12:[function(require,module,exports){ +},{"./base64":8,"amdefine":14}],8:[function(require,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ if (typeof define !== 'function') { - var define = require('amdefine')(module); + var define = require('amdefine')(module, require); } define(function (require, exports, module) { - var base64VLQ = require('./base64-vlq'); - var util = require('./util'); - var ArraySet = require('./array-set').ArraySet; + var charToIntMap = {}; + var intToCharMap = {}; - /** - * An instance of the SourceMapGenerator represents a source map which is - * being built incrementally. To create a new one, you must pass an object - * with the following properties: - * - * - file: The filename of the generated source. - * - sourceRoot: An optional root for all URLs in this source map. - */ - function SourceMapGenerator(aArgs) { - this._file = util.getArg(aArgs, 'file'); - this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); - this._sources = new ArraySet(); - this._names = new ArraySet(); - this._mappings = []; - this._sourcesContents = null; - } + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + .split('') + .forEach(function (ch, index) { + charToIntMap[ch] = index; + intToCharMap[index] = ch; + }); - SourceMapGenerator.prototype._version = 3; - /** - * Creates a new SourceMapGenerator based on a SourceMapConsumer - * - * @param aSourceMapConsumer The SourceMap. + * Encode an integer in the range of 0 to 63 to a single base 64 digit. */ - SourceMapGenerator.fromSourceMap = - function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { - var sourceRoot = aSourceMapConsumer.sourceRoot; - var generator = new SourceMapGenerator({ - file: aSourceMapConsumer.file, - sourceRoot: sourceRoot - }); - aSourceMapConsumer.eachMapping(function (mapping) { - var newMapping = { - generated: { - line: mapping.generatedLine, - column: mapping.generatedColumn - } - }; + exports.encode = function base64_encode(aNumber) { + if (aNumber in intToCharMap) { + return intToCharMap[aNumber]; + } + throw new TypeError("Must be between 0 and 63: " + aNumber); + }; - if (mapping.source) { - newMapping.source = mapping.source; - if (sourceRoot) { - newMapping.source = util.relative(sourceRoot, newMapping.source); - } - - newMapping.original = { - line: mapping.originalLine, - column: mapping.originalColumn - }; - - if (mapping.name) { - newMapping.name = mapping.name; - } - } - - generator.addMapping(newMapping); - }); - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content) { - generator.setSourceContent(sourceFile, content); - } - }); - return generator; - }; - /** - * Add a single mapping from original source line and column to the generated - * source's line and column for this source map being created. The mapping - * object should have the following properties: - * - * - generated: An object with the generated line and column positions. - * - original: An object with the original line and column positions. - * - source: The original source file (relative to the sourceRoot). - * - name: An optional original token name for this mapping. + * Decode a single base 64 digit to an integer. */ - SourceMapGenerator.prototype.addMapping = - function SourceMapGenerator_addMapping(aArgs) { - var generated = util.getArg(aArgs, 'generated'); - var original = util.getArg(aArgs, 'original', null); - var source = util.getArg(aArgs, 'source', null); - var name = util.getArg(aArgs, 'name', null); + exports.decode = function base64_decode(aChar) { + if (aChar in charToIntMap) { + return charToIntMap[aChar]; + } + throw new TypeError("Not a valid base 64 digit: " + aChar); + }; - this._validateMapping(generated, original, source, name); +}); - if (source && !this._sources.has(source)) { - this._sources.add(source); - } +},{"amdefine":14}],9:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { - if (name && !this._names.has(name)) { - this._names.add(name); - } - - this._mappings.push({ - generated: generated, - original: original, - source: source, - name: name - }); - }; - /** - * Set the source content for a source file. - */ - SourceMapGenerator.prototype.setSourceContent = - function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { - var source = aSourceFile; - if (this._sourceRoot) { - source = util.relative(this._sourceRoot, source); - } - - if (aSourceContent !== null) { - // Add the source content to the _sourcesContents map. - // Create a new _sourcesContents map if the property is null. - if (!this._sourcesContents) { - this._sourcesContents = {}; - } - this._sourcesContents[util.toSetString(source)] = aSourceContent; - } else { - // Remove the source file from the _sourcesContents map. - // If the _sourcesContents map is empty, set the property to null. - delete this._sourcesContents[util.toSetString(source)]; - if (Object.keys(this._sourcesContents).length === 0) { - this._sourcesContents = null; - } - } - }; - - /** - * Applies the mappings of a sub-source-map for a specific source file to the - * source map being generated. Each mapping to the supplied source file is - * rewritten using the supplied source map. Note: The resolution for the - * resulting mappings is the minimium of this map and the supplied map. + * Recursive implementation of binary search. * - * @param aSourceMapConsumer The source map to be applied. - * @param aSourceFile Optional. The filename of the source file. - * If omitted, SourceMapConsumer's file property will be used. + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. */ - SourceMapGenerator.prototype.applySourceMap = - function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) { - // If aSourceFile is omitted, we will use the file property of the SourceMap - if (!aSourceFile) { - aSourceFile = aSourceMapConsumer.file; + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the next + // closest element that is less than that element. + // + // 3. We did not find the exact element, and there is no next-closest + // element which is less than the one we are searching for, so we + // return null. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid]); + if (cmp === 0) { + // Found the element we are looking for. + return aHaystack[mid]; + } + else if (cmp > 0) { + // aHaystack[mid] is greater than our needle. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); } - var sourceRoot = this._sourceRoot; - // Make "aSourceFile" relative if an absolute Url is passed. - if (sourceRoot) { - aSourceFile = util.relative(sourceRoot, aSourceFile); + // We did not find an exact match, return the next closest one + // (termination case 2). + return aHaystack[mid]; + } + else { + // aHaystack[mid] is less than our needle. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); } - // Applying the SourceMap can add and remove items from the sources and - // the names array. - var newSources = new ArraySet(); - var newNames = new ArraySet(); + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (2) or (3) and return the appropriate thing. + return aLow < 0 + ? null + : aHaystack[aLow]; + } + } - // Find mappings for the "aSourceFile" - this._mappings.forEach(function (mapping) { - if (mapping.source === aSourceFile && mapping.original) { - // Check if it can be mapped by the source map, then update the mapping. - var original = aSourceMapConsumer.originalPositionFor({ - line: mapping.original.line, - column: mapping.original.column - }); - if (original.source !== null) { - // Copy mapping - if (sourceRoot) { - mapping.source = util.relative(sourceRoot, original.source); - } else { - mapping.source = original.source; - } - mapping.original.line = original.line; - mapping.original.column = original.column; - if (original.name !== null && mapping.name !== null) { - // Only use the identifier name if it's an identifier - // in both SourceMaps - mapping.name = original.name; - } - } - } - - var source = mapping.source; - if (source && !newSources.has(source)) { - newSources.add(source); - } - - var name = mapping.name; - if (name && !newNames.has(name)) { - newNames.add(name); - } - - }, this); - this._sources = newSources; - this._names = newNames; - - // Copy sourcesContents of applied map. - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content) { - if (sourceRoot) { - sourceFile = util.relative(sourceRoot, sourceFile); - } - this.setSourceContent(sourceFile, content); - } - }, this); - }; - /** - * A mapping can have one of the three levels of data: + * This is an implementation of binary search which will always try and return + * the next lowest value checked if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. * - * 1. Just the generated position. - * 2. The Generated position, original position, and original source. - * 3. Generated and original position, original source, as well as a name - * token. - * - * To maintain consistency, we validate that any new mapping being added falls - * in to one of these categories. + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. */ - SourceMapGenerator.prototype._validateMapping = - function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, - aName) { - if (aGenerated && 'line' in aGenerated && 'column' in aGenerated - && aGenerated.line > 0 && aGenerated.column >= 0 - && !aOriginal && !aSource && !aName) { - // Case 1. - return; - } - else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated - && aOriginal && 'line' in aOriginal && 'column' in aOriginal - && aGenerated.line > 0 && aGenerated.column >= 0 - && aOriginal.line > 0 && aOriginal.column >= 0 - && aSource) { - // Cases 2 and 3. - return; - } - else { - throw new Error('Invalid mapping.'); - } - }; + exports.search = function search(aNeedle, aHaystack, aCompare) { + return aHaystack.length > 0 + ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) + : null; + }; - function cmpLocation(loc1, loc2) { - var cmp = (loc1 && loc1.line) - (loc2 && loc2.line); - return cmp ? cmp : (loc1 && loc1.column) - (loc2 && loc2.column); - } - - function strcmp(str1, str2) { - str1 = str1 || ''; - str2 = str2 || ''; - return (str1 > str2) - (str1 < str2); - } - - function cmpMapping(mappingA, mappingB) { - return cmpLocation(mappingA.generated, mappingB.generated) || - cmpLocation(mappingA.original, mappingB.original) || - strcmp(mappingA.source, mappingB.source) || - strcmp(mappingA.name, mappingB.name); - } - - /** - * Serialize the accumulated mappings in to the stream of base 64 VLQs - * specified by the source map format. - */ - SourceMapGenerator.prototype._serializeMappings = - function SourceMapGenerator_serializeMappings() { - var previousGeneratedColumn = 0; - var previousGeneratedLine = 1; - var previousOriginalColumn = 0; - var previousOriginalLine = 0; - var previousName = 0; - var previousSource = 0; - var result = ''; - var mapping; - - // The mappings must be guarenteed to be in sorted order before we start - // serializing them or else the generated line numbers (which are defined - // via the ';' separators) will be all messed up. Note: it might be more - // performant to maintain the sorting as we insert them, rather than as we - // serialize them, but the big O is the same either way. - this._mappings.sort(cmpMapping); - - for (var i = 0, len = this._mappings.length; i < len; i++) { - mapping = this._mappings[i]; - - if (mapping.generated.line !== previousGeneratedLine) { - previousGeneratedColumn = 0; - while (mapping.generated.line !== previousGeneratedLine) { - result += ';'; - previousGeneratedLine++; - } - } - else { - if (i > 0) { - if (!cmpMapping(mapping, this._mappings[i - 1])) { - continue; - } - result += ','; - } - } - - result += base64VLQ.encode(mapping.generated.column - - previousGeneratedColumn); - previousGeneratedColumn = mapping.generated.column; - - if (mapping.source && mapping.original) { - result += base64VLQ.encode(this._sources.indexOf(mapping.source) - - previousSource); - previousSource = this._sources.indexOf(mapping.source); - - // lines are stored 0-based in SourceMap spec version 3 - result += base64VLQ.encode(mapping.original.line - 1 - - previousOriginalLine); - previousOriginalLine = mapping.original.line - 1; - - result += base64VLQ.encode(mapping.original.column - - previousOriginalColumn); - previousOriginalColumn = mapping.original.column; - - if (mapping.name) { - result += base64VLQ.encode(this._names.indexOf(mapping.name) - - previousName); - previousName = this._names.indexOf(mapping.name); - } - } - } - - return result; - }; - - /** - * Externalize the source map. - */ - SourceMapGenerator.prototype.toJSON = - function SourceMapGenerator_toJSON() { - var map = { - version: this._version, - file: this._file, - sources: this._sources.toArray(), - names: this._names.toArray(), - mappings: this._serializeMappings() - }; - if (this._sourceRoot) { - map.sourceRoot = this._sourceRoot; - } - if (this._sourcesContents) { - map.sourcesContent = map.sources.map(function (source) { - if (map.sourceRoot) { - source = util.relative(map.sourceRoot, source); - } - return Object.prototype.hasOwnProperty.call( - this._sourcesContents, util.toSetString(source)) - ? this._sourcesContents[util.toSetString(source)] - : null; - }, this); - } - return map; - }; - - /** - * Render the source map being generated to a string. - */ - SourceMapGenerator.prototype.toString = - function SourceMapGenerator_toString() { - return JSON.stringify(this); - }; - - exports.SourceMapGenerator = SourceMapGenerator; - }); -},{"./base64-vlq":16,"./util":17,"./array-set":18,"amdefine":19}],13:[function(require,module,exports){ +},{"amdefine":14}],10:[function(require,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ if (typeof define !== 'function') { - var define = require('amdefine')(module); + var define = require('amdefine')(module, require); } define(function (require, exports, module) { var util = require('./util'); var binarySearch = require('./binary-search'); @@ -8638,13 +7126,13 @@ name: null }; }; /** - * Returns the original source content. The only argument is - * the url of the original source file. Returns null if no - * original source content is availible. + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * availible. */ SourceMapConsumer.prototype.sourceContentFor = function SourceMapConsumer_sourceContentFor(aSource) { if (!this.sourcesContent) { return null; @@ -8658,14 +7146,25 @@ return this.sourcesContent[this._sources.indexOf(aSource)]; } var url; if (this.sourceRoot - && (url = util.urlParse(this.sourceRoot)) - && (!url.path || url.path == "/") - && this._sources.has("/" + aSource)) { - return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } } throw new Error('"' + aSource + '" is not in the SourceMap.'); }; @@ -8769,22 +7268,405 @@ exports.SourceMapConsumer = SourceMapConsumer; }); -},{"./util":17,"./binary-search":20,"./array-set":18,"./base64-vlq":16,"amdefine":19}],14:[function(require,module,exports){ +},{"./array-set":6,"./base64-vlq":7,"./binary-search":9,"./util":13,"amdefine":14}],11:[function(require,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ if (typeof define !== 'function') { - var define = require('amdefine')(module); + var define = require('amdefine')(module, require); } define(function (require, exports, module) { + var base64VLQ = require('./base64-vlq'); + var util = require('./util'); + var ArraySet = require('./array-set').ArraySet; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. To create a new one, you must pass an object + * with the following properties: + * + * - file: The filename of the generated source. + * - sourceRoot: An optional root for all URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + this._file = util.getArg(aArgs, 'file'); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = []; + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source) { + newMapping.source = mapping.source; + if (sourceRoot) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + this._validateMapping(generated, original, source, name); + + if (source && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.push({ + generated: generated, + original: original, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent !== null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = {}; + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) { + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (!aSourceFile) { + aSourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "aSourceFile" relative if an absolute Url is passed. + if (sourceRoot) { + aSourceFile = util.relative(sourceRoot, aSourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "aSourceFile" + this._mappings.forEach(function (mapping) { + if (mapping.source === aSourceFile && mapping.original) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.original.line, + column: mapping.original.column + }); + if (original.source !== null) { + // Copy mapping + if (sourceRoot) { + mapping.source = util.relative(sourceRoot, original.source); + } else { + mapping.source = original.source; + } + mapping.original.line = original.line; + mapping.original.column = original.column; + if (original.name !== null && mapping.name !== null) { + // Only use the identifier name if it's an identifier + // in both SourceMaps + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + if (sourceRoot) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping.'); + } + }; + + function cmpLocation(loc1, loc2) { + var cmp = (loc1 && loc1.line) - (loc2 && loc2.line); + return cmp ? cmp : (loc1 && loc1.column) - (loc2 && loc2.column); + } + + function strcmp(str1, str2) { + str1 = str1 || ''; + str2 = str2 || ''; + return (str1 > str2) - (str1 < str2); + } + + function cmpMapping(mappingA, mappingB) { + return cmpLocation(mappingA.generated, mappingB.generated) || + cmpLocation(mappingA.original, mappingB.original) || + strcmp(mappingA.source, mappingB.source) || + strcmp(mappingA.name, mappingB.name); + } + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + + // The mappings must be guaranteed to be in sorted order before we start + // serializing them or else the generated line numbers (which are defined + // via the ';' separators) will be all messed up. Note: it might be more + // performant to maintain the sorting as we insert them, rather than as we + // serialize them, but the big O is the same either way. + this._mappings.sort(cmpMapping); + + for (var i = 0, len = this._mappings.length; i < len; i++) { + mapping = this._mappings[i]; + + if (mapping.generated.line !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generated.line !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!cmpMapping(mapping, this._mappings[i - 1])) { + continue; + } + result += ','; + } + } + + result += base64VLQ.encode(mapping.generated.column + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generated.column; + + if (mapping.source && mapping.original) { + result += base64VLQ.encode(this._sources.indexOf(mapping.source) + - previousSource); + previousSource = this._sources.indexOf(mapping.source); + + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.original.line - 1 + - previousOriginalLine); + previousOriginalLine = mapping.original.line - 1; + + result += base64VLQ.encode(mapping.original.column + - previousOriginalColumn); + previousOriginalColumn = mapping.original.column; + + if (mapping.name) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + file: this._file, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._sourceRoot) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = map.sources.map(function (source) { + if (map.sourceRoot) { + source = util.relative(map.sourceRoot, source); + } + return Object.prototype.hasOwnProperty.call( + this._sourcesContents, util.toSetString(source)) + ? this._sourcesContents[util.toSetString(source)] + : null; + }, this); + } + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + +}); + +},{"./array-set":6,"./base64-vlq":7,"./util":13,"amdefine":14}],12:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; var util = require('./util'); /** * SourceNodes provide a way to abstract over interpolating/concatenating @@ -8897,11 +7779,11 @@ }); return node; function addMappingWithCode(mapping, code) { - if (mapping.source === undefined) { + if (mapping === null || mapping.source === undefined) { node.add(code); } else { node.add(new SourceNode(mapping.originalLine, mapping.originalColumn, mapping.source, @@ -9124,65 +8006,130 @@ exports.SourceNode = SourceNode; }); -},{"./source-map-generator":12,"./util":17,"amdefine":19}],21:[function(require,module,exports){ -// shim for using process in browser +},{"./source-map-generator":11,"./util":13,"amdefine":14}],13:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { -var process = module.exports = {}; + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; -process.nextTick = (function () { - var canSetImmediate = typeof window !== 'undefined' - && window.setImmediate; - var canPost = typeof window !== 'undefined' - && window.postMessage && window.addEventListener - ; + var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/; - if (canSetImmediate) { - return function (f) { return window.setImmediate(f) }; + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; } + return { + scheme: match[1], + auth: match[3], + host: match[4], + port: match[6], + path: match[7] + }; + } + exports.urlParse = urlParse; - if (canPost) { - var queue = []; - window.addEventListener('message', function (ev) { - if (ev.source === window && ev.data === 'process-tick') { - ev.stopPropagation(); - if (queue.length > 0) { - var fn = queue.shift(); - fn(); - } - } - }, true); + function urlGenerate(aParsedUrl) { + var url = aParsedUrl.scheme + "://"; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + "@" + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + exports.urlGenerate = urlGenerate; - return function nextTick(fn) { - queue.push(fn); - window.postMessage('process-tick', '*'); - }; + function join(aRoot, aPath) { + var url; + + if (aPath.match(urlRegexp)) { + return aPath; } - return function nextTick(fn) { - setTimeout(fn, 0); - }; -})(); + if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) { + url.path = aPath; + return urlGenerate(url); + } -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; + return aRoot.replace(/\/$/, '') + '/' + aPath; + } + exports.join = join; -process.binding = function (name) { - throw new Error('process.binding is not supported'); -} + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + return '$' + aStr; + } + exports.toSetString = toSetString; -// TODO(shtylman) -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; + function fromSetString(aStr) { + return aStr.substr(1); + } + exports.fromSetString = fromSetString; -},{}],19:[function(require,module,exports){ + function relative(aRoot, aPath) { + aRoot = aRoot.replace(/\/$/, ''); + + var url = urlParse(aRoot); + if (aPath.charAt(0) == "/" && url && url.path == "/") { + return aPath.slice(1); + } + + return aPath.indexOf(aRoot + '/') === 0 + ? aPath.substr(aRoot.length + 1) + : aPath; + } + exports.relative = relative; + +}); + +},{"amdefine":14}],14:[function(require,module,exports){ (function(process,__filename){/** vim: et:ts=4:sw=4:sts=4 * @license amdefine 0.0.5 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. * Available via the MIT or new BSD license. * see: http://github.com/jrburke/amdefine for details */ @@ -9480,676 +8427,1770 @@ } module.exports = amdefine; })(require("__browserify_process"),"/../node_modules/source-map/node_modules/amdefine/amdefine.js") -},{"path":22,"__browserify_process":21}],16:[function(require,module,exports){ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause +},{"__browserify_process":3,"path":2}],15:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. * - * Based on the Base 64 VLQ implementation in Closure Compiler: - * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * 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 * - * Copyright 2011 The Closure Compiler Authors. All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: + * http://www.apache.org/licenses/LICENSE-2.0 * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * 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. */ -if (typeof define !== 'function') { - var define = require('amdefine')(module); +/* jshint browser: true */ +/* jslint evil: true */ + +'use strict'; +var runScripts; + +var transform = require('./fbtransform/lib/transform').transform; +var visitors = require('./fbtransform/visitors').transformVisitors; +var transform = transform.bind(null, visitors.react); +var docblock = require('./fbtransform/lib/docblock'); + +var headEl = document.getElementsByTagName('head')[0]; + +exports.transform = transform; + +exports.exec = function(code) { + return eval(transform(code)); +}; + +var run = exports.run = function(code) { + var jsx = docblock.parseAsObject(docblock.extract(code)).jsx; + + var functionBody = jsx ? transform(code).code : code; + var scriptEl = document.createElement('script'); + + scriptEl.innerHTML = functionBody; + headEl.appendChild(scriptEl); +}; + +if (typeof window === "undefined" || window === null) { + return; } -define(function (require, exports, module) { - var base64 = require('./base64'); +var load = exports.load = function(url, callback) { + var xhr; + xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') + : new XMLHttpRequest(); + // Disable async since we need to execute scripts in the order they are in the + // DOM to mirror normal script loading. + xhr.open('GET', url, false); + if ('overrideMimeType' in xhr) { + xhr.overrideMimeType('text/plain'); + } + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + if (xhr.status === 0 || xhr.status === 200) { + run(xhr.responseText); + } else { + throw new Error("Could not load " + url); + } + if (callback) { + return callback(); + } + } + }; + return xhr.send(null); +}; - // A single base 64 digit can contain 6 bits of data. For the base 64 variable - // length quantities we use in the source map spec, the first bit is the sign, - // the next four bits are the actual value, and the 6th bit is the - // continuation bit. The continuation bit tells us whether there are more - // digits in this value following this digit. - // - // Continuation - // | Sign - // | | - // V V - // 101011 +runScripts = function() { + var scripts = document.getElementsByTagName('script'); + scripts = Array.prototype.slice.call(scripts); + var jsxScripts = scripts.filter(function(script) { + return script.type === 'text/jsx'; + }); - var VLQ_BASE_SHIFT = 5; + jsxScripts.forEach(function(script) { + if (script.src) { + load(script.src); + } else { + run(script.innerHTML); + } + }); +}; - // binary: 100000 - var VLQ_BASE = 1 << VLQ_BASE_SHIFT; +if (window.addEventListener) { + window.addEventListener('DOMContentLoaded', runScripts, false); +} else { + window.attachEvent('onload', runScripts); +} - // binary: 011111 - var VLQ_BASE_MASK = VLQ_BASE - 1; +},{"./fbtransform/lib/docblock":16,"./fbtransform/lib/transform":17,"./fbtransform/visitors":23}],16:[function(require,module,exports){ +/** + * 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. + * 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. + */ - // binary: 100000 - var VLQ_CONTINUATION_BIT = VLQ_BASE; +var docblockRe = /^\s*(\/\*\*(.|\n)*?\*\/)/; +var ltrimRe = /^\s*/; +/** + * @param {String} contents + * @return {String} + */ +function extract(contents) { + var match = contents.match(docblockRe); + if (match) { + return match[0].replace(ltrimRe, '') || ''; + } + return ''; +} - /** - * Converts from a two-complement value to a value where the sign bit is - * is placed in the least significant bit. For example, as decimals: - * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) - * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) - */ - function toVLQSigned(aValue) { - return aValue < 0 - ? ((-aValue) << 1) + 1 - : (aValue << 1) + 0; + +var commentStartRe = /^\/\*\*?/; +var commentEndRe = /\*\/$/; +var wsRe = /[\t ]+/g; +var stringStartRe = /(\n|^) *\*/g; +var multilineRe = /(?:^|\n) *(@[^\n]*?) *\n *([^@\n\s][^@\n]+?) *\n/g; +var propertyRe = /(?:^|\n) *@(\S+) *([^\n]*)/g; + +/** + * @param {String} contents + * @return {Array} + */ +function parse(docblock) { + docblock = docblock + .replace(commentStartRe, '') + .replace(commentEndRe, '') + .replace(wsRe, ' ') + .replace(stringStartRe, '$1'); + + // Normalize multi-line directives + var prev = ''; + while (prev != docblock) { + prev = docblock; + docblock = docblock.replace(multilineRe, "\n$1 $2\n"); } + docblock = docblock.trim(); - /** - * Converts to a two-complement value from a value where the sign bit is - * is placed in the least significant bit. For example, as decimals: - * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 - * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 - */ - function fromVLQSigned(aValue) { - var isNegative = (aValue & 1) === 1; - var shifted = aValue >> 1; - return isNegative - ? -shifted - : shifted; + var result = []; + var match; + while (match = propertyRe.exec(docblock)) { + result.push([match[1], match[2]]); } - /** - * Returns the base 64 VLQ encoded value. - */ - exports.encode = function base64VLQ_encode(aValue) { - var encoded = ""; - var digit; + return result; +} - var vlq = toVLQSigned(aValue); +/** + * Same as parse but returns an object of prop: value instead of array of paris + * If a property appers more than once the last one will be returned + * + * @param {String} contents + * @return {Object} + */ +function parseAsObject(docblock) { + var pairs = parse(docblock); + var result = {}; + for (var i = 0; i < pairs.length; i++) { + result[pairs[i][0]] = pairs[i][1]; + } + return result; +} - do { - digit = vlq & VLQ_BASE_MASK; - vlq >>>= VLQ_BASE_SHIFT; - if (vlq > 0) { - // There are still more digits in this value, so we must make sure the - // continuation bit is marked. - digit |= VLQ_CONTINUATION_BIT; - } - encoded += base64.encode(digit); - } while (vlq > 0); - return encoded; - }; +exports.extract = extract; +exports.parse = parse; +exports.parseAsObject = parseAsObject; - /** - * Decodes the next base 64 VLQ value from the given string and returns the - * value and the rest of the string. - */ - exports.decode = function base64VLQ_decode(aStr) { - var i = 0; - var strLen = aStr.length; - var result = 0; - var shift = 0; - var continuation, digit; +},{}],17:[function(require,module,exports){ +(function(){/** + * 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. + * 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. + */ +/*global exports:true*/ +/*jslint node: true*/ +"use strict"; - do { - if (i >= strLen) { - throw new Error("Expected more digits in base 64 VLQ value."); +/** + * Syntax transfomer for javascript. Takes the source in, spits the source + * out. Tries to maintain readability and preserve whitespace and line numbers + * where posssible. + * + * Support + * - ES6 class transformation + private property munging, see ./classes.js + * - React XHP style syntax transformations, see ./react.js + * - Bolt XHP style syntax transformations, see ./bolt.js + * + * The general flow is the following: + * - Parse the source with our customized esprima-parser + * https://github.com/voloko/esprima. We have to customize the parser to + * support non-standard XHP-style syntax. We parse the source range: true + * option that forces esprima to return positions in the source within + * resulting parse tree. + * + * - Traverse resulting syntax tree, trying to apply a set of visitors to each + * node. Each visitor should provide a .test() function that tests if the + * visitor can process a given node. + * + * - Visitor is responsible for code generation for a given syntax node. + * Generated code is stored in state.g.buffer that is passed to every + * visitor. It's up to the visitor to process the code the way it sees fit. + * All of the current visitors however use both the node and the original + * source to generate transformed code. They use nodes to generate new + * code and they copy the original source, preserving whitespace and comments, + * for the parts they don't care about. + */ +var esprima = require('esprima'); + +var createState = require('./utils').createState; +var catchup = require('./utils').catchup; + +/** + * @param {object} object + * @param {function} visitor + * @param {array} path + * @param {object} state + */ +function traverse(object, path, state) { + var key, child; + + if (walker(traverse, object, path, state) === false) { + return; + } + path.unshift(object); + for (key in object) { + // skip obviously wrong attributes + if (key === 'range' || key === 'loc') { + continue; + } + if (object.hasOwnProperty(key)) { + child = object[key]; + if (typeof child === 'object' && child !== null) { + child.range && catchup(child.range[0], state); + traverse(child, path, state); + child.range && catchup(child.range[1], state); } - digit = base64.decode(aStr.charAt(i++)); - continuation = !!(digit & VLQ_CONTINUATION_BIT); - digit &= VLQ_BASE_MASK; - result = result + (digit << shift); - shift += VLQ_BASE_SHIFT; - } while (continuation); + } + } + path.shift(); +} +function walker(traverse, object, path, state) { + var visitors = state.g.visitors; + for (var i = 0; i < visitors.length; i++) { + if (visitors[i].test(object, path, state)) { + return visitors[i](traverse, object, path, state); + } + } +} + +function runPass(source, visitors, options) { + var ast; + try { + ast = esprima.parse(source, { comment: true, loc: true, range: true }); + } catch (e) { + e.message = 'Parse Error: ' + e.message; + throw e; + } + var state = createState(source, options); + state.g.originalProgramAST = ast; + state.g.visitors = visitors; + + if (options.sourceMap) { + var SourceMapGenerator = require('source-map').SourceMapGenerator; + state.g.sourceMap = new SourceMapGenerator({ file: 'transformed.js' }); + } + traverse(ast, [], state); + catchup(source.length, state); + return state; +} + +/** + * Applies all available transformations to the source + * @param {array} visitors + * @param {string} source + * @param {?object} options + * @return {object} + */ +function transform(visitors, source, options) { + options = options || {}; + + var state = runPass(source, visitors, options); + var sourceMap = state.g.sourceMap; + + if (sourceMap) { return { - value: fromVLQSigned(result), - rest: aStr.slice(i) + sourceMap: sourceMap, + sourceMapFilename: options.filename || 'source.js', + code: state.g.buffer }; - }; + } else { + return { + code: state.g.buffer + }; + } +} -}); -},{"./base64":23,"amdefine":19}],22:[function(require,module,exports){ -(function(process){function filter (xs, fn) { - var res = []; - for (var i = 0; i < xs.length; i++) { - if (fn(xs[i], i, xs)) res.push(xs[i]); +exports.transform = transform; + +})() +},{"./utils":18,"esprima":4,"source-map":5}],18:[function(require,module,exports){ +(function(){/** + * 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. + * 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. + */ +/*global exports:true*/ + +/** + * State represents the given parser state. It has a local and global parts. + * Global contains parser position, source, etc. Local contains scope based + * properties, like current class name. State should contain all the info + * required for transformation. It's the only mandatory object that is being + * passed to every function in transform chain. + * + * @param {String} source + * @param {Object} transformOptions + * @return {Object} + */ +function createState(source, transformOptions) { + return { + /** + * Name of the super class variable + * @type {String} + */ + superVar: '', + /** + * Name of the enclosing class scope + * @type {String} + */ + scopeName: '', + /** + * Global state (not affected by updateState) + * @type {Object} + */ + g: { + /** + * A set of general options that transformations can consider while doing + * a transformation: + * + * - minify + * Specifies that transformation steps should do their best to minify + * the output source when possible. This is useful for places where + * minification optimizations are possible with higher-level context + * info than what jsxmin can provide. + * + * For example, the ES6 class transform will minify munged private + * variables if this flag is set. + */ + opts: transformOptions, + /** + * Current position in the source code + * @type {Number} + */ + position: 0, + /** + * Buffer containing the result + * @type {String} + */ + buffer: '', + /** + * Indentation offset (only negative offset is supported now) + * @type {Number} + */ + indentBy: 0, + /** + * Source that is being transformed + * @type {String} + */ + source: source, + + /** + * Cached parsed docblock (see getDocblock) + * @type {object} + */ + docblock: null, + + /** + * Whether the thing was used + * @type {Boolean} + */ + tagNamespaceUsed: false, + + /** + * If using bolt xjs transformation + * @type {Boolean} + */ + isBolt: undefined, + + /** + * Whether to record source map (expensive) or not + * @type {SourceMapGenerator|null} + */ + sourceMap: null, + + /** + * Filename of the file being processed. Will be returned as a source + * attribute in the source map + */ + sourceMapFilename: 'source.js', + + /** + * Only when source map is used: last line in the source for which + * source map was generated + * @type {Number} + */ + sourceLine: 1, + + /** + * Only when source map is used: last line in the buffer for which + * source map was generated + * @type {Number} + */ + bufferLine: 1, + + /** + * The top-level Program AST for the original file. + */ + originalProgramAST: null, + + sourceColumn: 0, + bufferColumn: 0 } - return res; + }; } -// resolves . and .. elements in a path array with directory names there -// must be no slashes, empty elements, or device names (c:\) in the array -// (so also no leading and trailing slashes - it does not distinguish -// relative and absolute paths) -function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length; i >= 0; i--) { - var last = parts[i]; - if (last == '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } +/** + * Updates a copy of a given state with "update" and returns an updated state. + * + * @param {Object} state + * @param {Object} update + * @return {Object} + */ +function updateState(state, update) { + return { + g: state.g, + superVar: update.superVar || state.superVar, + scopeName: update.scopeName || state.scopeName + }; +} + +/** + * Given a state fill the resulting buffer from the original source up to + * the end + * @param {Number} end + * @param {Object} state + * @param {Function?} contentTransformer Optional callback to transform newly + * added content. + */ +function catchup(end, state, contentTransformer) { + if (end < state.g.position) { + // cannot move backwards + return; } + var source = state.g.source.substring(state.g.position, end); + var transformed = updateIndent(source, state); + if (state.g.sourceMap && transformed) { + // record where we are + state.g.sourceMap.addMapping({ + generated: { line: state.g.bufferLine, column: state.g.bufferColumn }, + original: { line: state.g.sourceLine, column: state.g.sourceColumn }, + source: state.g.sourceMapFilename + }); - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); + // record line breaks in transformed source + var sourceLines = source.split('\n'); + var transformedLines = transformed.split('\n'); + // Add line break mappings between last known mapping and the end of the + // added piece. So for the code piece + // (foo, bar); + // > var x = 2; + // > var b = 3; + // var c = + // only add lines marked with ">": 2, 3. + for (var i = 1; i < sourceLines.length - 1; i++) { + state.g.sourceMap.addMapping({ + generated: { line: state.g.bufferLine, column: 0 }, + original: { line: state.g.sourceLine, column: 0 }, + source: state.g.sourceMapFilename + }); + state.g.sourceLine++; + state.g.bufferLine++; } + // offset for the last piece + if (sourceLines.length > 1) { + state.g.sourceLine++; + state.g.bufferLine++; + state.g.sourceColumn = 0; + state.g.bufferColumn = 0; + } + state.g.sourceColumn += sourceLines[sourceLines.length - 1].length; + state.g.bufferColumn += + transformedLines[transformedLines.length - 1].length; } + state.g.buffer += + contentTransformer ? contentTransformer(transformed) : transformed; + state.g.position = end; +} - return parts; +/** + * Applies `catchup` but passing in a function that removes any non-whitespace + * characters. + */ +var re = /(\S)/g; +function stripNonWhite(value) { + return value.replace(re, function() { + return ''; + }); } +/** + * Catches up as `catchup` but turns each non-white character into a space. + */ +function catchupWhiteSpace(end, state) { + catchup(end, state, stripNonWhite); +} -// Regex to split a filename into [*, dir, basename, ext] -// posix version -var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/; +/** + * Same as catchup but does not touch the buffer + * @param {Number} end + * @param {Object} state + */ +function move(end, state) { + // move the internal cursors + if (state.g.sourceMap) { + if (end < state.g.position) { + state.g.position = 0; + state.g.sourceLine = 1; + state.g.sourceColumn = 0; + } -// path.resolve([from ...], to) -// posix version -exports.resolve = function() { -var resolvedPath = '', - resolvedAbsolute = false; + var source = state.g.source.substring(state.g.position, end); + var sourceLines = source.split('\n'); + if (sourceLines.length > 1) { + state.g.sourceLine += sourceLines.length - 1; + state.g.sourceColumn = 0; + } + state.g.sourceColumn += sourceLines[sourceLines.length - 1].length; + } + state.g.position = end; +} -for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) - ? arguments[i] - : process.cwd(); +/** + * Appends a string of text to the buffer + * @param {String} string + * @param {Object} state + */ +function append(string, state) { + if (state.g.sourceMap && string) { + state.g.sourceMap.addMapping({ + generated: { line: state.g.bufferLine, column: state.g.bufferColumn }, + original: { line: state.g.sourceLine, column: state.g.sourceColumn }, + source: state.g.sourceMapFilename + }); + var transformedLines = string.split('\n'); + if (transformedLines.length > 1) { + state.g.bufferLine += transformedLines.length - 1; + state.g.bufferColumn = 0; + } + state.g.bufferColumn += + transformedLines[transformedLines.length - 1].length; + } + state.g.buffer += string; +} - // Skip empty and invalid entries - if (typeof path !== 'string' || !path) { - continue; +/** + * Update indent using state.indentBy property. Indent is measured in + * double spaces. Updates a single line only. + * + * @param {String} str + * @param {Object} state + * @return {String} + */ +function updateIndent(str, state) { + for (var i = 0; i < -state.g.indentBy; i++) { + str = str.replace(/(^|\n)( {2}|\t)/g, '$1'); } + return str; +} - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; +/** + * Calculates indent from the beginning of the line until "start" or the first + * character before start. + * @example + * " foo.bar()" + * ^ + * start + * indent will be 2 + * + * @param {Number} start + * @param {Object} state + * @return {Number} + */ +function indentBefore(start, state) { + var end = start; + start = start - 1; + + while (start > 0 && state.g.source[start] != '\n') { + if (!state.g.source[start].match(/[ \t]/)) { + end = start; + } + start--; + } + return state.g.source.substring(start + 1, end); } -// At this point the path should be resolved to a full absolute path, but -// handle relative paths to be safe (might happen when process.cwd() fails) +function getDocblock(state) { + if (!state.g.docblock) { + var docblock = require('./docblock'); + state.g.docblock = + docblock.parseAsObject(docblock.extract(state.g.source)); + } + return state.g.docblock; +} -// Normalize the path -resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); +exports.catchup = catchup; +exports.catchupWhiteSpace = catchupWhiteSpace; +exports.append = append; +exports.move = move; +exports.updateIndent = updateIndent; +exports.indentBefore = indentBefore; +exports.updateState = updateState; +exports.createState = createState; +exports.getDocblock = getDocblock; - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; -}; +})() +},{"./docblock":16}],19:[function(require,module,exports){ +(function(){/** + * 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. + * 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. + */ +/*global exports:true*/ +"use strict"; -// path.normalize(path) -// posix version -exports.normalize = function(path) { -var isAbsolute = path.charAt(0) === '/', - trailingSlash = path.slice(-1) === '/'; +/** + * Desugarizer for ES6 minimal class proposal. See + * http://wiki.ecmascript.org/doku.php?id=harmony:proposals + * + * Does not require any runtime. Preserves whitespace and comments. + * Supports a class declaration with methods, super calls and inheritance. + * Currently does not support for getters and setters, since there's a very + * low probability we're going to use them anytime soon. + * + * Additional features: + * - Any member with private name (the name with prefix _, such _name) inside + * the class's scope will be munged. This would will to eliminate the case + * of sub-class accidentally overriding the super-class's provate properties + * also discouage people from accessing private members that they should not + * access. However, quoted property names don't get munged. + * + * class SkinnedMesh extends require('THREE').Mesh { + * + * update(camera) { + * camera.code = 'iphone' + * super.update(camera); + * } + * + * / + * * @constructor + * / + * constructor(geometry, materials) { + * super(geometry, materials); + * + * super.update(1); + * + * this.identityMatrix = new THREE.Matrix4(); + * this.bones = []; + * this.boneMatrices = []; + * this._name = 'foo'; + * } + * + * / + * * some other code + * / + * readMore() { + * + * } + * + * _doSomething() { + * + * } + * } + * + * should be converted to + * + * var SkinnedMesh = (function() { + * var __super = require('parent').Mesh; + * + * / + * * @constructor + * / + * function SkinnedMesh(geometry, materials) { + * __super.call(this, geometry, materials); + * + * __super.prototype.update.call(this, 1); + * + * this.identityMatrix = new THREE.Matrix4(); + * this.bones = []; + * this.boneMatrices = []; + * this.$SkinnedMesh_name = 'foo'; + * } + * SkinnedMesh.prototype = Object.create(__super.prototype); + * SkinnedMesh.prototype.constructor = SkinnedMesh; + * + * / + * * @param camera + * / + * SkinnedMesh.prototype.update = function(camera) { + * camera.code = 'iphone' + * __super.prototype.update.call(this, camera); + * }; + * + * SkinnedMesh.prototype.readMore = function() { + * + * }; + * + * SkinnedMesh.prototype.$SkinnedMesh_doSomething = function() { + * + * }; + * + * return SkinnedMesh; + * })(); + * + */ +var Syntax = require('esprima').Syntax; +var base62 = require('base62'); -// Normalize the path -path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isAbsolute).join('/'); +var catchup = require('../lib/utils').catchup; +var append = require('../lib/utils').append; +var move = require('../lib/utils').move; +var indentBefore = require('../lib/utils').indentBefore; +var updateIndent = require('../lib/utils').updateIndent; +var updateState = require('../lib/utils').updateState; - if (!path && !isAbsolute) { - path = '.'; +function findConstructorIndex(object) { + var classElements = object.body && object.body.body || []; + for (var i = 0; i < classElements.length; i++) { + if (classElements[i].type === Syntax.MethodDefinition && + classElements[i].key.name === 'constructor') { + return i; + } } - if (path && trailingSlash) { - path += '/'; + return -1; +} + +var _mungedSymbolMaps = {}; +function getMungedName(scopeName, name, minify) { + if (minify) { + if (!_mungedSymbolMaps[scopeName]) { + _mungedSymbolMaps[scopeName] = { + symbolMap: {}, + identifierUUIDCounter: 0 + }; + } + + var symbolMap = _mungedSymbolMaps[scopeName].symbolMap; + if (!symbolMap[name]) { + symbolMap[name] = + base62.encode(_mungedSymbolMaps[scopeName].identifierUUIDCounter); + _mungedSymbolMaps[scopeName].identifierUUIDCounter++; + } + name = symbolMap[name]; } - - return (isAbsolute ? '/' : '') + path; -}; + return '$' + scopeName + name; +} +function shouldMungeName(scopeName, name, state) { + // only run when @preventMunge is not present in the docblock + if (state.g.preventMunge === undefined) { + var docblock = require('../lib/docblock'); + state.g.preventMunge = docblock.parseAsObject( + docblock.extract(state.g.source)).preventMunge !== undefined; + } + // Starts with only a single underscore (i.e. don't count double-underscores) + return !state.g.preventMunge && scopeName ? /^_(?!_)/.test(name) : false; +} -// posix version -exports.join = function() { - var paths = Array.prototype.slice.call(arguments, 0); - return exports.normalize(filter(paths, function(p, index) { - return p && typeof p === 'string'; - }).join('/')); -}; +function getProtoOfPrototypeVariableName(superVar) { + return superVar + 'ProtoOfPrototype'; +} -exports.dirname = function(path) { - var dir = splitPathRe.exec(path)[1] || ''; - var isWindows = false; - if (!dir) { - // No dirname - return '.'; - } else if (dir.length === 1 || - (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) { - // It is just a slash or a drive letter with a slash - return dir; - } else { - // It is a full dirname, strip trailing slash - return dir.substring(0, dir.length - 1); +function getSuperKeyName(superVar) { + return superVar + 'Key'; +} + +function getSuperProtoOfPrototypeVariable(superVariableName, indent) { + var string = (indent + + 'var $proto = $superName && $superName.prototype ? ' + + '$superName.prototype : $superName;\n' + ).replace(/\$proto/g, getProtoOfPrototypeVariableName(superVariableName)) + .replace(/\$superName/g, superVariableName); + return string; +} + + +function getInheritanceSetup(superClassToken, className, indent, superName) { + var string = ''; + if (superClassToken) { + string += getStaticMethodsOnConstructorSetup(className, indent, superName); + string += getPrototypeOnConstructorSetup(className, indent, superName); + string += getConstructorPropertySetup(className, indent); } -}; + return string; +} +function getStaticMethodsOnConstructorSetup(className, indent, superName) { + var string = ( indent + + 'for (var $keyName in $superName) {\n' + indent + + ' if ($superName.hasOwnProperty($keyName)) {\n' + indent + + ' $className[$keyName] = $superName[$keyName];\n' + indent + + ' }\n' + indent + + '}\n') + .replace(/\$className/g, className) + .replace(/\$keyName/g, getSuperKeyName(superName)) + .replace(/\$superName/g, superName); + return string; +} -exports.basename = function(path, ext) { - var f = splitPathRe.exec(path)[2] || ''; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); +function getPrototypeOnConstructorSetup(className, indent, superName) { + var string = ( indent + + '$className.prototype = Object.create($protoPrototype);\n') + .replace(/\$protoPrototype/g, getProtoOfPrototypeVariableName(superName)) + .replace(/\$className/g, className); + return string; +} + +function getConstructorPropertySetup(className, indent) { + var string = ( indent + + '$className.prototype.constructor = $className;\n') + .replace(/\$className/g, className); + + return string; +} + +function getSuperConstructorSetup(superClassToken, indent, superName) { + if (!superClassToken) return ''; + var string = ( '\n' + indent + + ' if ($superName && $superName.prototype) {\n' + indent + + ' $superName.apply(this, arguments);\n' + indent + + ' }\n' + indent) + .replace(/\$superName/g, superName); + return string; +} + +function getMemberFunctionCall(superVar, propertyName, superArgs) { + var string = ( + '$superPrototype.$propertyName.call($superArguments)') + .replace(/\$superPrototype/g, getProtoOfPrototypeVariableName(superVar)) + .replace(/\$propertyName/g, propertyName) + .replace(/\$superArguments/g, superArgs); + return string; +} + +function getCallParams(classElement, state) { + var params = classElement.value.params; + if (!params.length) { + return ''; } - return f; -}; + return state.g.source.substring( + params[0].range[0], + params[params.length - 1].range[1]); +} +function getSuperArguments(callExpression, state) { + var args = callExpression.arguments; + if (!args.length) { + return 'this'; + } + return 'this, ' + state.g.source.substring( + args[0].range[0], + args[args.length - 1].range[1]); +} -exports.extname = function(path) { - return splitPathRe.exec(path)[3] || ''; -}; +// The seed is used to generate the name for an anonymous class, +// and this seed should be unique per browser's session. +// The value of the seed looks like this: 1229588505.2969012. +var classIDSeed = Date.now() % (60 * 60 * 1000) + Math.random(); -exports.relative = function(from, to) { - from = exports.resolve(from).substr(1); - to = exports.resolve(to).substr(1); +/** + * Generates a name for an anonymous class. The generated value looks like + * this: "Classkc6pcn_mniza1yvi" + * @param {String} scopeName + * @return {string} the scope name for Anonymous Class + */ +function generateAnonymousClassName(scopeName) { + classIDSeed++; + return 'Class' + + (classIDSeed).toString(36).replace('.', '_') + + (scopeName || ''); +} - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } +function renderMethods(traverse, object, name, path, state) { + var classElements = object.body && object.body.body || []; - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } + move(object.body.range[0] + 1, state); + for (var i = 0; i < classElements.length; i++) { + if (classElements[i].key.name !== 'constructor') { + catchup(classElements[i].range[0], state); - if (start > end) return []; - return arr.slice(start, end - start + 1); + var memberName = classElements[i].key.name; + if (shouldMungeName(state.scopeName, memberName, state)) { + memberName = getMungedName( + state.scopeName, + memberName, + state.g.opts.minify + ); + } + + var prototypeOrStatic; + if (classElements[i]['static']) { + prototypeOrStatic = ''; + } else { + prototypeOrStatic = 'prototype.'; + } + + append(name + '.' + prototypeOrStatic + memberName + ' = ', state); + renderMethod(traverse, classElements[i], null, path, state); + append(';', state); + } + move(classElements[i].range[1], state); } + if (classElements.length) { + append('\n', state); + } + move(object.range[1], state); +} - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); +function renderMethod(traverse, method, name, path, state) { + append(name ? 'function ' + name + '(' : 'function(', state); + append(getCallParams(method, state) + ') {', state); + move(method.value.body.range[0] + 1, state); + traverse(method.value.body, path, state); + catchup(method.value.body.range[1] - 1, state); + append('}', state); +} - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; +function renderSuperClass(traverse, superClass, path, state) { + append('var ' + state.superVar + ' = ', state); + move(superClass.range[0], state); + traverse(superClass, path, state); + catchup(superClass.range[1], state); + append(';\n', state); +} + +function renderConstructor(traverse, object, name, indent, path, state) { + var classElements = object.body && object.body.body || []; + var constructorIndex = findConstructorIndex(object); + var constructor = constructorIndex === -1 ? + null : + classElements[constructorIndex]; + if (constructor) { + move(constructorIndex === 0 ? + object.body.range[0] + 1 : + classElements[constructorIndex - 1].range[1], state); + catchup(constructor.range[0], state); + renderMethod(traverse, constructor, name, path, state); + append('\n', state); + } else { + if (object.superClass) { + append('\n' + indent, state); } + append('function ', state); + if (object.id) { + move(object.id.range[0], state); + } + append(name, state); + if (object.id) { + move(object.id.range[1], state); + } + append('(){ ', state); + if (object.body) { + move(object.body.range[0], state); + } + append(getSuperConstructorSetup( + object.superClass, + indent, + state.superVar), state); + append('}\n', state); } +} - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); +var superId = 0; +function renderClassBody(traverse, object, path, state) { + var name = object.id ? object.id.name : 'constructor'; + var superClass = object.superClass; + var indent = updateIndent( + indentBefore(object.range[0], state) + ' ', + state); + + state = updateState( + state, + { + scopeName: object.id ? object.id.name : + generateAnonymousClassName(state.scopeName), + superVar: superClass ? '__super' + superId++ : '' + }); + + // super class + if (superClass) { + append(indent, state); + renderSuperClass(traverse, superClass, path, state); + append(getSuperProtoOfPrototypeVariable(state.superVar, indent), state); } - outputParts = outputParts.concat(toParts.slice(samePartsLength)); + renderConstructor(traverse, object, name, indent, path, state); + append(getInheritanceSetup(superClass, name, indent, state.superVar), state); + renderMethods(traverse, object, name, path, state); +} - return outputParts.join('/'); + +/** + * @public + */ +function visitClassExpression(traverse, object, path, state) { + var indent = updateIndent( + indentBefore(object.range[0], state) + ' ', + state); + var name = object.id ? object.id.name : 'constructor'; + + append('(function() {\n', state); + renderClassBody(traverse, object, path, state); + append(indent + 'return ' + name + ';\n', state); + append(indent.substring(0, indent.length - 2) + '})()', state); + return false +} + +visitClassExpression.test = function(object, path, state) { + return object.type === Syntax.ClassExpression; }; -})(require("__browserify_process")) -},{"__browserify_process":21}],17:[function(require,module,exports){ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause +/** + * @public */ -if (typeof define !== 'function') { - var define = require('amdefine')(module); +function visitClassDeclaration(traverse, object, path, state) { + state.g.indentBy--; + renderClassBody(traverse, object, path, state); + state.g.indentBy++; + return false; } -define(function (require, exports, module) { - /** - * This is a helper function for getting values from parameter/options - * objects. - * - * @param args The object we are extracting values from - * @param name The name of the property we are getting. - * @param defaultValue An optional value to return if the property is missing - * from the object. If this is not specified and the property is missing, an - * error will be thrown. - */ - function getArg(aArgs, aName, aDefaultValue) { - if (aName in aArgs) { - return aArgs[aName]; - } else if (arguments.length === 3) { - return aDefaultValue; +visitClassDeclaration.test = function(object, path, state) { + return object.type === Syntax.ClassDeclaration; +}; + + +/** + * @public + */ +function visitSuperCall(traverse, object, path, state) { + if (path[0].type === Syntax.CallExpression) { + append(state.superVar + + '.call(' + getSuperArguments(path[0], state) + ')', state); + move(path[0].range[1], state); + } else if (path[0].type === Syntax.MemberExpression) { + append(getMemberFunctionCall( + state.superVar, + path[0].property.name, + getSuperArguments(path[1], state)), state); + move(path[1].range[1], state); + } + return false; +} + +visitSuperCall.test = function(object, path, state) { + return state.superVar && object.type === Syntax.Identifier && + object.name === 'super'; +}; + +/** + * @public + */ +function visitPrivateProperty(traverse, object, path, state) { + var type = path[0] ? path[0].type : null; + if (type !== Syntax.Property) { + if (type === Syntax.MemberExpression) { + type = path[0].object ? path[0].object.type : null; + if (type === Syntax.Identifier && + path[0].object.range[0] === object.range[0]) { + // Identifier is a variable that appears "private". + return; + } } else { - throw new Error('"' + aName + '" is a required argument.'); + // Other syntax that are neither Property nor MemberExpression. + return; } } - exports.getArg = getArg; - var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/; + var oldName = object.name; + var newName = getMungedName( + state.scopeName, + oldName, + state.g.opts.minify + ); + append(newName, state); + move(object.range[1], state); +} - function urlParse(aUrl) { - var match = aUrl.match(urlRegexp); - if (!match) { - return null; +visitPrivateProperty.test = function(object, path, state) { + return object.type === Syntax.Identifier && + shouldMungeName(state.scopeName, object.name, state); +}; + + +exports.visitClassDeclaration = visitClassDeclaration; +exports.visitClassExpression = visitClassExpression; +exports.visitSuperCall = visitSuperCall; +exports.visitPrivateProperty = visitPrivateProperty; + +})() +},{"../lib/docblock":16,"../lib/utils":18,"base62":1,"esprima":4}],20:[function(require,module,exports){ +(function(){/** + * 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. + * 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. + */ +/*global exports:true*/ +"use strict"; + +var Syntax = require('esprima').Syntax; + +var catchup = require('../lib/utils').catchup; +var append = require('../lib/utils').append; +var move = require('../lib/utils').move; +var getDocblock = require('../lib/utils').getDocblock; + +var FALLBACK_TAGS = require('./xjs').knownTags; +var renderXJSExpressionContainer = + require('./xjs').renderXJSExpressionContainer; +var renderXJSLiteral = require('./xjs').renderXJSLiteral; +var quoteAttrName = require('./xjs').quoteAttrName; + +/** + * 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)]) + * + * 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. + */ + +var JSX_ATTRIBUTE_RENAMES = { + 'class': 'className', + cxName: 'className' +}; + +var JSX_ATTRIBUTE_TRANSFORMS = { + cxName: function(attr) { + if (attr.value.type !== Syntax.Literal) { + throw new Error("cx only accepts a string literal"); + } else { + var classNames = attr.value.value.split(/\s+/g); + return 'cx(' + classNames.map(JSON.stringify).join(',') + ')'; } - return { - scheme: match[1], - auth: match[3], - host: match[4], - port: match[6], - path: match[7] - }; } - exports.urlParse = urlParse; +}; - function urlGenerate(aParsedUrl) { - var url = aParsedUrl.scheme + "://"; - if (aParsedUrl.auth) { - url += aParsedUrl.auth + "@" +function visitReactTag(traverse, object, path, state) { + var jsxObjIdent = getDocblock(state).jsx; + + catchup(object.openingElement.range[0], state); + + if (object.name.namespace) { + throw new Error( + 'Namespace tags are not supported. ReactJSX is not XML.'); + } + + var isFallbackTag = FALLBACK_TAGS[object.name.name]; + append( + (isFallbackTag ? jsxObjIdent + '.' : '') + (object.name.name) + '(', + state + ); + + move(object.name.range[1], state); + + var childrenToRender = object.children.filter(function(child) { + return !(child.type === Syntax.Literal && !child.value.match(/\S/)); + }); + + // if we don't have any attributes, pass in null + if (object.attributes.length === 0) { + append('null', state); + } + + // write attributes + object.attributes.forEach(function(attr, index) { + catchup(attr.range[0], state); + if (attr.name.namespace) { + throw new Error( + 'Namespace attributes are not supported. ReactJSX is not XML.'); } - if (aParsedUrl.host) { - url += aParsedUrl.host; + var name = JSX_ATTRIBUTE_RENAMES[attr.name.name] || attr.name.name; + var isFirst = index === 0; + var isLast = index === object.attributes.length - 1; + + if (isFirst) { + append('{', state); } - if (aParsedUrl.port) { - url += ":" + aParsedUrl.port - } - if (aParsedUrl.path) { - url += aParsedUrl.path; - } - return url; - } - exports.urlGenerate = urlGenerate; - function join(aRoot, aPath) { - var url; + append(quoteAttrName(name), state); + append(':', state); - if (aPath.match(urlRegexp)) { - return aPath; + if (!attr.value) { + state.g.buffer += 'true'; + state.g.position = attr.name.range[1]; + if (!isLast) { + append(',', state); + } + } else if (JSX_ATTRIBUTE_TRANSFORMS[attr.name.name]) { + move(attr.value.range[0], state); + append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state); + move(attr.value.range[1], state); + if (!isLast) { + append(',', state); + } + } else if (attr.value.type === Syntax.Literal) { + move(attr.value.range[0], state); + renderXJSLiteral(attr.value, isLast, state); + } else { + move(attr.value.range[0], state); + renderXJSExpressionContainer(traverse, attr.value, isLast, path, state); } - if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) { - url.path = aPath; - return urlGenerate(url); + if (isLast) { + append('}', state); } - return aRoot.replace(/\/$/, '') + '/' + aPath; + catchup(attr.range[1], state); + }); + + if (!object.selfClosing) { + catchup(object.openingElement.range[1] - 1, state); + move(object.openingElement.range[1], state); } - exports.join = join; - /** - * Because behavior goes wacky when you set `__proto__` on objects, we - * have to prefix all the strings in our set with an arbitrary character. - * - * See https://github.com/mozilla/source-map/pull/31 and - * https://github.com/mozilla/source-map/issues/30 - * - * @param String aStr - */ - function toSetString(aStr) { - return '$' + aStr; + // filter out whitespace + if (childrenToRender.length > 0) { + append(', ', state); + + object.children.forEach(function(child) { + if (child.type === Syntax.Literal && !child.value.match(/\S/)) { + return; + } + catchup(child.range[0], state); + + var isLast = child === childrenToRender[childrenToRender.length - 1]; + + if (child.type === Syntax.Literal) { + renderXJSLiteral(child, isLast, state); + } else if (child.type === Syntax.XJSExpressionContainer) { + renderXJSExpressionContainer(traverse, child, isLast, path, state); + } else { + traverse(child, path, state); + if (!isLast) { + append(',', state); + state.g.buffer = state.g.buffer.replace(/(\s*),$/, ',$1'); + } + } + + catchup(child.range[1], state); + }); } - exports.toSetString = toSetString; - function fromSetString(aStr) { - return aStr.substr(1); + if (object.selfClosing) { + // everything up to /> + catchup(object.openingElement.range[1] - 2, state); + move(object.openingElement.range[1], state); + } else { + // everything up to </ sdflksjfd> + catchup(object.closingElement.range[0], state); + move(object.closingElement.range[1], state); } - exports.fromSetString = fromSetString; - function relative(aRoot, aPath) { - aRoot = aRoot.replace(/\/$/, ''); + append(')', state); + return false; +} - var url = urlParse(aRoot); - if (aPath.charAt(0) == "/" && url && url.path == "/") { - return aPath.slice(1); - } +visitReactTag.test = function(object, path, state) { + // only run react when react @jsx namespace is specified in docblock + var jsx = getDocblock(state).jsx; + return object.type === Syntax.XJSElement && jsx && jsx.length; +}; - return aPath.indexOf(aRoot + '/') === 0 - ? aPath.substr(aRoot.length + 1) - : aPath; - } - exports.relative = relative; +exports.visitReactTag = visitReactTag; -}); +})() +},{"../lib/utils":18,"./xjs":22,"esprima":4}],21:[function(require,module,exports){ +(function(){/** + * 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. + * 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. + */ +/*global exports:true*/ +"use strict"; -},{"amdefine":19}],18:[function(require,module,exports){ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause +var Syntax = require('esprima').Syntax; +var catchup = require('../lib/utils').catchup; +var append = require('../lib/utils').append; +var getDocblock = require('../lib/utils').getDocblock; + +/** + * Transforms the following: + * + * var MyComponent = React.createClass({ + * render: ... + * }); + * + * into: + * + * var MyComponent = React.createClass({ + * displayName: 'MyComponent', + * render: ... + * }); */ -if (typeof define !== 'function') { - var define = require('amdefine')(module); +function visitReactDisplayName(traverse, object, path, state) { + if (object.id.type === Syntax.Identifier && + object.init && + object.init.type === Syntax.CallExpression && + object.init.callee.type === Syntax.MemberExpression && + object.init.callee.object.type === Syntax.Identifier && + object.init.callee.object.name === 'React' && + object.init.callee.property.type === Syntax.Identifier && + object.init.callee.property.name === 'createClass' && + object.init['arguments'].length === 1 && + object.init['arguments'][0].type === Syntax.ObjectExpression) { + + var displayName = object.id.name; + catchup(object.init['arguments'][0].range[0] + 1, state); + append("displayName: '" + displayName + "',", state); + } } -define(function (require, exports, module) { - var util = require('./util'); +/** + * Will only run on @jsx files for now. + */ +visitReactDisplayName.test = function(object, path, state) { + return object.type === Syntax.VariableDeclarator && !!getDocblock(state).jsx; +}; - /** - * A data structure which is a combination of an array and a set. Adding a new - * member is O(1), testing for membership is O(1), and finding the index of an - * element is O(1). Removing elements from the set is not supported. Only - * strings are supported for membership. - */ - function ArraySet() { - this._array = []; - this._set = {}; - } +exports.visitReactDisplayName = visitReactDisplayName; - /** - * Static method for creating ArraySet instances from an existing array. - */ - ArraySet.fromArray = function ArraySet_fromArray(aArray) { - var set = new ArraySet(); - for (var i = 0, len = aArray.length; i < len; i++) { - set.add(aArray[i]); - } - return set; - }; +})() +},{"../lib/utils":18,"esprima":4}],22:[function(require,module,exports){ +(function(){/** + * 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. + * 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. + */ +/*global exports:true*/ +"use strict"; +var append = require('../lib/utils').append; +var catchup = require('../lib/utils').catchup; +var move = require('../lib/utils').move; +var Syntax = require('esprima').Syntax; - /** - * Add the given string to this set. - * - * @param String aStr - */ - ArraySet.prototype.add = function ArraySet_add(aStr) { - if (this.has(aStr)) { - // Already a member; nothing to do. - return; - } - var idx = this._array.length; - this._array.push(aStr); - this._set[util.toSetString(aStr)] = idx; - }; +var knownTags = { + a: true, + abbr: true, + address: true, + applet: true, + area: true, + article: true, + aside: true, + audio: true, + b: true, + base: true, + bdi: true, + bdo: true, + big: true, + blockquote: true, + body: true, + br: true, + button: true, + canvas: true, + caption: true, + circle: true, + cite: true, + code: true, + col: true, + colgroup: true, + command: true, + data: true, + datalist: true, + dd: true, + del: true, + details: true, + dfn: true, + dialog: true, + div: true, + dl: true, + dt: true, + ellipse: true, + em: true, + embed: true, + fieldset: true, + figcaption: true, + figure: true, + footer: true, + form: true, + g: true, + h1: true, + h2: true, + h3: true, + h4: true, + h5: true, + h6: true, + head: true, + header: true, + hgroup: true, + hr: true, + html: true, + i: true, + iframe: true, + img: true, + input: true, + ins: true, + kbd: true, + keygen: true, + label: true, + legend: true, + li: true, + line: true, + link: true, + main: true, + map: true, + mark: true, + marquee: true, + menu: true, + menuitem: true, + meta: true, + meter: true, + nav: true, + noscript: true, + object: true, + ol: true, + optgroup: true, + option: true, + output: true, + p: true, + param: true, + path: true, + polyline: true, + pre: true, + progress: true, + q: true, + rect: true, + rp: true, + rt: true, + ruby: true, + s: true, + samp: true, + script: true, + section: true, + select: true, + small: true, + source: true, + span: true, + strong: true, + style: true, + sub: true, + summary: true, + sup: true, + svg: true, + table: true, + tbody: true, + td: true, + text: true, + textarea: true, + tfoot: true, + th: true, + thead: true, + time: true, + title: true, + tr: true, + track: true, + u: true, + ul: true, + 'var': true, + video: true, + wbr: true +}; - /** - * Is the given string a member of this set? - * - * @param String aStr - */ - ArraySet.prototype.has = function ArraySet_has(aStr) { - return Object.prototype.hasOwnProperty.call(this._set, - util.toSetString(aStr)); - }; +function safeTrim(string) { + return string.replace(/^[ \t]+/, '').replace(/[ \t]+$/, ''); +} - /** - * What is the index of the given string in the array? - * - * @param String aStr - */ - ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { - if (this.has(aStr)) { - return this._set[util.toSetString(aStr)]; - } - throw new Error('"' + aStr + '" is not in the set.'); - }; +// Replace all trailing whitespace characters with a single space character +function trimWithSingleSpace(string) { + return string.replace(/^[ \t\xA0]{2,}/, ' '). + replace(/[ \t\xA0]{2,}$/, ' ').replace(/^\s+$/, ''); +} - /** - * What is the element at the given index? - * - * @param Number aIdx - */ - ArraySet.prototype.at = function ArraySet_at(aIdx) { - if (aIdx >= 0 && aIdx < this._array.length) { - return this._array[aIdx]; +/** + * Special handling for multiline string literals + * print lines: + * + * line + * line + * + * as: + * + * "line "+ + * "line" + */ +function renderXJSLiteral(object, isLast, state, start, end) { + /** Added blank check filtering and triming*/ + var trimmedChildValue = safeTrim(object.value); + + if (trimmedChildValue) { + // head whitespace + append(object.value.match(/^[\t ]*/)[0], state); + if (start) { + append(start, state); } - throw new Error('No element indexed by ' + aIdx); - }; - /** - * Returns the array representation of this set (which has the proper indices - * indicated by indexOf). Note that this is a copy of the internal array used - * for storing the members so that no one can mess with internal state. - */ - ArraySet.prototype.toArray = function ArraySet_toArray() { - return this._array.slice(); - }; + var trimmedChildValueWithSpace = trimWithSingleSpace(object.value); - exports.ArraySet = ArraySet; + /** + */ + var initialLines = trimmedChildValue.split(/\r\n|\n|\r/); -}); + var lines = initialLines.filter(function(line) { + return safeTrim(line).length > 0; + }); -},{"./util":17,"amdefine":19}],20:[function(require,module,exports){ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = require('amdefine')(module); -} -define(function (require, exports, module) { + var hasInitialNewLine = initialLines[0] !== lines[0]; + var hasFinalNewLine = + initialLines[initialLines.length - 1] !== lines[lines.length - 1]; - /** - * Recursive implementation of binary search. - * - * @param aLow Indices here and lower do not contain the needle. - * @param aHigh Indices here and higher do not contain the needle. - * @param aNeedle The element being searched for. - * @param aHaystack The non-empty array being searched. - * @param aCompare Function which takes two elements and returns -1, 0, or 1. - */ - function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { - // This function terminates when one of the following is true: - // - // 1. We find the exact element we are looking for. - // - // 2. We did not find the exact element, but we can return the next - // closest element that is less than that element. - // - // 3. We did not find the exact element, and there is no next-closest - // element which is less than the one we are searching for, so we - // return null. - var mid = Math.floor((aHigh - aLow) / 2) + aLow; - var cmp = aCompare(aNeedle, aHaystack[mid]); - if (cmp === 0) { - // Found the element we are looking for. - return aHaystack[mid]; - } - else if (cmp > 0) { - // aHaystack[mid] is greater than our needle. - if (aHigh - mid > 1) { - // The element is in the upper half. - return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); + var numLines = lines.length; + lines.forEach(function (line, ii) { + var lastLine = ii === numLines - 1; + var trimmedLine = safeTrim(line); + if (trimmedLine === '' && !lastLine) { + append(line, state); + } else { + var preString = ''; + var postString = ''; + var leading = ''; + + if (ii === 0) { + if (hasInitialNewLine) { + preString = ' '; + leading = '\n'; + } + if (trimmedChildValueWithSpace.substring(0, 1) === ' ') { + // If this is the first line, and the original content starts with + // whitespace, place a single space at the beginning. + preString = ' '; + } + } else { + leading = line.match(/^[ \t]*/)[0]; + } + if (!lastLine || trimmedChildValueWithSpace.substr( + trimmedChildValueWithSpace.length - 1, 1) === ' ' || + hasFinalNewLine + ) { + // If either not on the last line, or the original content ends with + // whitespace, place a single character at the end. + postString = ' '; + } + + append( + leading + + JSON.stringify( + preString + trimmedLine + postString + ) + + (lastLine ? '' : '+') + + line.match(/[ \t]*$/)[0], + state); } - // We did not find an exact match, return the next closest one - // (termination case 2). - return aHaystack[mid]; - } - else { - // aHaystack[mid] is less than our needle. - if (mid - aLow > 1) { - // The element is in the lower half. - return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); + if (!lastLine) { + append('\n', state); } - // The exact needle element was not found in this haystack. Determine if - // we are in termination case (2) or (3) and return the appropriate thing. - return aLow < 0 - ? null - : aHaystack[aLow]; + }); + } else { + if (start) { + append(start, state); } + append('""', state); } + if (end) { + append(end, state); + } - /** - * This is an implementation of binary search which will always try and return - * the next lowest value checked if there is no exact hit. This is because - * mappings between original and generated line/col pairs are single points, - * and there is an implicit region between each of them, so a miss just means - * that you aren't on the very start of a region. - * - * @param aNeedle The element you are looking for. - * @param aHaystack The array that is being searched. - * @param aCompare A function which takes the needle and an element in the - * array and returns -1, 0, or 1 depending on whether the needle is less - * than, equal to, or greater than the element, respectively. - */ - exports.search = function search(aNeedle, aHaystack, aCompare) { - return aHaystack.length > 0 - ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) - : null; - }; + // add comma before trailing whitespace + if (!isLast) { + append(',', state); + } -}); + // tail whitespace + append(object.value.match(/[ \t]*$/)[0], state); + move(object.range[1], state); +} -},{"amdefine":19}],23:[function(require,module,exports){ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = require('amdefine')(module); +function renderXJSExpressionContainer(traverse, object, isLast, path, state) { + // Plus 1 to skip `{`. + move(object.range[0] + 1, state); + traverse(object.expression, path, state); + if (!isLast && object.expression.type !== Syntax.XJSEmptyExpression) { + // If we need to append a comma, make sure to do so after the expression. + catchup(object.expression.range[1], state); + append(',', state); + } + + // Minus 1 to skip `}`. + catchup(object.range[1] - 1, state); + move(object.range[1], state); + return false; } -define(function (require, exports, module) { - var charToIntMap = {}; - var intToCharMap = {}; +function quoteAttrName(attr) { + // Quote invalid JS identifiers. + if (!/^[a-z_$][a-z\d_$]*$/i.test(attr)) { + return "'" + attr + "'"; + } + return attr; +} - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' - .split('') - .forEach(function (ch, index) { - charToIntMap[ch] = index; - intToCharMap[index] = ch; - }); +exports.knownTags = knownTags; +exports.renderXJSExpressionContainer = renderXJSExpressionContainer; +exports.renderXJSLiteral = renderXJSLiteral; +exports.quoteAttrName = quoteAttrName; - /** - * Encode an integer in the range of 0 to 63 to a single base 64 digit. - */ - exports.encode = function base64_encode(aNumber) { - if (aNumber in intToCharMap) { - return intToCharMap[aNumber]; - } - throw new TypeError("Must be between 0 and 63: " + aNumber); - }; +})() +},{"../lib/utils":18,"esprima":4}],23:[function(require,module,exports){ +(function(){/*global exports:true*/ +var classes = require('./transforms/classes'); +var react = require('./transforms/react'); +var reactDisplayName = require('./transforms/reactDisplayName'); - /** - * Decode a single base 64 digit to an integer. - */ - exports.decode = function base64_decode(aChar) { - if (aChar in charToIntMap) { - return charToIntMap[aChar]; +/** + * Map from transformName => orderedListOfVisitors. + */ +var transformVisitors = { + 'es6-classes': [ + classes.visitClassExpression, + classes.visitClassDeclaration, + classes.visitSuperCall, + classes.visitPrivateProperty + ] +}; + +transformVisitors.react = transformVisitors[ + "es6-classes" +].concat([ + react.visitReactTag, + reactDisplayName.visitReactDisplayName +]); + +/** + * Specifies the order in which each transform should run. + */ +var transformRunOrder = [ + 'es6-classes', + 'react' +]; + +/** + * Given a list of transform names, return the ordered list of visitors to be + * passed to the transform() function. + * + * @param {array?} excludes + * @return {array} + */ +function getVisitorsList(excludes) { + var ret = []; + for (var i = 0, il = transformRunOrder.length; i < il; i++) { + if (!excludes || excludes.indexOf(transformRunOrder[i]) === -1) { + ret = ret.concat(transformVisitors[transformRunOrder[i]]); } - throw new TypeError("Not a valid base 64 digit: " + aChar); - }; + } + return ret; +} -}); +exports.getVisitorsList = getVisitorsList; +exports.transformVisitors = transformVisitors; -},{"amdefine":19}]},{},[1])(1) +})() +},{"./transforms/classes":19,"./transforms/react":20,"./transforms/reactDisplayName":21}]},{},[15])(15) }); ; \ No newline at end of file