diff options
Diffstat (limited to 'devtools/client/debugger/new')
91 files changed, 74613 insertions, 0 deletions
diff --git a/devtools/client/debugger/new/bundle.js b/devtools/client/debugger/new/bundle.js new file mode 100644 index 000000000..cbbd15a44 --- /dev/null +++ b/devtools/client/debugger/new/bundle.js @@ -0,0 +1,58335 @@ +// Generated from: 8175aacaec380ecf859183ad62bee2a9aef180d2 Disable searching test because it's timing out on try on certain platforms for some reason + +var Debugger = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; +/******/ +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = "/public/build"; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports = __webpack_require__(1); + + +/***/ }, +/* 1 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + + var _require = __webpack_require__(3); + + var bindActionCreators = _require.bindActionCreators; + var combineReducers = _require.combineReducers; + + var ReactDOM = __webpack_require__(16); + + var _require2 = __webpack_require__(18); + + var _require2$client = _require2.client; + var getClient = _require2$client.getClient; + var firefox = _require2$client.firefox; + var renderRoot = _require2.renderRoot; + var bootstrap = _require2.bootstrap; + + var _require3 = __webpack_require__(89); + + var getValue = _require3.getValue; + var isFirefoxPanel = _require3.isFirefoxPanel; + + + var configureStore = __webpack_require__(238); + + var reducers = __webpack_require__(249); + var selectors = __webpack_require__(259); + + var App = __webpack_require__(260); + + var createStore = configureStore({ + log: getValue("logging.actions"), + makeThunkArgs: (args, state) => { + return Object.assign({}, args, { client: getClient(state) }); + } + }); + + var store = createStore(combineReducers(reducers)); + var actions = bindActionCreators(__webpack_require__(262), store.dispatch); + + if (!isFirefoxPanel()) { + L10N.setBundle(__webpack_require__(458)); + } + + window.appStore = store; + + // Expose the bound actions so external things can do things like + // selecting a source. + window.actions = { + selectSource: actions.selectSource, + selectSourceURL: actions.selectSourceURL + }; + + function unmountRoot() { + var mount = document.querySelector("#mount"); + ReactDOM.unmountComponentAtNode(mount); + } + + if (isFirefoxPanel()) { + (function () { + var sourceMap = __webpack_require__(264); + var prettyPrint = __webpack_require__(276); + + module.exports = { + bootstrap: (_ref) => { + var threadClient = _ref.threadClient; + var tabTarget = _ref.tabTarget; + var toolbox = _ref.toolbox; + var L10N = _ref.L10N; + + // TODO (jlast) remove when the panel has L10N + if (L10N) { + window.L10N = L10N; + } else { + window.L10N = __webpack_require__(459); + window.L10N.setBundle(__webpack_require__(458)); + } + + firefox.setThreadClient(threadClient); + firefox.setTabTarget(tabTarget); + renderRoot(React, ReactDOM, App, store); + return firefox.initPage(actions); + }, + destroy: () => { + unmountRoot(); + sourceMap.destroyWorker(); + prettyPrint.destroyWorker(); + }, + store: store, + actions: actions, + selectors: selectors, + client: firefox.clientCommands + }; + })(); + } else { + bootstrap(React, ReactDOM, App, actions, store); + } + +/***/ }, +/* 2 */ +/***/ function(module, exports) { + + module.exports = devtoolsRequire("devtools/client/shared/vendor/react"); + +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + exports.compose = exports.applyMiddleware = exports.bindActionCreators = exports.combineReducers = exports.createStore = undefined; + + var _createStore = __webpack_require__(4); + + var _createStore2 = _interopRequireDefault(_createStore); + + var _combineReducers = __webpack_require__(11); + + var _combineReducers2 = _interopRequireDefault(_combineReducers); + + var _bindActionCreators = __webpack_require__(13); + + var _bindActionCreators2 = _interopRequireDefault(_bindActionCreators); + + var _applyMiddleware = __webpack_require__(14); + + var _applyMiddleware2 = _interopRequireDefault(_applyMiddleware); + + var _compose = __webpack_require__(15); + + var _compose2 = _interopRequireDefault(_compose); + + var _warning = __webpack_require__(12); + + var _warning2 = _interopRequireDefault(_warning); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + + /* + * This is a dummy function to check if the function name has been altered by minification. + * If the function has been minified and NODE_ENV !== 'production', warn the user. + */ + function isCrushed() {} + + if (false) { + (0, _warning2["default"])('You are currently using minified code outside of NODE_ENV === \'production\'. ' + 'This means that you are running a slower development build of Redux. ' + 'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' + 'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' + 'to ensure you have the correct code for your production build.'); + } + + exports.createStore = _createStore2["default"]; + exports.combineReducers = _combineReducers2["default"]; + exports.bindActionCreators = _bindActionCreators2["default"]; + exports.applyMiddleware = _applyMiddleware2["default"]; + exports.compose = _compose2["default"]; + +/***/ }, +/* 4 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + exports.ActionTypes = undefined; + exports["default"] = createStore; + + var _isPlainObject = __webpack_require__(5); + + var _isPlainObject2 = _interopRequireDefault(_isPlainObject); + + var _symbolObservable = __webpack_require__(9); + + var _symbolObservable2 = _interopRequireDefault(_symbolObservable); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + + /** + * These are private action types reserved by Redux. + * For any unknown actions, you must return the current state. + * If the current state is undefined, you must return the initial state. + * Do not reference these action types directly in your code. + */ + var ActionTypes = exports.ActionTypes = { + INIT: '@@redux/INIT' + }; + + /** + * Creates a Redux store that holds the state tree. + * The only way to change the data in the store is to call `dispatch()` on it. + * + * There should only be a single store in your app. To specify how different + * parts of the state tree respond to actions, you may combine several reducers + * into a single reducer function by using `combineReducers`. + * + * @param {Function} reducer A function that returns the next state tree, given + * the current state tree and the action to handle. + * + * @param {any} [initialState] The initial state. You may optionally specify it + * to hydrate the state from the server in universal apps, or to restore a + * previously serialized user session. + * If you use `combineReducers` to produce the root reducer function, this must be + * an object with the same shape as `combineReducers` keys. + * + * @param {Function} enhancer The store enhancer. You may optionally specify it + * to enhance the store with third-party capabilities such as middleware, + * time travel, persistence, etc. The only store enhancer that ships with Redux + * is `applyMiddleware()`. + * + * @returns {Store} A Redux store that lets you read the state, dispatch actions + * and subscribe to changes. + */ + function createStore(reducer, initialState, enhancer) { + var _ref2; + + if (typeof initialState === 'function' && typeof enhancer === 'undefined') { + enhancer = initialState; + initialState = undefined; + } + + if (typeof enhancer !== 'undefined') { + if (typeof enhancer !== 'function') { + throw new Error('Expected the enhancer to be a function.'); + } + + return enhancer(createStore)(reducer, initialState); + } + + if (typeof reducer !== 'function') { + throw new Error('Expected the reducer to be a function.'); + } + + var currentReducer = reducer; + var currentState = initialState; + var currentListeners = []; + var nextListeners = currentListeners; + var isDispatching = false; + + function ensureCanMutateNextListeners() { + if (nextListeners === currentListeners) { + nextListeners = currentListeners.slice(); + } + } + + /** + * Reads the state tree managed by the store. + * + * @returns {any} The current state tree of your application. + */ + function getState() { + return currentState; + } + + /** + * Adds a change listener. It will be called any time an action is dispatched, + * and some part of the state tree may potentially have changed. You may then + * call `getState()` to read the current state tree inside the callback. + * + * You may call `dispatch()` from a change listener, with the following + * caveats: + * + * 1. The subscriptions are snapshotted just before every `dispatch()` call. + * If you subscribe or unsubscribe while the listeners are being invoked, this + * will not have any effect on the `dispatch()` that is currently in progress. + * However, the next `dispatch()` call, whether nested or not, will use a more + * recent snapshot of the subscription list. + * + * 2. The listener should not expect to see all state changes, as the state + * might have been updated multiple times during a nested `dispatch()` before + * the listener is called. It is, however, guaranteed that all subscribers + * registered before the `dispatch()` started will be called with the latest + * state by the time it exits. + * + * @param {Function} listener A callback to be invoked on every dispatch. + * @returns {Function} A function to remove this change listener. + */ + function subscribe(listener) { + if (typeof listener !== 'function') { + throw new Error('Expected listener to be a function.'); + } + + var isSubscribed = true; + + ensureCanMutateNextListeners(); + nextListeners.push(listener); + + return function unsubscribe() { + if (!isSubscribed) { + return; + } + + isSubscribed = false; + + ensureCanMutateNextListeners(); + var index = nextListeners.indexOf(listener); + nextListeners.splice(index, 1); + }; + } + + /** + * Dispatches an action. It is the only way to trigger a state change. + * + * The `reducer` function, used to create the store, will be called with the + * current state tree and the given `action`. Its return value will + * be considered the **next** state of the tree, and the change listeners + * will be notified. + * + * The base implementation only supports plain object actions. If you want to + * dispatch a Promise, an Observable, a thunk, or something else, you need to + * wrap your store creating function into the corresponding middleware. For + * example, see the documentation for the `redux-thunk` package. Even the + * middleware will eventually dispatch plain object actions using this method. + * + * @param {Object} action A plain object representing “what changed”. It is + * a good idea to keep actions serializable so you can record and replay user + * sessions, or use the time travelling `redux-devtools`. An action must have + * a `type` property which may not be `undefined`. It is a good idea to use + * string constants for action types. + * + * @returns {Object} For convenience, the same action object you dispatched. + * + * Note that, if you use a custom middleware, it may wrap `dispatch()` to + * return something else (for example, a Promise you can await). + */ + function dispatch(action) { + if (!(0, _isPlainObject2["default"])(action)) { + throw new Error('Actions must be plain objects. ' + 'Use custom middleware for async actions.'); + } + + if (typeof action.type === 'undefined') { + throw new Error('Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?'); + } + + if (isDispatching) { + throw new Error('Reducers may not dispatch actions.'); + } + + try { + isDispatching = true; + currentState = currentReducer(currentState, action); + } finally { + isDispatching = false; + } + + var listeners = currentListeners = nextListeners; + for (var i = 0; i < listeners.length; i++) { + listeners[i](); + } + + return action; + } + + /** + * Replaces the reducer currently used by the store to calculate the state. + * + * You might need this if your app implements code splitting and you want to + * load some of the reducers dynamically. You might also need this if you + * implement a hot reloading mechanism for Redux. + * + * @param {Function} nextReducer The reducer for the store to use instead. + * @returns {void} + */ + function replaceReducer(nextReducer) { + if (typeof nextReducer !== 'function') { + throw new Error('Expected the nextReducer to be a function.'); + } + + currentReducer = nextReducer; + dispatch({ type: ActionTypes.INIT }); + } + + /** + * Interoperability point for observable/reactive libraries. + * @returns {observable} A minimal observable of state changes. + * For more information, see the observable proposal: + * https://github.com/zenparsing/es-observable + */ + function observable() { + var _ref; + + var outerSubscribe = subscribe; + return _ref = { + /** + * The minimal observable subscription method. + * @param {Object} observer Any object that can be used as an observer. + * The observer object should have a `next` method. + * @returns {subscription} An object with an `unsubscribe` method that can + * be used to unsubscribe the observable from the store, and prevent further + * emission of values from the observable. + */ + + subscribe: function subscribe(observer) { + if (typeof observer !== 'object') { + throw new TypeError('Expected the observer to be an object.'); + } + + function observeState() { + if (observer.next) { + observer.next(getState()); + } + } + + observeState(); + var unsubscribe = outerSubscribe(observeState); + return { unsubscribe: unsubscribe }; + } + }, _ref[_symbolObservable2["default"]] = function () { + return this; + }, _ref; + } + + // When a store is created, an "INIT" action is dispatched so that every + // reducer returns their initial state. This effectively populates + // the initial state tree. + dispatch({ type: ActionTypes.INIT }); + + return _ref2 = { + dispatch: dispatch, + subscribe: subscribe, + getState: getState, + replaceReducer: replaceReducer + }, _ref2[_symbolObservable2["default"]] = observable, _ref2; + } + +/***/ }, +/* 5 */ +/***/ function(module, exports, __webpack_require__) { + + var getPrototype = __webpack_require__(6), + isObjectLike = __webpack_require__(8); + + /** `Object#toString` result references. */ + var objectTag = '[object Object]'; + + /** Used for built-in method references. */ + var funcProto = Function.prototype, + objectProto = Object.prototype; + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to infer the `Object` constructor. */ + var objectCtorString = funcToString.call(Object); + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var objectToString = objectProto.toString; + + /** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ + function isPlainObject(value) { + if (!isObjectLike(value) || objectToString.call(value) != objectTag) { + return false; + } + var proto = getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; + return (typeof Ctor == 'function' && + Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString); + } + + module.exports = isPlainObject; + + +/***/ }, +/* 6 */ +/***/ function(module, exports, __webpack_require__) { + + var overArg = __webpack_require__(7); + + /** Built-in value references. */ + var getPrototype = overArg(Object.getPrototypeOf, Object); + + module.exports = getPrototype; + + +/***/ }, +/* 7 */ +/***/ function(module, exports) { + + /** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } + + module.exports = overArg; + + +/***/ }, +/* 8 */ +/***/ function(module, exports) { + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return value != null && typeof value == 'object'; + } + + module.exports = isObjectLike; + + +/***/ }, +/* 9 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {/* global window */ + 'use strict'; + + module.exports = __webpack_require__(10)(global || window || this); + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 10 */ +/***/ function(module, exports) { + + 'use strict'; + + module.exports = function symbolObservablePonyfill(root) { + var result; + var Symbol = root.Symbol; + + if (typeof Symbol === 'function') { + if (Symbol.observable) { + result = Symbol.observable; + } else { + result = Symbol('observable'); + Symbol.observable = result; + } + } else { + result = '@@observable'; + } + + return result; + }; + + +/***/ }, +/* 11 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + exports["default"] = combineReducers; + + var _createStore = __webpack_require__(4); + + var _isPlainObject = __webpack_require__(5); + + var _isPlainObject2 = _interopRequireDefault(_isPlainObject); + + var _warning = __webpack_require__(12); + + var _warning2 = _interopRequireDefault(_warning); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + + function getUndefinedStateErrorMessage(key, action) { + var actionType = action && action.type; + var actionName = actionType && '"' + actionType.toString() + '"' || 'an action'; + + return 'Given action ' + actionName + ', reducer "' + key + '" returned undefined. ' + 'To ignore an action, you must explicitly return the previous state.'; + } + + function getUnexpectedStateShapeWarningMessage(inputState, reducers, action) { + var reducerKeys = Object.keys(reducers); + var argumentName = action && action.type === _createStore.ActionTypes.INIT ? 'initialState argument passed to createStore' : 'previous state received by the reducer'; + + if (reducerKeys.length === 0) { + return 'Store does not have a valid reducer. Make sure the argument passed ' + 'to combineReducers is an object whose values are reducers.'; + } + + if (!(0, _isPlainObject2["default"])(inputState)) { + return 'The ' + argumentName + ' has unexpected type of "' + {}.toString.call(inputState).match(/\s([a-z|A-Z]+)/)[1] + '". Expected argument to be an object with the following ' + ('keys: "' + reducerKeys.join('", "') + '"'); + } + + var unexpectedKeys = Object.keys(inputState).filter(function (key) { + return !reducers.hasOwnProperty(key); + }); + + if (unexpectedKeys.length > 0) { + return 'Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('"' + unexpectedKeys.join('", "') + '" found in ' + argumentName + '. ') + 'Expected to find one of the known reducer keys instead: ' + ('"' + reducerKeys.join('", "') + '". Unexpected keys will be ignored.'); + } + } + + function assertReducerSanity(reducers) { + Object.keys(reducers).forEach(function (key) { + var reducer = reducers[key]; + var initialState = reducer(undefined, { type: _createStore.ActionTypes.INIT }); + + if (typeof initialState === 'undefined') { + throw new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined.'); + } + + var type = '@@redux/PROBE_UNKNOWN_ACTION_' + Math.random().toString(36).substring(7).split('').join('.'); + if (typeof reducer(undefined, { type: type }) === 'undefined') { + throw new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + _createStore.ActionTypes.INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined.'); + } + }); + } + + /** + * Turns an object whose values are different reducer functions, into a single + * reducer function. It will call every child reducer, and gather their results + * into a single state object, whose keys correspond to the keys of the passed + * reducer functions. + * + * @param {Object} reducers An object whose values correspond to different + * reducer functions that need to be combined into one. One handy way to obtain + * it is to use ES6 `import * as reducers` syntax. The reducers may never return + * undefined for any action. Instead, they should return their initial state + * if the state passed to them was undefined, and the current state for any + * unrecognized action. + * + * @returns {Function} A reducer function that invokes every reducer inside the + * passed object, and builds a state object with the same shape. + */ + function combineReducers(reducers) { + var reducerKeys = Object.keys(reducers); + var finalReducers = {}; + for (var i = 0; i < reducerKeys.length; i++) { + var key = reducerKeys[i]; + if (typeof reducers[key] === 'function') { + finalReducers[key] = reducers[key]; + } + } + var finalReducerKeys = Object.keys(finalReducers); + + var sanityError; + try { + assertReducerSanity(finalReducers); + } catch (e) { + sanityError = e; + } + + return function combination() { + var state = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; + var action = arguments[1]; + + if (sanityError) { + throw sanityError; + } + + if (false) { + var warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action); + if (warningMessage) { + (0, _warning2["default"])(warningMessage); + } + } + + var hasChanged = false; + var nextState = {}; + for (var i = 0; i < finalReducerKeys.length; i++) { + var key = finalReducerKeys[i]; + var reducer = finalReducers[key]; + var previousStateForKey = state[key]; + var nextStateForKey = reducer(previousStateForKey, action); + if (typeof nextStateForKey === 'undefined') { + var errorMessage = getUndefinedStateErrorMessage(key, action); + throw new Error(errorMessage); + } + nextState[key] = nextStateForKey; + hasChanged = hasChanged || nextStateForKey !== previousStateForKey; + } + return hasChanged ? nextState : state; + }; + } + +/***/ }, +/* 12 */ +/***/ function(module, exports) { + + 'use strict'; + + exports.__esModule = true; + exports["default"] = warning; + /** + * Prints a warning in the console if it exists. + * + * @param {String} message The warning message. + * @returns {void} + */ + function warning(message) { + /* eslint-disable no-console */ + if (typeof console !== 'undefined' && typeof console.error === 'function') { + console.error(message); + } + /* eslint-enable no-console */ + try { + // This error was thrown as a convenience so that if you enable + // "break on all exceptions" in your console, + // it would pause the execution at this line. + throw new Error(message); + /* eslint-disable no-empty */ + } catch (e) {} + /* eslint-enable no-empty */ + } + +/***/ }, +/* 13 */ +/***/ function(module, exports) { + + 'use strict'; + + exports.__esModule = true; + exports["default"] = bindActionCreators; + function bindActionCreator(actionCreator, dispatch) { + return function () { + return dispatch(actionCreator.apply(undefined, arguments)); + }; + } + + /** + * Turns an object whose values are action creators, into an object with the + * same keys, but with every function wrapped into a `dispatch` call so they + * may be invoked directly. This is just a convenience method, as you can call + * `store.dispatch(MyActionCreators.doSomething())` yourself just fine. + * + * For convenience, you can also pass a single function as the first argument, + * and get a function in return. + * + * @param {Function|Object} actionCreators An object whose values are action + * creator functions. One handy way to obtain it is to use ES6 `import * as` + * syntax. You may also pass a single function. + * + * @param {Function} dispatch The `dispatch` function available on your Redux + * store. + * + * @returns {Function|Object} The object mimicking the original object, but with + * every action creator wrapped into the `dispatch` call. If you passed a + * function as `actionCreators`, the return value will also be a single + * function. + */ + function bindActionCreators(actionCreators, dispatch) { + if (typeof actionCreators === 'function') { + return bindActionCreator(actionCreators, dispatch); + } + + if (typeof actionCreators !== 'object' || actionCreators === null) { + throw new Error('bindActionCreators expected an object or a function, instead received ' + (actionCreators === null ? 'null' : typeof actionCreators) + '. ' + 'Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?'); + } + + var keys = Object.keys(actionCreators); + var boundActionCreators = {}; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var actionCreator = actionCreators[key]; + if (typeof actionCreator === 'function') { + boundActionCreators[key] = bindActionCreator(actionCreator, dispatch); + } + } + return boundActionCreators; + } + +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + + exports["default"] = applyMiddleware; + + var _compose = __webpack_require__(15); + + var _compose2 = _interopRequireDefault(_compose); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + + /** + * Creates a store enhancer that applies middleware to the dispatch method + * of the Redux store. This is handy for a variety of tasks, such as expressing + * asynchronous actions in a concise manner, or logging every action payload. + * + * See `redux-thunk` package as an example of the Redux middleware. + * + * Because middleware is potentially asynchronous, this should be the first + * store enhancer in the composition chain. + * + * Note that each middleware will be given the `dispatch` and `getState` functions + * as named arguments. + * + * @param {...Function} middlewares The middleware chain to be applied. + * @returns {Function} A store enhancer applying the middleware. + */ + function applyMiddleware() { + for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) { + middlewares[_key] = arguments[_key]; + } + + return function (createStore) { + return function (reducer, initialState, enhancer) { + var store = createStore(reducer, initialState, enhancer); + var _dispatch = store.dispatch; + var chain = []; + + var middlewareAPI = { + getState: store.getState, + dispatch: function dispatch(action) { + return _dispatch(action); + } + }; + chain = middlewares.map(function (middleware) { + return middleware(middlewareAPI); + }); + _dispatch = _compose2["default"].apply(undefined, chain)(store.dispatch); + + return _extends({}, store, { + dispatch: _dispatch + }); + }; + }; + } + +/***/ }, +/* 15 */ +/***/ function(module, exports) { + + "use strict"; + + exports.__esModule = true; + exports["default"] = compose; + /** + * Composes single-argument functions from right to left. The rightmost + * function can take multiple arguments as it provides the signature for + * the resulting composite function. + * + * @param {...Function} funcs The functions to compose. + * @returns {Function} A function obtained by composing the argument functions + * from right to left. For example, compose(f, g, h) is identical to doing + * (...args) => f(g(h(...args))). + */ + + function compose() { + for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) { + funcs[_key] = arguments[_key]; + } + + if (funcs.length === 0) { + return function (arg) { + return arg; + }; + } else { + var _ret = function () { + var last = funcs[funcs.length - 1]; + var rest = funcs.slice(0, -1); + return { + v: function v() { + return rest.reduceRight(function (composed, f) { + return f(composed); + }, last.apply(undefined, arguments)); + } + }; + }(); + + if (typeof _ret === "object") return _ret.v; + } + } + +/***/ }, +/* 16 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + module.exports = __webpack_require__(17); + + +/***/ }, +/* 17 */ +/***/ function(module, exports) { + + module.exports = devtoolsRequire("devtools/client/shared/vendor/react-dom"); + +/***/ }, +/* 18 */ +/***/ function(module, exports, __webpack_require__) { + + /* global window, document, DebuggerConfig */ + + var _require = __webpack_require__(3); + + var bindActionCreators = _require.bindActionCreators; + var combineReducers = _require.combineReducers; + + var _require2 = __webpack_require__(19); + + var Provider = _require2.Provider; + + var _require3 = __webpack_require__(28); + + var DevToolsUtils = _require3.DevToolsUtils; + var AppConstants = _require3.AppConstants; + + var _require4 = __webpack_require__(88); + + var injectGlobals = _require4.injectGlobals; + var debugGlobal = _require4.debugGlobal; + + var _require5 = __webpack_require__(89); + + var setConfig = _require5.setConfig; + var isEnabled = _require5.isEnabled; + var getValue = _require5.getValue; + var isDevelopment = _require5.isDevelopment; + + + setConfig(({"environment":"firefox-panel","baseWorkerURL":"resource://devtools/client/debugger/new/","logging":false,"clientLogging":false,"features":{"tabs":true,"sourceMaps":true,"prettyPrint":true}})); + + // Set various flags before requiring app code. + if (isEnabled("logging.client")) { + DevToolsUtils.dumpn.wantLogging = true; + } + + var client = __webpack_require__(141); + var getClient = client.getClient; + var connectClients = client.connectClients; + var startDebugging = client.startDebugging; + + + var Root = __webpack_require__(210); + + // Using this static variable allows webpack to know at compile-time + // to avoid this require and not include it at all in the output. + if (false) { + var theme = getValue("theme"); + switch (theme) { + case "dark": + require("./lib/themes/dark-theme.css");break; + case "light": + require("./lib/themes/light-theme.css");break; + case "firebug": + require("./lib/themes/firebug-theme.css");break; + } + document.body.parentNode.classList.add(`theme-${ theme }`); + + window.L10N = require("./utils/L10N"); + } + + function initApp() { + var configureStore = __webpack_require__(216); + var reducers = __webpack_require__(226); + var LandingPage = __webpack_require__(231); + + var createStore = configureStore({ + log: getValue("logging.actions"), + makeThunkArgs: (args, state) => { + return Object.assign({}, args, { client: getClient(state) }); + } + }); + + var store = createStore(combineReducers(reducers)); + var actions = bindActionCreators(__webpack_require__(236), store.dispatch); + + if (isDevelopment()) { + AppConstants.DEBUG_JS_MODULES = true; + injectGlobals({ store }); + } + + return { store, actions, LandingPage }; + } + + function renderRoot(_React, _ReactDOM, component, _store) { + var mount = document.querySelector("#mount"); + + // bail in test environments that do not have a mount + if (!mount) { + return; + } + + _ReactDOM.render(_React.createElement(Provider, { store: _store }, Root(component)), mount); + } + + function getTargetFromQuery() { + var href = window.location.href; + var nodeMatch = href.match(/ws=([^&#]*)/); + var firefoxMatch = href.match(/firefox-tab=([^&#]*)/); + var chromeMatch = href.match(/chrome-tab=([^&#]*)/); + + if (nodeMatch) { + return { type: "node", param: nodeMatch[1] }; + } else if (firefoxMatch) { + return { type: "firefox", param: firefoxMatch[1] }; + } else if (chromeMatch) { + return { type: "chrome", param: chromeMatch[1] }; + } + + return null; + } + + function bootstrap(React, ReactDOM, App, appActions, appStore) { + var connTarget = getTargetFromQuery(); + if (connTarget) { + startDebugging(connTarget, appActions).then(tabs => { + renderRoot(React, ReactDOM, App, appStore); + }); + } else { + (function () { + var _initApp = initApp(); + + var store = _initApp.store; + var actions = _initApp.actions; + var LandingPage = _initApp.LandingPage; + + renderRoot(React, ReactDOM, LandingPage, store); + connectClients(tabs => actions.newTabs(tabs)); + })(); + } + } + + module.exports = { + bootstrap, + renderRoot, + debugGlobal, + client + }; + +/***/ }, +/* 19 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + exports.connect = exports.Provider = undefined; + + var _Provider = __webpack_require__(20); + + var _Provider2 = _interopRequireDefault(_Provider); + + var _connect = __webpack_require__(23); + + var _connect2 = _interopRequireDefault(_connect); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + + exports.Provider = _Provider2["default"]; + exports.connect = _connect2["default"]; + +/***/ }, +/* 20 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + exports["default"] = undefined; + + var _react = __webpack_require__(2); + + var _storeShape = __webpack_require__(21); + + var _storeShape2 = _interopRequireDefault(_storeShape); + + var _warning = __webpack_require__(22); + + var _warning2 = _interopRequireDefault(_warning); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + + function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + + var didWarnAboutReceivingStore = false; + function warnAboutReceivingStore() { + if (didWarnAboutReceivingStore) { + return; + } + didWarnAboutReceivingStore = true; + + (0, _warning2["default"])('<Provider> does not support changing `store` on the fly. ' + 'It is most likely that you see this error because you updated to ' + 'Redux 2.x and React Redux 2.x which no longer hot reload reducers ' + 'automatically. See https://github.com/reactjs/react-redux/releases/' + 'tag/v2.0.0 for the migration instructions.'); + } + + var Provider = function (_Component) { + _inherits(Provider, _Component); + + Provider.prototype.getChildContext = function getChildContext() { + return { store: this.store }; + }; + + function Provider(props, context) { + _classCallCheck(this, Provider); + + var _this = _possibleConstructorReturn(this, _Component.call(this, props, context)); + + _this.store = props.store; + return _this; + } + + Provider.prototype.render = function render() { + var children = this.props.children; + + return _react.Children.only(children); + }; + + return Provider; + }(_react.Component); + + exports["default"] = Provider; + + if (false) { + Provider.prototype.componentWillReceiveProps = function (nextProps) { + var store = this.store; + var nextStore = nextProps.store; + + if (store !== nextStore) { + warnAboutReceivingStore(); + } + }; + } + + Provider.propTypes = { + store: _storeShape2["default"].isRequired, + children: _react.PropTypes.element.isRequired + }; + Provider.childContextTypes = { + store: _storeShape2["default"].isRequired + }; + +/***/ }, +/* 21 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _react = __webpack_require__(2); + + exports["default"] = _react.PropTypes.shape({ + subscribe: _react.PropTypes.func.isRequired, + dispatch: _react.PropTypes.func.isRequired, + getState: _react.PropTypes.func.isRequired + }); + +/***/ }, +/* 22 */ +/***/ function(module, exports) { + + 'use strict'; + + exports.__esModule = true; + exports["default"] = warning; + /** + * Prints a warning in the console if it exists. + * + * @param {String} message The warning message. + * @returns {void} + */ + function warning(message) { + /* eslint-disable no-console */ + if (typeof console !== 'undefined' && typeof console.error === 'function') { + console.error(message); + } + /* eslint-enable no-console */ + try { + // This error was thrown as a convenience so that you can use this stack + // to find the callsite that caused this warning to fire. + throw new Error(message); + /* eslint-disable no-empty */ + } catch (e) {} + /* eslint-enable no-empty */ + } + +/***/ }, +/* 23 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + + exports.__esModule = true; + exports["default"] = connect; + + var _react = __webpack_require__(2); + + var _storeShape = __webpack_require__(21); + + var _storeShape2 = _interopRequireDefault(_storeShape); + + var _shallowEqual = __webpack_require__(24); + + var _shallowEqual2 = _interopRequireDefault(_shallowEqual); + + var _wrapActionCreators = __webpack_require__(25); + + var _wrapActionCreators2 = _interopRequireDefault(_wrapActionCreators); + + var _warning = __webpack_require__(22); + + var _warning2 = _interopRequireDefault(_warning); + + var _isPlainObject = __webpack_require__(5); + + var _isPlainObject2 = _interopRequireDefault(_isPlainObject); + + var _hoistNonReactStatics = __webpack_require__(26); + + var _hoistNonReactStatics2 = _interopRequireDefault(_hoistNonReactStatics); + + var _invariant = __webpack_require__(27); + + var _invariant2 = _interopRequireDefault(_invariant); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + + function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + + var defaultMapStateToProps = function defaultMapStateToProps(state) { + return {}; + }; // eslint-disable-line no-unused-vars + var defaultMapDispatchToProps = function defaultMapDispatchToProps(dispatch) { + return { dispatch: dispatch }; + }; + var defaultMergeProps = function defaultMergeProps(stateProps, dispatchProps, parentProps) { + return _extends({}, parentProps, stateProps, dispatchProps); + }; + + function getDisplayName(WrappedComponent) { + return WrappedComponent.displayName || WrappedComponent.name || 'Component'; + } + + var errorObject = { value: null }; + function tryCatch(fn, ctx) { + try { + return fn.apply(ctx); + } catch (e) { + errorObject.value = e; + return errorObject; + } + } + + // Helps track hot reloading. + var nextVersion = 0; + + function connect(mapStateToProps, mapDispatchToProps, mergeProps) { + var options = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3]; + + var shouldSubscribe = Boolean(mapStateToProps); + var mapState = mapStateToProps || defaultMapStateToProps; + + var mapDispatch = undefined; + if (typeof mapDispatchToProps === 'function') { + mapDispatch = mapDispatchToProps; + } else if (!mapDispatchToProps) { + mapDispatch = defaultMapDispatchToProps; + } else { + mapDispatch = (0, _wrapActionCreators2["default"])(mapDispatchToProps); + } + + var finalMergeProps = mergeProps || defaultMergeProps; + var _options$pure = options.pure; + var pure = _options$pure === undefined ? true : _options$pure; + var _options$withRef = options.withRef; + var withRef = _options$withRef === undefined ? false : _options$withRef; + + var checkMergedEquals = pure && finalMergeProps !== defaultMergeProps; + + // Helps track hot reloading. + var version = nextVersion++; + + return function wrapWithConnect(WrappedComponent) { + var connectDisplayName = 'Connect(' + getDisplayName(WrappedComponent) + ')'; + + function checkStateShape(props, methodName) { + if (!(0, _isPlainObject2["default"])(props)) { + (0, _warning2["default"])(methodName + '() in ' + connectDisplayName + ' must return a plain object. ' + ('Instead received ' + props + '.')); + } + } + + function computeMergedProps(stateProps, dispatchProps, parentProps) { + var mergedProps = finalMergeProps(stateProps, dispatchProps, parentProps); + if (false) { + checkStateShape(mergedProps, 'mergeProps'); + } + return mergedProps; + } + + var Connect = function (_Component) { + _inherits(Connect, _Component); + + Connect.prototype.shouldComponentUpdate = function shouldComponentUpdate() { + return !pure || this.haveOwnPropsChanged || this.hasStoreStateChanged; + }; + + function Connect(props, context) { + _classCallCheck(this, Connect); + + var _this = _possibleConstructorReturn(this, _Component.call(this, props, context)); + + _this.version = version; + _this.store = props.store || context.store; + + (0, _invariant2["default"])(_this.store, 'Could not find "store" in either the context or ' + ('props of "' + connectDisplayName + '". ') + 'Either wrap the root component in a <Provider>, ' + ('or explicitly pass "store" as a prop to "' + connectDisplayName + '".')); + + var storeState = _this.store.getState(); + _this.state = { storeState: storeState }; + _this.clearCache(); + return _this; + } + + Connect.prototype.computeStateProps = function computeStateProps(store, props) { + if (!this.finalMapStateToProps) { + return this.configureFinalMapState(store, props); + } + + var state = store.getState(); + var stateProps = this.doStatePropsDependOnOwnProps ? this.finalMapStateToProps(state, props) : this.finalMapStateToProps(state); + + if (false) { + checkStateShape(stateProps, 'mapStateToProps'); + } + return stateProps; + }; + + Connect.prototype.configureFinalMapState = function configureFinalMapState(store, props) { + var mappedState = mapState(store.getState(), props); + var isFactory = typeof mappedState === 'function'; + + this.finalMapStateToProps = isFactory ? mappedState : mapState; + this.doStatePropsDependOnOwnProps = this.finalMapStateToProps.length !== 1; + + if (isFactory) { + return this.computeStateProps(store, props); + } + + if (false) { + checkStateShape(mappedState, 'mapStateToProps'); + } + return mappedState; + }; + + Connect.prototype.computeDispatchProps = function computeDispatchProps(store, props) { + if (!this.finalMapDispatchToProps) { + return this.configureFinalMapDispatch(store, props); + } + + var dispatch = store.dispatch; + + var dispatchProps = this.doDispatchPropsDependOnOwnProps ? this.finalMapDispatchToProps(dispatch, props) : this.finalMapDispatchToProps(dispatch); + + if (false) { + checkStateShape(dispatchProps, 'mapDispatchToProps'); + } + return dispatchProps; + }; + + Connect.prototype.configureFinalMapDispatch = function configureFinalMapDispatch(store, props) { + var mappedDispatch = mapDispatch(store.dispatch, props); + var isFactory = typeof mappedDispatch === 'function'; + + this.finalMapDispatchToProps = isFactory ? mappedDispatch : mapDispatch; + this.doDispatchPropsDependOnOwnProps = this.finalMapDispatchToProps.length !== 1; + + if (isFactory) { + return this.computeDispatchProps(store, props); + } + + if (false) { + checkStateShape(mappedDispatch, 'mapDispatchToProps'); + } + return mappedDispatch; + }; + + Connect.prototype.updateStatePropsIfNeeded = function updateStatePropsIfNeeded() { + var nextStateProps = this.computeStateProps(this.store, this.props); + if (this.stateProps && (0, _shallowEqual2["default"])(nextStateProps, this.stateProps)) { + return false; + } + + this.stateProps = nextStateProps; + return true; + }; + + Connect.prototype.updateDispatchPropsIfNeeded = function updateDispatchPropsIfNeeded() { + var nextDispatchProps = this.computeDispatchProps(this.store, this.props); + if (this.dispatchProps && (0, _shallowEqual2["default"])(nextDispatchProps, this.dispatchProps)) { + return false; + } + + this.dispatchProps = nextDispatchProps; + return true; + }; + + Connect.prototype.updateMergedPropsIfNeeded = function updateMergedPropsIfNeeded() { + var nextMergedProps = computeMergedProps(this.stateProps, this.dispatchProps, this.props); + if (this.mergedProps && checkMergedEquals && (0, _shallowEqual2["default"])(nextMergedProps, this.mergedProps)) { + return false; + } + + this.mergedProps = nextMergedProps; + return true; + }; + + Connect.prototype.isSubscribed = function isSubscribed() { + return typeof this.unsubscribe === 'function'; + }; + + Connect.prototype.trySubscribe = function trySubscribe() { + if (shouldSubscribe && !this.unsubscribe) { + this.unsubscribe = this.store.subscribe(this.handleChange.bind(this)); + this.handleChange(); + } + }; + + Connect.prototype.tryUnsubscribe = function tryUnsubscribe() { + if (this.unsubscribe) { + this.unsubscribe(); + this.unsubscribe = null; + } + }; + + Connect.prototype.componentDidMount = function componentDidMount() { + this.trySubscribe(); + }; + + Connect.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) { + if (!pure || !(0, _shallowEqual2["default"])(nextProps, this.props)) { + this.haveOwnPropsChanged = true; + } + }; + + Connect.prototype.componentWillUnmount = function componentWillUnmount() { + this.tryUnsubscribe(); + this.clearCache(); + }; + + Connect.prototype.clearCache = function clearCache() { + this.dispatchProps = null; + this.stateProps = null; + this.mergedProps = null; + this.haveOwnPropsChanged = true; + this.hasStoreStateChanged = true; + this.haveStatePropsBeenPrecalculated = false; + this.statePropsPrecalculationError = null; + this.renderedElement = null; + this.finalMapDispatchToProps = null; + this.finalMapStateToProps = null; + }; + + Connect.prototype.handleChange = function handleChange() { + if (!this.unsubscribe) { + return; + } + + var storeState = this.store.getState(); + var prevStoreState = this.state.storeState; + if (pure && prevStoreState === storeState) { + return; + } + + if (pure && !this.doStatePropsDependOnOwnProps) { + var haveStatePropsChanged = tryCatch(this.updateStatePropsIfNeeded, this); + if (!haveStatePropsChanged) { + return; + } + if (haveStatePropsChanged === errorObject) { + this.statePropsPrecalculationError = errorObject.value; + } + this.haveStatePropsBeenPrecalculated = true; + } + + this.hasStoreStateChanged = true; + this.setState({ storeState: storeState }); + }; + + Connect.prototype.getWrappedInstance = function getWrappedInstance() { + (0, _invariant2["default"])(withRef, 'To access the wrapped instance, you need to specify ' + '{ withRef: true } as the fourth argument of the connect() call.'); + + return this.refs.wrappedInstance; + }; + + Connect.prototype.render = function render() { + var haveOwnPropsChanged = this.haveOwnPropsChanged; + var hasStoreStateChanged = this.hasStoreStateChanged; + var haveStatePropsBeenPrecalculated = this.haveStatePropsBeenPrecalculated; + var statePropsPrecalculationError = this.statePropsPrecalculationError; + var renderedElement = this.renderedElement; + + this.haveOwnPropsChanged = false; + this.hasStoreStateChanged = false; + this.haveStatePropsBeenPrecalculated = false; + this.statePropsPrecalculationError = null; + + if (statePropsPrecalculationError) { + throw statePropsPrecalculationError; + } + + var shouldUpdateStateProps = true; + var shouldUpdateDispatchProps = true; + if (pure && renderedElement) { + shouldUpdateStateProps = hasStoreStateChanged || haveOwnPropsChanged && this.doStatePropsDependOnOwnProps; + shouldUpdateDispatchProps = haveOwnPropsChanged && this.doDispatchPropsDependOnOwnProps; + } + + var haveStatePropsChanged = false; + var haveDispatchPropsChanged = false; + if (haveStatePropsBeenPrecalculated) { + haveStatePropsChanged = true; + } else if (shouldUpdateStateProps) { + haveStatePropsChanged = this.updateStatePropsIfNeeded(); + } + if (shouldUpdateDispatchProps) { + haveDispatchPropsChanged = this.updateDispatchPropsIfNeeded(); + } + + var haveMergedPropsChanged = true; + if (haveStatePropsChanged || haveDispatchPropsChanged || haveOwnPropsChanged) { + haveMergedPropsChanged = this.updateMergedPropsIfNeeded(); + } else { + haveMergedPropsChanged = false; + } + + if (!haveMergedPropsChanged && renderedElement) { + return renderedElement; + } + + if (withRef) { + this.renderedElement = (0, _react.createElement)(WrappedComponent, _extends({}, this.mergedProps, { + ref: 'wrappedInstance' + })); + } else { + this.renderedElement = (0, _react.createElement)(WrappedComponent, this.mergedProps); + } + + return this.renderedElement; + }; + + return Connect; + }(_react.Component); + + Connect.displayName = connectDisplayName; + Connect.WrappedComponent = WrappedComponent; + Connect.contextTypes = { + store: _storeShape2["default"] + }; + Connect.propTypes = { + store: _storeShape2["default"] + }; + + if (false) { + Connect.prototype.componentWillUpdate = function componentWillUpdate() { + if (this.version === version) { + return; + } + + // We are hot reloading! + this.version = version; + this.trySubscribe(); + this.clearCache(); + }; + } + + return (0, _hoistNonReactStatics2["default"])(Connect, WrappedComponent); + }; + } + +/***/ }, +/* 24 */ +/***/ function(module, exports) { + + "use strict"; + + exports.__esModule = true; + exports["default"] = shallowEqual; + function shallowEqual(objA, objB) { + if (objA === objB) { + return true; + } + + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); + + if (keysA.length !== keysB.length) { + return false; + } + + // Test for A's keys different from B. + var hasOwn = Object.prototype.hasOwnProperty; + for (var i = 0; i < keysA.length; i++) { + if (!hasOwn.call(objB, keysA[i]) || objA[keysA[i]] !== objB[keysA[i]]) { + return false; + } + } + + return true; + } + +/***/ }, +/* 25 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + exports["default"] = wrapActionCreators; + + var _redux = __webpack_require__(3); + + function wrapActionCreators(actionCreators) { + return function (dispatch) { + return (0, _redux.bindActionCreators)(actionCreators, dispatch); + }; + } + +/***/ }, +/* 26 */ +/***/ function(module, exports) { + + /** + * Copyright 2015, Yahoo! Inc. + * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ + 'use strict'; + + var REACT_STATICS = { + childContextTypes: true, + contextTypes: true, + defaultProps: true, + displayName: true, + getDefaultProps: true, + mixins: true, + propTypes: true, + type: true + }; + + var KNOWN_STATICS = { + name: true, + length: true, + prototype: true, + caller: true, + arguments: true, + arity: true + }; + + var isGetOwnPropertySymbolsAvailable = typeof Object.getOwnPropertySymbols === 'function'; + + module.exports = function hoistNonReactStatics(targetComponent, sourceComponent, customStatics) { + if (typeof sourceComponent !== 'string') { // don't hoist over string (html) components + var keys = Object.getOwnPropertyNames(sourceComponent); + + /* istanbul ignore else */ + if (isGetOwnPropertySymbolsAvailable) { + keys = keys.concat(Object.getOwnPropertySymbols(sourceComponent)); + } + + for (var i = 0; i < keys.length; ++i) { + if (!REACT_STATICS[keys[i]] && !KNOWN_STATICS[keys[i]] && (!customStatics || !customStatics[keys[i]])) { + try { + targetComponent[keys[i]] = sourceComponent[keys[i]]; + } catch (error) { + + } + } + } + } + + return targetComponent; + }; + + +/***/ }, +/* 27 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + + 'use strict'; + + /** + * Use invariant() to assert state which your program assumes to be true. + * + * Provide sprintf-style format (only %s is supported) and arguments + * to provide information about what broke and what you were + * expecting. + * + * The invariant message will be stripped in production, but the invariant + * will remain to ensure logic does not differ in production. + */ + + var invariant = function(condition, format, a, b, c, d, e, f) { + if (false) { + if (format === undefined) { + throw new Error('invariant requires an error message argument'); + } + } + + if (!condition) { + var error; + if (format === undefined) { + error = new Error( + 'Minified exception occurred; use the non-minified dev environment ' + + 'for the full error message and additional helpful warnings.' + ); + } else { + var args = [a, b, c, d, e, f]; + var argIndex = 0; + error = new Error( + format.replace(/%s/g, function() { return args[argIndex++]; }) + ); + error.name = 'Invariant Violation'; + } + + error.framesToPop = 1; // we don't care about invariant's own frame + throw error; + } + }; + + module.exports = invariant; + + +/***/ }, +/* 28 */ +/***/ function(module, exports, __webpack_require__) { + + var _require = __webpack_require__(29); + + var KeyShortcuts = _require.KeyShortcuts; + + var _require2 = __webpack_require__(67); + + var DebuggerTransport = _require2.DebuggerTransport; + + var _require3 = __webpack_require__(79); + + var DebuggerClient = _require3.DebuggerClient; + + var PrefsHelper = __webpack_require__(83).PrefsHelper; + + var _require4 = __webpack_require__(84); + + var TargetFactory = _require4.TargetFactory; + + var DevToolsUtils = __webpack_require__(68); + var AppConstants = __webpack_require__(70); + var EventEmitter = __webpack_require__(60); + var WebsocketTransport = __webpack_require__(85); + var Menu = __webpack_require__(86); + var MenuItem = __webpack_require__(87); + + module.exports = { + KeyShortcuts, + PrefsHelper, + DebuggerClient, + DebuggerTransport, + TargetFactory, + DevToolsUtils, + AppConstants, + EventEmitter, + WebsocketTransport, + Menu, + MenuItem + }; + +/***/ }, +/* 29 */ +/***/ function(module, exports, __webpack_require__) { + + var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var _require = __webpack_require__(30); + + var appinfo = _require.Services.appinfo; + + var EventEmitter = __webpack_require__(60); + var isOSX = appinfo.OS === "Darwin"; + "use strict"; + + // List of electron keys mapped to DOM API (DOM_VK_*) key code + var ElectronKeysMapping = { + "F1": "DOM_VK_F1", + "F2": "DOM_VK_F2", + "F3": "DOM_VK_F3", + "F4": "DOM_VK_F4", + "F5": "DOM_VK_F5", + "F6": "DOM_VK_F6", + "F7": "DOM_VK_F7", + "F8": "DOM_VK_F8", + "F9": "DOM_VK_F9", + "F10": "DOM_VK_F10", + "F11": "DOM_VK_F11", + "F12": "DOM_VK_F12", + "F13": "DOM_VK_F13", + "F14": "DOM_VK_F14", + "F15": "DOM_VK_F15", + "F16": "DOM_VK_F16", + "F17": "DOM_VK_F17", + "F18": "DOM_VK_F18", + "F19": "DOM_VK_F19", + "F20": "DOM_VK_F20", + "F21": "DOM_VK_F21", + "F22": "DOM_VK_F22", + "F23": "DOM_VK_F23", + "F24": "DOM_VK_F24", + "Space": "DOM_VK_SPACE", + "Backspace": "DOM_VK_BACK_SPACE", + "Delete": "DOM_VK_DELETE", + "Insert": "DOM_VK_INSERT", + "Return": "DOM_VK_RETURN", + "Enter": "DOM_VK_RETURN", + "Up": "DOM_VK_UP", + "Down": "DOM_VK_DOWN", + "Left": "DOM_VK_LEFT", + "Right": "DOM_VK_RIGHT", + "Home": "DOM_VK_HOME", + "End": "DOM_VK_END", + "PageUp": "DOM_VK_PAGE_UP", + "PageDown": "DOM_VK_PAGE_DOWN", + "Escape": "DOM_VK_ESCAPE", + "Esc": "DOM_VK_ESCAPE", + "Tab": "DOM_VK_TAB", + "VolumeUp": "DOM_VK_VOLUME_UP", + "VolumeDown": "DOM_VK_VOLUME_DOWN", + "VolumeMute": "DOM_VK_VOLUME_MUTE", + "PrintScreen": "DOM_VK_PRINTSCREEN" + }; + + /** + * Helper to listen for keyboard events decribed in .properties file. + * + * let shortcuts = new KeyShortcuts({ + * window + * }); + * shortcuts.on("Ctrl+F", event => { + * // `event` is the KeyboardEvent which relates to the key shortcuts + * }); + * + * @param DOMWindow window + * The window object of the document to listen events from. + * @param DOMElement target + * Optional DOM Element on which we should listen events from. + * If omitted, we listen for all events fired on `window`. + */ + function KeyShortcuts(_ref) { + var window = _ref.window; + var target = _ref.target; + + this.window = window; + this.target = target || window; + this.keys = new Map(); + this.eventEmitter = new EventEmitter(); + this.target.addEventListener("keydown", this); + } + + /* + * Parse an electron-like key string and return a normalized object which + * allow efficient match on DOM key event. The normalized object matches DOM + * API. + * + * @param DOMWindow window + * Any DOM Window object, just to fetch its `KeyboardEvent` object + * @param String str + * The shortcut string to parse, following this document: + * https://github.com/electron/electron/blob/master/docs/api/accelerator.md + */ + KeyShortcuts.parseElectronKey = function (window, str) { + var modifiers = str.split("+"); + var key = modifiers.pop(); + + var shortcut = { + ctrl: false, + meta: false, + alt: false, + shift: false, + // Set for character keys + key: undefined, + // Set for non-character keys + keyCode: undefined + }; + for (var mod of modifiers) { + if (mod === "Alt") { + shortcut.alt = true; + } else if (["Command", "Cmd"].includes(mod)) { + shortcut.meta = true; + } else if (["CommandOrControl", "CmdOrCtrl"].includes(mod)) { + if (isOSX) { + shortcut.meta = true; + } else { + shortcut.ctrl = true; + } + } else if (["Control", "Ctrl"].includes(mod)) { + shortcut.ctrl = true; + } else if (mod === "Shift") { + shortcut.shift = true; + } else { + console.error("Unsupported modifier:", mod, "from key:", str); + return null; + } + } + + // Plus is a special case. It's a character key and shouldn't be matched + // against a keycode as it is only accessible via Shift/Capslock + if (key === "Plus") { + key = "+"; + } + + if (typeof key === "string" && key.length === 1) { + // Match any single character + shortcut.key = key.toLowerCase(); + } else if (key in ElectronKeysMapping) { + // Maps the others manually to DOM API DOM_VK_* + key = ElectronKeysMapping[key]; + shortcut.keyCode = window.KeyboardEvent[key]; + // Used only to stringify the shortcut + shortcut.keyCodeString = key; + shortcut.key = key; + } else { + console.error("Unsupported key:", key); + return null; + } + + return shortcut; + }; + + KeyShortcuts.stringify = function (shortcut) { + var list = []; + if (shortcut.alt) { + list.push("Alt"); + } + if (shortcut.ctrl) { + list.push("Ctrl"); + } + if (shortcut.meta) { + list.push("Cmd"); + } + if (shortcut.shift) { + list.push("Shift"); + } + var key = void 0; + if (shortcut.key) { + key = shortcut.key.toUpperCase(); + } else { + key = shortcut.keyCodeString; + } + list.push(key); + return list.join("+"); + }; + + KeyShortcuts.prototype = { + destroy() { + this.target.removeEventListener("keydown", this); + this.keys.clear(); + }, + + doesEventMatchShortcut(event, shortcut) { + if (shortcut.meta != event.metaKey) { + return false; + } + if (shortcut.ctrl != event.ctrlKey) { + return false; + } + if (shortcut.alt != event.altKey) { + return false; + } + // Shift is a special modifier, it may implicitely be required if the + // expected key is a special character accessible via shift. + if (shortcut.shift != event.shiftKey && event.key && event.key.match(/[a-zA-Z]/)) { + return false; + } + if (shortcut.keyCode) { + return event.keyCode == shortcut.keyCode; + } else if (event.key in ElectronKeysMapping) { + return ElectronKeysMapping[event.key] === shortcut.key; + } + + // get the key from the keyCode if key is not provided. + var key = event.key || String.fromCharCode(event.keyCode); + + // For character keys, we match if the final character is the expected one. + // But for digits we also accept indirect match to please azerty keyboard, + // which requires Shift to be pressed to get digits. + return key.toLowerCase() == shortcut.key || shortcut.key.match(/[0-9]/) && event.keyCode == shortcut.key.charCodeAt(0); + }, + + handleEvent(event) { + for (var _ref2 of this.keys) { + var _ref3 = _slicedToArray(_ref2, 2); + + var key = _ref3[0]; + var shortcut = _ref3[1]; + + if (this.doesEventMatchShortcut(event, shortcut)) { + this.eventEmitter.emit(key, event); + } + } + }, + + on(key, listener) { + if (typeof listener !== "function") { + throw new Error("KeyShortcuts.on() expects a function as " + "second argument"); + } + if (!this.keys.has(key)) { + var shortcut = KeyShortcuts.parseElectronKey(this.window, key); + // The key string is wrong and we were unable to compute the key shortcut + if (!shortcut) { + return; + } + this.keys.set(key, shortcut); + } + this.eventEmitter.on(key, listener); + }, + + off(key, listener) { + this.eventEmitter.off(key, listener); + } + }; + exports.KeyShortcuts = KeyShortcuts; + +/***/ }, +/* 30 */ +/***/ function(module, exports, __webpack_require__) { + + var Services = __webpack_require__(31); + var SplitBox = __webpack_require__(32); + // const SplitBoxCSS = require("./client/shared/components/splitter/SplitBox.css") + var rep = __webpack_require__(34).Rep; + // const repCSS = require("./client/shared/components/reps/reps.css"); + var Grip = __webpack_require__(44).Grip; + var sprintf = __webpack_require__(59).sprintf; + + module.exports = { + Services, + SplitBox, + // SplitBoxCSS, + rep, + // repCSS, + Grip, + sprintf + }; + +/***/ }, +/* 31 */ +/***/ function(module, exports) { + + module.exports = devtoolsRequire("Services"); + +/***/ }, +/* 32 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var ReactDOM = __webpack_require__(16); + var Draggable = React.createFactory(__webpack_require__(33)); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + /** + * This component represents a Splitter. The splitter supports vertical + * as well as horizontal mode. + */ + + var SplitBox = React.createClass({ + + propTypes: { + // Custom class name. You can use more names separated by a space. + className: PropTypes.string, + // Initial size of controlled panel. + initialSize: PropTypes.any, + // Optional initial width of controlled panel. + initialWidth: PropTypes.number, + // Optional initial height of controlled panel. + initialHeight: PropTypes.number, + // Left/top panel + startPanel: PropTypes.any, + // Min panel size. + minSize: PropTypes.any, + // Max panel size. + maxSize: PropTypes.any, + // Right/bottom panel + endPanel: PropTypes.any, + // True if the right/bottom panel should be controlled. + endPanelControl: PropTypes.bool, + // Size of the splitter handle bar. + splitterSize: PropTypes.number, + // True if the splitter bar is vertical (default is vertical). + vert: PropTypes.bool, + // Optional style properties passed into the splitbox + style: PropTypes.object + }, + + displayName: "SplitBox", + + getDefaultProps() { + return { + splitterSize: 5, + vert: true, + endPanelControl: false + }; + }, + + /** + * The state stores the current orientation (vertical or horizontal) + * and the current size (width/height). All these values can change + * during the component's life time. + */ + getInitialState() { + return { + vert: this.props.vert, + width: this.props.initialWidth || this.props.initialSize, + height: this.props.initialHeight || this.props.initialSize + }; + }, + + // Dragging Events + + /** + * Set 'resizing' cursor on entire document during splitter dragging. + * This avoids cursor-flickering that happens when the mouse leaves + * the splitter bar area (happens frequently). + */ + onStartMove() { + var splitBox = ReactDOM.findDOMNode(this); + var doc = splitBox.ownerDocument; + var defaultCursor = doc.documentElement.style.cursor; + doc.documentElement.style.cursor = this.state.vert ? "ew-resize" : "ns-resize"; + + splitBox.classList.add("dragging"); + + this.setState({ + defaultCursor: defaultCursor + }); + }, + + onStopMove() { + var splitBox = ReactDOM.findDOMNode(this); + var doc = splitBox.ownerDocument; + doc.documentElement.style.cursor = this.state.defaultCursor; + + splitBox.classList.remove("dragging"); + }, + + screenX() { + var borderWidth = (window.outerWidth - window.innerWidth) / 2; + return window.screenX + borderWidth; + }, + + screenY() { + var borderHeignt = window.outerHeight - window.innerHeight; + return window.screenY + borderHeignt; + }, + + /** + * Adjust size of the controlled panel. Depending on the current + * orientation we either remember the width or height of + * the splitter box. + */ + onMove(x, y) { + var node = ReactDOM.findDOMNode(this); + var doc = node.ownerDocument; + var win = doc.defaultView; + + var size = void 0; + var endPanelControl = this.props.endPanelControl; + + + if (this.state.vert) { + // Switch the control flag in case of RTL. Note that RTL + // has impact on vertical splitter only. + var dir = win.getComputedStyle(doc.documentElement).direction; + if (dir == "rtl") { + endPanelControl = !endPanelControl; + } + + var innerOffset = x - this.screenX(); + size = endPanelControl ? node.offsetLeft + node.offsetWidth - innerOffset : innerOffset - node.offsetLeft; + + this.setState({ + width: size + }); + } else { + var _innerOffset = y - this.screenY(); + size = endPanelControl ? node.offsetTop + node.offsetHeight - _innerOffset : _innerOffset - node.offsetTop; + + this.setState({ + height: size + }); + } + }, + + // Rendering + + render() { + var vert = this.state.vert; + var _props = this.props; + var startPanel = _props.startPanel; + var endPanel = _props.endPanel; + var endPanelControl = _props.endPanelControl; + var minSize = _props.minSize; + var maxSize = _props.maxSize; + var splitterSize = _props.splitterSize; + + + var style = Object.assign({}, this.props.style); + + // Calculate class names list. + var classNames = ["split-box"]; + classNames.push(vert ? "vert" : "horz"); + if (this.props.className) { + classNames = classNames.concat(this.props.className.split(" ")); + } + + var leftPanelStyle = void 0; + var rightPanelStyle = void 0; + + // Set proper size for panels depending on the current state. + if (vert) { + leftPanelStyle = { + maxWidth: endPanelControl ? null : maxSize, + minWidth: endPanelControl ? null : minSize, + width: endPanelControl ? null : this.state.width + }; + rightPanelStyle = { + maxWidth: endPanelControl ? maxSize : null, + minWidth: endPanelControl ? minSize : null, + width: endPanelControl ? this.state.width : null + }; + } else { + leftPanelStyle = { + maxHeight: endPanelControl ? null : maxSize, + minHeight: endPanelControl ? null : minSize, + height: endPanelControl ? null : this.state.height + }; + rightPanelStyle = { + maxHeight: endPanelControl ? maxSize : null, + minHeight: endPanelControl ? minSize : null, + height: endPanelControl ? this.state.height : null + }; + } + + // Calculate splitter size + var splitterStyle = { + flex: "0 0 " + splitterSize + "px" + }; + + return dom.div({ + className: classNames.join(" "), + style: style }, startPanel ? dom.div({ + className: endPanelControl ? "uncontrolled" : "controlled", + style: leftPanelStyle }, startPanel) : null, Draggable({ + className: "splitter", + style: splitterStyle, + onStart: this.onStartMove, + onStop: this.onStopMove, + onMove: this.onMove + }), endPanel ? dom.div({ + className: endPanelControl ? "controlled" : "uncontrolled", + style: rightPanelStyle }, endPanel) : null); + } + }); + + module.exports = SplitBox; + +/***/ }, +/* 33 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var React = __webpack_require__(2); + var ReactDOM = __webpack_require__(16); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + + var Draggable = React.createClass({ + displayName: "Draggable", + + propTypes: { + onMove: PropTypes.func.isRequired, + onStart: PropTypes.func, + onStop: PropTypes.func, + style: PropTypes.object, + className: PropTypes.string + }, + + startDragging(ev) { + ev.preventDefault(); + var doc = ReactDOM.findDOMNode(this).ownerDocument; + doc.addEventListener("mousemove", this.onMove); + doc.addEventListener("mouseup", this.onUp); + this.props.onStart && this.props.onStart(); + }, + + onMove(ev) { + ev.preventDefault(); + // Use screen coordinates so, moving mouse over iframes + // doesn't mangle (relative) coordinates. + this.props.onMove(ev.screenX, ev.screenY); + }, + + onUp(ev) { + ev.preventDefault(); + var doc = ReactDOM.findDOMNode(this).ownerDocument; + doc.removeEventListener("mousemove", this.onMove); + doc.removeEventListener("mouseup", this.onUp); + this.props.onStop && this.props.onStop(); + }, + + render() { + return dom.div({ + style: this.props.style, + className: this.props.className, + onMouseDown: this.startDragging + }); + } + }); + + module.exports = Draggable; + +/***/ }, +/* 34 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // Dependencies + var React = __webpack_require__(2); + + var _require = __webpack_require__(35); + + var isGrip = _require.isGrip; + + // Load all existing rep templates + + var _require2 = __webpack_require__(36); + + var Undefined = _require2.Undefined; + + var _require3 = __webpack_require__(37); + + var Null = _require3.Null; + + var _require4 = __webpack_require__(38); + + var StringRep = _require4.StringRep; + + var _require5 = __webpack_require__(39); + + var Number = _require5.Number; + + var _require6 = __webpack_require__(40); + + var ArrayRep = _require6.ArrayRep; + + var _require7 = __webpack_require__(42); + + var Obj = _require7.Obj; + + var _require8 = __webpack_require__(45); + + var SymbolRep = _require8.SymbolRep; + + // DOM types (grips) + + var _require9 = __webpack_require__(46); + + var Attribute = _require9.Attribute; + + var _require10 = __webpack_require__(47); + + var DateTime = _require10.DateTime; + + var _require11 = __webpack_require__(48); + + var Document = _require11.Document; + + var _require12 = __webpack_require__(49); + + var Event = _require12.Event; + + var _require13 = __webpack_require__(50); + + var Func = _require13.Func; + + var _require14 = __webpack_require__(51); + + var RegExp = _require14.RegExp; + + var _require15 = __webpack_require__(52); + + var StyleSheet = _require15.StyleSheet; + + var _require16 = __webpack_require__(53); + + var TextNode = _require16.TextNode; + + var _require17 = __webpack_require__(54); + + var Window = _require17.Window; + + var _require18 = __webpack_require__(55); + + var ObjectWithText = _require18.ObjectWithText; + + var _require19 = __webpack_require__(56); + + var ObjectWithURL = _require19.ObjectWithURL; + + var _require20 = __webpack_require__(57); + + var GripArray = _require20.GripArray; + + var _require21 = __webpack_require__(58); + + var GripMap = _require21.GripMap; + + var _require22 = __webpack_require__(44); + + var Grip = _require22.Grip; + + // List of all registered template. + // XXX there should be a way for extensions to register a new + // or modify an existing rep. + + var reps = [RegExp, StyleSheet, Event, DateTime, TextNode, Attribute, Func, ArrayRep, Document, Window, ObjectWithText, ObjectWithURL, GripArray, GripMap, Grip, Undefined, Null, StringRep, Number, SymbolRep]; + + /** + * Generic rep that is using for rendering native JS types or an object. + * The right template used for rendering is picked automatically according + * to the current value type. The value must be passed is as 'object' + * property. + */ + var Rep = React.createClass({ + displayName: "Rep", + + propTypes: { + object: React.PropTypes.any, + defaultRep: React.PropTypes.object, + mode: React.PropTypes.string + }, + + render: function () { + var rep = getRep(this.props.object, this.props.defaultRep); + return rep(this.props); + } + }); + + // Helpers + + /** + * Return a rep object that is responsible for rendering given + * object. + * + * @param object {Object} Object to be rendered in the UI. This + * can be generic JS object as well as a grip (handle to a remote + * debuggee object). + * + * @param defaultObject {React.Component} The default template + * that should be used to render given object if none is found. + */ + function getRep(object) { + var defaultRep = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Obj; + + var type = typeof object; + if (type == "object" && object instanceof String) { + type = "string"; + } else if (type == "object" && object.type === "symbol") { + type = "symbol"; + } + + if (isGrip(object)) { + type = object.class; + } + + for (var i = 0; i < reps.length; i++) { + var rep = reps[i]; + try { + // supportsObject could return weight (not only true/false + // but a number), which would allow to priorities templates and + // support better extensibility. + if (rep.supportsObject(object, type)) { + return React.createFactory(rep.rep); + } + } catch (err) { + console.error(err); + } + } + + return React.createFactory(defaultRep.rep); + } + + // Exports from this module + exports.Rep = Rep; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 35 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* globals URLSearchParams */ + /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + // Make this available to both AMD and CJS environments + + function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // Dependencies + var React = __webpack_require__(2); + + /** + * Create React factories for given arguments. + * Example: + * const { Rep } = createFactories(require("./rep")); + */ + function createFactories(args) { + var result = {}; + for (var p in args) { + result[p] = React.createFactory(args[p]); + } + return result; + } + + /** + * Returns true if the given object is a grip (see RDP protocol) + */ + function isGrip(object) { + return object && object.actor; + } + + function escapeNewLines(value) { + return value.replace(/\r/gm, "\\r").replace(/\n/gm, "\\n"); + } + + function cropMultipleLines(text, limit) { + return escapeNewLines(cropString(text, limit)); + } + + function cropString(text, limit, alternativeText) { + if (!alternativeText) { + alternativeText = "\u2026"; + } + + // Make sure it's a string. + text = text + ""; + + // Crop the string only if a limit is actually specified. + if (!limit || limit <= 0) { + return text; + } + + // Set the limit at least to the length of the alternative text + // plus one character of the original text. + if (limit <= alternativeText.length) { + limit = alternativeText.length + 1; + } + + var halfLimit = (limit - alternativeText.length) / 2; + + if (text.length > limit) { + return text.substr(0, Math.ceil(halfLimit)) + alternativeText + text.substr(text.length - Math.floor(halfLimit)); + } + + return text; + } + + function parseURLParams(url) { + url = new URL(url); + return parseURLEncodedText(url.searchParams); + } + + function parseURLEncodedText(text) { + var params = []; + + // In case the text is empty just return the empty parameters + if (text == "") { + return params; + } + + var searchParams = new URLSearchParams(text); + var entries = [].concat(_toConsumableArray(searchParams.entries())); + return entries.map(entry => { + return { + name: entry[0], + value: entry[1] + }; + }); + } + + function getFileName(url) { + var split = splitURLBase(url); + return split.name; + } + + function splitURLBase(url) { + if (!isDataURL(url)) { + return splitURLTrue(url); + } + return {}; + } + + function getURLDisplayString(url) { + return cropString(url); + } + + function isDataURL(url) { + return url && url.substr(0, 5) == "data:"; + } + + function splitURLTrue(url) { + var reSplitFile = /(.*?):\/{2,3}([^\/]*)(.*?)([^\/]*?)($|\?.*)/; + var m = reSplitFile.exec(url); + + if (!m) { + return { + name: url, + path: url + }; + } else if (m[4] == "" && m[5] == "") { + return { + protocol: m[1], + domain: m[2], + path: m[3], + name: m[3] != "/" ? m[3] : m[2] + }; + } + + return { + protocol: m[1], + domain: m[2], + path: m[2] + m[3], + name: m[4] + m[5] + }; + } + + // Exports from this module + exports.createFactories = createFactories; + exports.isGrip = isGrip; + exports.cropString = cropString; + exports.cropMultipleLines = cropMultipleLines; + exports.parseURLParams = parseURLParams; + exports.parseURLEncodedText = parseURLEncodedText; + exports.getFileName = getFileName; + exports.getURLDisplayString = getURLDisplayString; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 36 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // Dependencies + var React = __webpack_require__(2); + + // Shortcuts + var span = React.DOM.span; + + /** + * Renders undefined value + */ + + var Undefined = React.createClass({ + displayName: "UndefinedRep", + + render: function () { + return span({ className: "objectBox objectBox-undefined" }, "undefined"); + } + }); + + function supportsObject(object, type) { + if (object && object.type && object.type == "undefined") { + return true; + } + + return type == "undefined"; + } + + // Exports from this module + + exports.Undefined = { + rep: Undefined, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 37 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // Dependencies + var React = __webpack_require__(2); + + // Shortcuts + var span = React.DOM.span; + + /** + * Renders null value + */ + + var Null = React.createClass({ + displayName: "NullRep", + + render: function () { + return span({ className: "objectBox objectBox-null" }, "null"); + } + }); + + function supportsObject(object, type) { + if (object && object.type && object.type == "null") { + return true; + } + + return object == null; + } + + // Exports from this module + + exports.Null = { + rep: Null, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 38 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // Dependencies + var React = __webpack_require__(2); + + var _require = __webpack_require__(35); + + var cropMultipleLines = _require.cropMultipleLines; + + // Shortcuts + + var span = React.DOM.span; + + /** + * Renders a string. String value is enclosed within quotes. + */ + + var StringRep = React.createClass({ + displayName: "StringRep", + + propTypes: { + useQuotes: React.PropTypes.bool + }, + + getDefaultProps: function () { + return { + useQuotes: true + }; + }, + + render: function () { + var text = this.props.object; + var member = this.props.member; + if (member && member.open) { + return span({ className: "objectBox objectBox-string" }, "\"" + text + "\""); + } + + var croppedString = this.props.cropLimit ? cropMultipleLines(text, this.props.cropLimit) : cropMultipleLines(text); + + var formattedString = this.props.useQuotes ? "\"" + croppedString + "\"" : croppedString; + + return span({ className: "objectBox objectBox-string" }, formattedString); + } + }); + + function supportsObject(object, type) { + return type == "string"; + } + + // Exports from this module + + exports.StringRep = { + rep: StringRep, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 39 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // Dependencies + var React = __webpack_require__(2); + + // Shortcuts + var span = React.DOM.span; + + /** + * Renders a number + */ + + var Number = React.createClass({ + displayName: "Number", + + stringify: function (object) { + var isNegativeZero = Object.is(object, -0) || object.type && object.type == "-0"; + + return isNegativeZero ? "-0" : String(object); + }, + + render: function () { + var value = this.props.object; + + return span({ className: "objectBox objectBox-number" }, this.stringify(value)); + } + }); + + function supportsObject(object, type) { + return type == "boolean" || type == "number" || type == "object" && object.type == "-0"; + } + + // Exports from this module + + exports.Number = { + rep: Number, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 40 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // Dependencies + var React = __webpack_require__(2); + + var _require = __webpack_require__(35); + + var createFactories = _require.createFactories; + + var _createFactories = createFactories(__webpack_require__(41)); + + var Caption = _createFactories.Caption; + + // Shortcuts + + var DOM = React.DOM; + + /** + * Renders an array. The array is enclosed by left and right bracket + * and the max number of rendered items depends on the current mode. + */ + var ArrayRep = React.createClass({ + displayName: "ArrayRep", + + getTitle: function (object, context) { + return "[" + object.length + "]"; + }, + + arrayIterator: function (array, max) { + var items = []; + var delim = void 0; + + for (var i = 0; i < array.length && i < max; i++) { + try { + var value = array[i]; + + delim = i == array.length - 1 ? "" : ", "; + + items.push(ItemRep({ + key: i, + object: value, + // Hardcode tiny mode to avoid recursive handling. + mode: "tiny", + delim: delim + })); + } catch (exc) { + items.push(ItemRep({ + key: i, + object: exc, + mode: "tiny", + delim: delim + })); + } + } + + if (array.length > max) { + var objectLink = this.props.objectLink || DOM.span; + items.push(Caption({ + key: "more", + object: objectLink({ + object: this.props.object + }, array.length - max + " more…") + })); + } + + return items; + }, + + /** + * Returns true if the passed object is an array with additional (custom) + * properties, otherwise returns false. Custom properties should be + * displayed in extra expandable section. + * + * Example array with a custom property. + * let arr = [0, 1]; + * arr.myProp = "Hello"; + * + * @param {Array} array The array object. + */ + hasSpecialProperties: function (array) { + function isInteger(x) { + var y = parseInt(x, 10); + if (isNaN(y)) { + return false; + } + return x === y.toString(); + } + + var props = Object.getOwnPropertyNames(array); + for (var i = 0; i < props.length; i++) { + var p = props[i]; + + // Valid indexes are skipped + if (isInteger(p)) { + continue; + } + + // Ignore standard 'length' property, anything else is custom. + if (p != "length") { + return true; + } + } + + return false; + }, + + // Event Handlers + + onToggleProperties: function (event) {}, + + onClickBracket: function (event) {}, + + render: function () { + var mode = this.props.mode || "short"; + var object = this.props.object; + var items = void 0; + var brackets = void 0; + var needSpace = function (space) { + return space ? { left: "[ ", right: " ]" } : { left: "[", right: "]" }; + }; + + if (mode == "tiny") { + var isEmpty = object.length === 0; + items = DOM.span({ className: "length" }, isEmpty ? "" : object.length); + brackets = needSpace(false); + } else { + var max = mode == "short" ? 3 : 300; + items = this.arrayIterator(object, max); + brackets = needSpace(items.length > 0); + } + + var objectLink = this.props.objectLink || DOM.span; + + return DOM.span({ + className: "objectBox objectBox-array" }, objectLink({ + className: "arrayLeftBracket", + object: object + }, brackets.left), items, objectLink({ + className: "arrayRightBracket", + object: object + }, brackets.right), DOM.span({ + className: "arrayProperties", + role: "group" })); + } + }); + + /** + * Renders array item. Individual values are separated by a comma. + */ + var ItemRep = React.createFactory(React.createClass({ + displayName: "ItemRep", + + render: function () { + var _createFactories2 = createFactories(__webpack_require__(34)); + + var Rep = _createFactories2.Rep; + + + var object = this.props.object; + var delim = this.props.delim; + var mode = this.props.mode; + return DOM.span({}, Rep({ object: object, mode: mode }), delim); + } + })); + + function supportsObject(object, type) { + return Array.isArray(object) || Object.prototype.toString.call(object) === "[object Arguments]"; + } + + // Exports from this module + exports.ArrayRep = { + rep: ArrayRep, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 41 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // Dependencies + var React = __webpack_require__(2); + var DOM = React.DOM; + + /** + * Renders a caption. This template is used by other components + * that needs to distinguish between a simple text/value and a label. + */ + var Caption = React.createClass({ + displayName: "Caption", + + render: function () { + return DOM.span({ "className": "caption" }, this.props.object); + } + }); + + // Exports from this module + exports.Caption = Caption; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 42 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // Dependencies + var React = __webpack_require__(2); + + var _require = __webpack_require__(35); + + var createFactories = _require.createFactories; + + var _createFactories = createFactories(__webpack_require__(41)); + + var Caption = _createFactories.Caption; + + var _createFactories2 = createFactories(__webpack_require__(43)); + + var PropRep = _createFactories2.PropRep; + // Shortcuts + + var span = React.DOM.span; + /** + * Renders an object. An object is represented by a list of its + * properties enclosed in curly brackets. + */ + + var Obj = React.createClass({ + displayName: "Obj", + + propTypes: { + object: React.PropTypes.object, + mode: React.PropTypes.string + }, + + getTitle: function (object) { + var className = object && object.class ? object.class : "Object"; + if (this.props.objectLink) { + return this.props.objectLink({ + object: object + }, className); + } + return className; + }, + + safePropIterator: function (object, max) { + max = typeof max === "undefined" ? 3 : max; + try { + return this.propIterator(object, max); + } catch (err) { + console.error(err); + } + return []; + }, + + propIterator: function (object, max) { + var isInterestingProp = (t, value) => { + // Do not pick objects, it could cause recursion. + return t == "boolean" || t == "number" || t == "string" && value; + }; + + // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=945377 + if (Object.prototype.toString.call(object) === "[object Generator]") { + object = Object.getPrototypeOf(object); + } + + // Object members with non-empty values are preferred since it gives the + // user a better overview of the object. + var props = this.getProps(object, max, isInterestingProp); + + if (props.length <= max) { + // There are not enough props yet (or at least, not enough props to + // be able to know whether we should print "more…" or not). + // Let's display also empty members and functions. + props = props.concat(this.getProps(object, max, (t, value) => { + return !isInterestingProp(t, value); + })); + } + + if (props.length > max) { + props.pop(); + var objectLink = this.props.objectLink || span; + + props.push(Caption({ + key: "more", + object: objectLink({ + object: object + }, Object.keys(object).length - max + " more…") + })); + } else if (props.length > 0) { + // Remove the last comma. + props[props.length - 1] = React.cloneElement(props[props.length - 1], { delim: "" }); + } + + return props; + }, + + getProps: function (object, max, filter) { + var props = []; + + max = max || 3; + if (!object) { + return props; + } + + // Hardcode tiny mode to avoid recursive handling. + var mode = "tiny"; + + try { + for (var name in object) { + if (props.length > max) { + return props; + } + + var value = void 0; + try { + value = object[name]; + } catch (exc) { + continue; + } + + var t = typeof value; + if (filter(t, value)) { + props.push(PropRep({ + key: name, + mode: mode, + name: name, + object: value, + equal: ": ", + delim: ", " + })); + } + } + } catch (err) { + console.error(err); + } + + return props; + }, + + render: function () { + var object = this.props.object; + var props = this.safePropIterator(object); + var objectLink = this.props.objectLink || span; + + if (this.props.mode == "tiny" || !props.length) { + return span({ className: "objectBox objectBox-object" }, objectLink({ className: "objectTitle" }, this.getTitle(object))); + } + + return span({ className: "objectBox objectBox-object" }, this.getTitle(object), objectLink({ + className: "objectLeftBrace", + object: object + }, " { "), props, objectLink({ + className: "objectRightBrace", + object: object + }, " }")); + } + }); + function supportsObject(object, type) { + return true; + } + + // Exports from this module + exports.Obj = { + rep: Obj, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 43 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + var React = __webpack_require__(2); + + var _require = __webpack_require__(35); + + var createFactories = _require.createFactories; + var span = React.DOM.span; + + /** + * Property for Obj (local JS objects), Grip (remote JS objects) + * and GripMap (remote JS maps and weakmaps) reps. + * It's used to render object properties. + */ + + var PropRep = React.createFactory(React.createClass({ + displayName: "PropRep", + + propTypes: { + // Property name. + name: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.object]).isRequired, + // Equal character rendered between property name and value. + equal: React.PropTypes.string, + // Delimiter character used to separate individual properties. + delim: React.PropTypes.string, + mode: React.PropTypes.string + }, + + render: function () { + var _require2 = __webpack_require__(44); + + var Grip = _require2.Grip; + + var _createFactories = createFactories(__webpack_require__(34)); + + var Rep = _createFactories.Rep; + + + var key = void 0; + // The key can be a simple string, for plain objects, + // or another object for maps and weakmaps. + if (typeof this.props.name === "string") { + key = span({ "className": "nodeName" }, this.props.name); + } else { + key = Rep({ + object: this.props.name, + mode: this.props.mode || "tiny", + defaultRep: Grip, + objectLink: this.props.objectLink + }); + } + + return span({}, key, span({ + "className": "objectEqual" + }, this.props.equal), Rep(this.props), span({ + "className": "objectComma" + }, this.props.delim)); + } + })); + + // Exports from this module + exports.PropRep = PropRep; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 44 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // ReactJS + var React = __webpack_require__(2); + // Dependencies + + var _require = __webpack_require__(35); + + var createFactories = _require.createFactories; + var isGrip = _require.isGrip; + + var _createFactories = createFactories(__webpack_require__(41)); + + var Caption = _createFactories.Caption; + + var _createFactories2 = createFactories(__webpack_require__(43)); + + var PropRep = _createFactories2.PropRep; + // Shortcuts + + var span = React.DOM.span; + + /** + * Renders generic grip. Grip is client representation + * of remote JS object and is used as an input object + * for this rep component. + */ + + var GripRep = React.createClass({ + displayName: "Grip", + + propTypes: { + object: React.PropTypes.object.isRequired, + mode: React.PropTypes.string, + isInterestingProp: React.PropTypes.func + }, + + getTitle: function (object) { + if (this.props.objectLink) { + return this.props.objectLink({ + object: object + }, object.class); + } + return object.class || "Object"; + }, + + safePropIterator: function (object, max) { + max = typeof max === "undefined" ? 3 : max; + try { + return this.propIterator(object, max); + } catch (err) { + console.error(err); + } + return []; + }, + + propIterator: function (object, max) { + // Property filter. Show only interesting properties to the user. + var isInterestingProp = this.props.isInterestingProp || ((type, value) => { + return type == "boolean" || type == "number" || type == "string" && value.length != 0; + }); + + var ownProperties = object.preview ? object.preview.ownProperties : []; + var indexes = this.getPropIndexes(ownProperties, max, isInterestingProp); + if (indexes.length < max && indexes.length < object.ownPropertyLength) { + // There are not enough props yet. Then add uninteresting props to display them. + indexes = indexes.concat(this.getPropIndexes(ownProperties, max - indexes.length, (t, value, name) => { + return !isInterestingProp(t, value, name); + })); + } + + var props = this.getProps(ownProperties, indexes); + if (props.length < object.ownPropertyLength) { + // There are some undisplayed props. Then display "more...". + var objectLink = this.props.objectLink || span; + + props.push(Caption({ + key: "more", + object: objectLink({ + object: object + }, (object ? object.ownPropertyLength : 0) - max + " more…") + })); + } else if (props.length > 0) { + // Remove the last comma. + // NOTE: do not change comp._store.props directly to update a property, + // it should be re-rendered or cloned with changed props + var last = props.length - 1; + props[last] = React.cloneElement(props[last], { + delim: "" + }); + } + + return props; + }, + + /** + * Get props ordered by index. + * + * @param {Object} ownProperties Props object. + * @param {Array} indexes Indexes of props. + * @return {Array} Props. + */ + getProps: function (ownProperties, indexes) { + var props = []; + + // Make indexes ordered by ascending. + indexes.sort(function (a, b) { + return a - b; + }); + + indexes.forEach(i => { + var name = Object.keys(ownProperties)[i]; + var prop = ownProperties[name]; + var value = prop.value !== undefined ? prop.value : prop; + props.push(PropRep(Object.assign({}, this.props, { + key: name, + mode: "tiny", + name: name, + object: value, + equal: ": ", + delim: ", ", + defaultRep: Grip + }))); + }); + + return props; + }, + + /** + * Get the indexes of props in the object. + * + * @param {Object} ownProperties Props object. + * @param {Number} max The maximum length of indexes array. + * @param {Function} filter Filter the props you want. + * @return {Array} Indexes of interesting props in the object. + */ + getPropIndexes: function (ownProperties, max, filter) { + var indexes = []; + + try { + var i = 0; + for (var name in ownProperties) { + if (indexes.length >= max) { + return indexes; + } + + var prop = ownProperties[name]; + var value = prop.value !== undefined ? prop.value : prop; + + // Type is specified in grip's "class" field and for primitive + // values use typeof. + var type = value.class || typeof value; + type = type.toLowerCase(); + + if (filter(type, value, name)) { + indexes.push(i); + } + i++; + } + } catch (err) { + console.error(err); + } + + return indexes; + }, + + render: function () { + var object = this.props.object; + var props = this.safePropIterator(object, this.props.mode == "long" ? 100 : 3); + + var objectLink = this.props.objectLink || span; + if (this.props.mode == "tiny" || !props.length) { + return span({ className: "objectBox objectBox-object" }, this.getTitle(object), objectLink({ + className: "objectLeftBrace", + object: object + }, "")); + } + + return span({ className: "objectBox objectBox-object" }, this.getTitle(object), objectLink({ + className: "objectLeftBrace", + object: object + }, " { "), props, objectLink({ + className: "objectRightBrace", + object: object + }, " }")); + } + }); + + // Registration + function supportsObject(object, type) { + if (!isGrip(object)) { + return false; + } + return object.preview && object.preview.ownProperties; + } + + var Grip = { + rep: GripRep, + supportsObject: supportsObject + }; + + // Exports from this module + exports.Grip = Grip; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 45 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // Dependencies + var React = __webpack_require__(2); + + // Shortcuts + var span = React.DOM.span; + + /** + * Renders a symbol. + */ + + var SymbolRep = React.createClass({ + displayName: "SymbolRep", + + propTypes: { + object: React.PropTypes.object.isRequired + }, + + render: function () { + var object = this.props.object; + var name = object.name; + + + return span({ className: "objectBox objectBox-symbol" }, `Symbol(${ name || "" })`); + } + }); + + function supportsObject(object, type) { + return type == "symbol"; + } + + // Exports from this module + exports.SymbolRep = { + rep: SymbolRep, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 46 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // ReactJS + var React = __webpack_require__(2); + + // Reps + + var _require = __webpack_require__(35); + + var createFactories = _require.createFactories; + var isGrip = _require.isGrip; + + var _require2 = __webpack_require__(38); + + var StringRep = _require2.StringRep; + + // Shortcuts + + var span = React.DOM.span; + + var _createFactories = createFactories(StringRep); + + var StringRepFactory = _createFactories.rep; + + /** + * Renders DOM attribute + */ + + var Attribute = React.createClass({ + displayName: "Attr", + + propTypes: { + object: React.PropTypes.object.isRequired + }, + + getTitle: function (grip) { + return grip.preview.nodeName; + }, + + render: function () { + var grip = this.props.object; + var value = grip.preview.value; + var objectLink = this.props.objectLink || span; + + return objectLink({ className: "objectLink-Attr" }, span({}, span({ className: "attrTitle" }, this.getTitle(grip)), span({ className: "attrEqual" }, "="), StringRepFactory({ object: value }))); + } + }); + + // Registration + + function supportsObject(grip, type) { + if (!isGrip(grip)) { + return false; + } + + return type == "Attr" && grip.preview; + } + + exports.Attribute = { + rep: Attribute, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 47 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // ReactJS + var React = __webpack_require__(2); + + // Reps + + var _require = __webpack_require__(35); + + var isGrip = _require.isGrip; + + // Shortcuts + + var span = React.DOM.span; + + /** + * Used to render JS built-in Date() object. + */ + + var DateTime = React.createClass({ + displayName: "Date", + + propTypes: { + object: React.PropTypes.object.isRequired + }, + + getTitle: function (grip) { + if (this.props.objectLink) { + return this.props.objectLink({ + object: grip + }, grip.class + " "); + } + return ""; + }, + + render: function () { + var grip = this.props.object; + return span({ className: "objectBox" }, this.getTitle(grip), span({ className: "Date" }, new Date(grip.preview.timestamp).toISOString())); + } + }); + + // Registration + + function supportsObject(grip, type) { + if (!isGrip(grip)) { + return false; + } + + return type == "Date" && grip.preview; + } + + // Exports from this module + exports.DateTime = { + rep: DateTime, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 48 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // ReactJS + var React = __webpack_require__(2); + + // Reps + + var _require = __webpack_require__(35); + + var isGrip = _require.isGrip; + var getURLDisplayString = _require.getURLDisplayString; + + // Shortcuts + + var span = React.DOM.span; + + /** + * Renders DOM document object. + */ + + var Document = React.createClass({ + displayName: "Document", + + propTypes: { + object: React.PropTypes.object.isRequired + }, + + getLocation: function (grip) { + var location = grip.preview.location; + return location ? getURLDisplayString(location) : ""; + }, + + getTitle: function (grip) { + if (this.props.objectLink) { + return span({ className: "objectBox" }, this.props.objectLink({ + object: grip + }, grip.class + " ")); + } + return ""; + }, + + getTooltip: function (doc) { + return doc.location.href; + }, + + render: function () { + var grip = this.props.object; + + return span({ className: "objectBox objectBox-object" }, this.getTitle(grip), span({ className: "objectPropValue" }, this.getLocation(grip))); + } + }); + + // Registration + + function supportsObject(object, type) { + if (!isGrip(object)) { + return false; + } + + return object.preview && type == "HTMLDocument"; + } + + // Exports from this module + exports.Document = { + rep: Document, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 49 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // ReactJS + var React = __webpack_require__(2); + + // Reps + + var _require = __webpack_require__(35); + + var createFactories = _require.createFactories; + var isGrip = _require.isGrip; + + var _createFactories = createFactories(__webpack_require__(44).Grip); + + var rep = _createFactories.rep; + + /** + * Renders DOM event objects. + */ + + var Event = React.createClass({ + displayName: "event", + + propTypes: { + object: React.PropTypes.object.isRequired + }, + + render: function () { + // Use `Object.assign` to keep `this.props` without changes because: + // 1. JSON.stringify/JSON.parse is slow. + // 2. Immutable.js is planned for the future. + var props = Object.assign({}, this.props); + props.object = Object.assign({}, this.props.object); + props.object.preview = Object.assign({}, this.props.object.preview); + props.object.preview.ownProperties = props.object.preview.properties; + delete props.object.preview.properties; + props.object.ownPropertyLength = Object.keys(props.object.preview.ownProperties).length; + + switch (props.object.class) { + case "MouseEvent": + props.isInterestingProp = (type, value, name) => { + return name == "clientX" || name == "clientY" || name == "layerX" || name == "layerY"; + }; + break; + case "KeyboardEvent": + props.isInterestingProp = (type, value, name) => { + return name == "key" || name == "charCode" || name == "keyCode"; + }; + break; + case "MessageEvent": + props.isInterestingProp = (type, value, name) => { + return name == "isTrusted" || name == "data"; + }; + break; + } + return rep(props); + } + }); + + // Registration + + function supportsObject(grip, type) { + if (!isGrip(grip)) { + return false; + } + + return grip.preview && grip.preview.kind == "DOMEvent"; + } + + // Exports from this module + exports.Event = { + rep: Event, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 50 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // ReactJS + var React = __webpack_require__(2); + + // Reps + + var _require = __webpack_require__(35); + + var isGrip = _require.isGrip; + var cropString = _require.cropString; + + // Shortcuts + + var span = React.DOM.span; + + /** + * This component represents a template for Function objects. + */ + + var Func = React.createClass({ + displayName: "Func", + + propTypes: { + object: React.PropTypes.object.isRequired + }, + + getTitle: function (grip) { + if (this.props.objectLink) { + return this.props.objectLink({ + object: grip + }, "function "); + } + return ""; + }, + + summarizeFunction: function (grip) { + var name = grip.userDisplayName || grip.displayName || grip.name || "function"; + return cropString(name + "()", 100); + }, + + render: function () { + var grip = this.props.object; + + return span({ className: "objectBox objectBox-function" }, this.getTitle(grip), this.summarizeFunction(grip)); + } + }); + + // Registration + + function supportsObject(grip, type) { + if (!isGrip(grip)) { + return type == "function"; + } + + return type == "Function"; + } + + // Exports from this module + + exports.Func = { + rep: Func, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 51 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // ReactJS + var React = __webpack_require__(2); + + // Reps + + var _require = __webpack_require__(35); + + var isGrip = _require.isGrip; + + // Shortcuts + + var span = React.DOM.span; + + /** + * Renders a grip object with regular expression. + */ + + var RegExp = React.createClass({ + displayName: "regexp", + + propTypes: { + object: React.PropTypes.object.isRequired + }, + + getSource: function (grip) { + return grip.displayString; + }, + + render: function () { + var grip = this.props.object; + var objectLink = this.props.objectLink || span; + + return span({ className: "objectBox objectBox-regexp" }, objectLink({ + object: grip, + className: "regexpSource" + }, this.getSource(grip))); + } + }); + + // Registration + + function supportsObject(object, type) { + if (!isGrip(object)) { + return false; + } + + return type == "RegExp"; + } + + // Exports from this module + exports.RegExp = { + rep: RegExp, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 52 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // ReactJS + var React = __webpack_require__(2); + + // Reps + + var _require = __webpack_require__(35); + + var isGrip = _require.isGrip; + var getURLDisplayString = _require.getURLDisplayString; + + // Shortcuts + + var DOM = React.DOM; + + /** + * Renders a grip representing CSSStyleSheet + */ + var StyleSheet = React.createClass({ + displayName: "object", + + propTypes: { + object: React.PropTypes.object.isRequired + }, + + getTitle: function (grip) { + var title = "StyleSheet "; + if (this.props.objectLink) { + return DOM.span({ className: "objectBox" }, this.props.objectLink({ + object: grip + }, title)); + } + return title; + }, + + getLocation: function (grip) { + // Embedded stylesheets don't have URL and so, no preview. + var url = grip.preview ? grip.preview.url : ""; + return url ? getURLDisplayString(url) : ""; + }, + + render: function () { + var grip = this.props.object; + + return DOM.span({ className: "objectBox objectBox-object" }, this.getTitle(grip), DOM.span({ className: "objectPropValue" }, this.getLocation(grip))); + } + }); + + // Registration + + function supportsObject(object, type) { + if (!isGrip(object)) { + return false; + } + + return type == "CSSStyleSheet"; + } + + // Exports from this module + + exports.StyleSheet = { + rep: StyleSheet, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 53 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // ReactJS + var React = __webpack_require__(2); + + // Reps + + var _require = __webpack_require__(35); + + var isGrip = _require.isGrip; + var cropMultipleLines = _require.cropMultipleLines; + + // Shortcuts + + var DOM = React.DOM; + + /** + * Renders DOM #text node. + */ + var TextNode = React.createClass({ + displayName: "TextNode", + + propTypes: { + object: React.PropTypes.object.isRequired, + mode: React.PropTypes.string + }, + + getTextContent: function (grip) { + return cropMultipleLines(grip.preview.textContent); + }, + + getTitle: function (grip) { + if (this.props.objectLink) { + return this.props.objectLink({ + object: grip + }, "#text"); + } + return ""; + }, + + render: function () { + var grip = this.props.object; + var mode = this.props.mode || "short"; + + if (mode == "short" || mode == "tiny") { + return DOM.span({ className: "objectBox objectBox-textNode" }, this.getTitle(grip), "\"" + this.getTextContent(grip) + "\""); + } + + var objectLink = this.props.objectLink || DOM.span; + return DOM.span({ className: "objectBox objectBox-textNode" }, this.getTitle(grip), objectLink({ + object: grip + }, "<"), DOM.span({ className: "nodeTag" }, "TextNode"), " textContent=\"", DOM.span({ className: "nodeValue" }, this.getTextContent(grip)), "\"", objectLink({ + object: grip + }, ">;")); + } + }); + + // Registration + + function supportsObject(grip, type) { + if (!isGrip(grip)) { + return false; + } + + return grip.preview && grip.class == "Text"; + } + + // Exports from this module + exports.TextNode = { + rep: TextNode, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 54 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // ReactJS + var React = __webpack_require__(2); + + // Reps + + var _require = __webpack_require__(35); + + var isGrip = _require.isGrip; + var getURLDisplayString = _require.getURLDisplayString; + + // Shortcuts + + var DOM = React.DOM; + + /** + * Renders a grip representing a window. + */ + var Window = React.createClass({ + displayName: "Window", + + propTypes: { + object: React.PropTypes.object.isRequired, + mode: React.PropTypes.string + }, + + getTitle: function (grip) { + if (this.props.objectLink) { + return DOM.span({ className: "objectBox" }, this.props.objectLink({ + object: grip + }, grip.class + " ")); + } + return ""; + }, + + getLocation: function (grip) { + return getURLDisplayString(grip.preview.url); + }, + + getDisplayValue: function (grip) { + if (this.props.mode === "tiny") { + return grip.isGlobal ? "Global" : "Window"; + } else { + return this.getLocation(grip); + } + }, + + render: function () { + var grip = this.props.object; + + return DOM.span({ className: "objectBox objectBox-Window" }, this.getTitle(grip), DOM.span({ className: "objectPropValue" }, this.getDisplayValue(grip))); + } + }); + + // Registration + + function supportsObject(object, type) { + if (!isGrip(object)) { + return false; + } + + return object.preview && type == "Window"; + } + + // Exports from this module + exports.Window = { + rep: Window, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 55 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // ReactJS + var React = __webpack_require__(2); + + // Reps + + var _require = __webpack_require__(35); + + var isGrip = _require.isGrip; + + // Shortcuts + + var span = React.DOM.span; + + /** + * Renders a grip object with textual data. + */ + + var ObjectWithText = React.createClass({ + displayName: "ObjectWithText", + + propTypes: { + object: React.PropTypes.object.isRequired + }, + + getTitle: function (grip) { + if (this.props.objectLink) { + return span({ className: "objectBox" }, this.props.objectLink({ + object: grip + }, this.getType(grip) + " ")); + } + return ""; + }, + + getType: function (grip) { + return grip.class; + }, + + getDescription: function (grip) { + return "\"" + grip.preview.text + "\""; + }, + + render: function () { + var grip = this.props.object; + return span({ className: "objectBox objectBox-" + this.getType(grip) }, this.getTitle(grip), span({ className: "objectPropValue" }, this.getDescription(grip))); + } + }); + + // Registration + + function supportsObject(grip, type) { + if (!isGrip(grip)) { + return false; + } + + return grip.preview && grip.preview.kind == "ObjectWithText"; + } + + // Exports from this module + exports.ObjectWithText = { + rep: ObjectWithText, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 56 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // ReactJS + var React = __webpack_require__(2); + + // Reps + + var _require = __webpack_require__(35); + + var isGrip = _require.isGrip; + var getURLDisplayString = _require.getURLDisplayString; + + // Shortcuts + + var span = React.DOM.span; + + /** + * Renders a grip object with URL data. + */ + + var ObjectWithURL = React.createClass({ + displayName: "ObjectWithURL", + + propTypes: { + object: React.PropTypes.object.isRequired + }, + + getTitle: function (grip) { + if (this.props.objectLink) { + return span({ className: "objectBox" }, this.props.objectLink({ + object: grip + }, this.getType(grip) + " ")); + } + return ""; + }, + + getType: function (grip) { + return grip.class; + }, + + getDescription: function (grip) { + return getURLDisplayString(grip.preview.url); + }, + + render: function () { + var grip = this.props.object; + return span({ className: "objectBox objectBox-" + this.getType(grip) }, this.getTitle(grip), span({ className: "objectPropValue" }, this.getDescription(grip))); + } + }); + + // Registration + + function supportsObject(grip, type) { + if (!isGrip(grip)) { + return false; + } + + return grip.preview && grip.preview.kind == "ObjectWithURL"; + } + + // Exports from this module + exports.ObjectWithURL = { + rep: ObjectWithURL, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 57 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + // Make this available to both AMD and CJS environments + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // Dependencies + var React = __webpack_require__(2); + + var _require = __webpack_require__(35); + + var createFactories = _require.createFactories; + var isGrip = _require.isGrip; + + var _createFactories = createFactories(__webpack_require__(41)); + + var Caption = _createFactories.Caption; + + // Shortcuts + + var span = React.DOM.span; + + /** + * Renders an array. The array is enclosed by left and right bracket + * and the max number of rendered items depends on the current mode. + */ + + var GripArray = React.createClass({ + displayName: "GripArray", + + propTypes: { + object: React.PropTypes.object.isRequired, + mode: React.PropTypes.string, + provider: React.PropTypes.object + }, + + getLength: function (grip) { + return grip.preview ? grip.preview.length : 0; + }, + + getTitle: function (object, context) { + var objectLink = this.props.objectLink || span; + if (this.props.mode != "tiny") { + return objectLink({ + object: object + }, object.class + " "); + } + return ""; + }, + + arrayIterator: function (grip, max) { + var items = []; + + if (!grip.preview || !grip.preview.length) { + return items; + } + + var array = grip.preview.items; + if (!array) { + return items; + } + + var delim = void 0; + // number of grip.preview.items is limited to 10, but we may have more + // items in grip-array + var delimMax = grip.preview.length > array.length ? array.length : array.length - 1; + var provider = this.props.provider; + + for (var i = 0; i < array.length && i < max; i++) { + try { + var itemGrip = array[i]; + var value = provider ? provider.getValue(itemGrip) : itemGrip; + + delim = i == delimMax ? "" : ", "; + + items.push(GripArrayItem(Object.assign({}, this.props, { + key: i, + object: value, + delim: delim }))); + } catch (exc) { + items.push(GripArrayItem(Object.assign({}, this.props, { + object: exc, + delim: delim, + key: i }))); + } + } + if (array.length > max || grip.preview.length > array.length) { + var objectLink = this.props.objectLink || span; + var leftItemNum = grip.preview.length - max > 0 ? grip.preview.length - max : grip.preview.length - array.length; + items.push(Caption({ + key: "more", + object: objectLink({ + object: this.props.object + }, leftItemNum + " more…") + })); + } + + return items; + }, + + render: function () { + var mode = this.props.mode || "short"; + var object = this.props.object; + + var items = void 0; + var brackets = void 0; + var needSpace = function (space) { + return space ? { left: "[ ", right: " ]" } : { left: "[", right: "]" }; + }; + + if (mode == "tiny") { + var objectLength = this.getLength(object); + var isEmpty = objectLength === 0; + items = span({ className: "length" }, isEmpty ? "" : objectLength); + brackets = needSpace(false); + } else { + var max = mode == "short" ? 3 : 300; + items = this.arrayIterator(object, max); + brackets = needSpace(items.length > 0); + } + + var objectLink = this.props.objectLink || span; + var title = this.getTitle(object); + + return span({ + className: "objectBox objectBox-array" }, title, objectLink({ + className: "arrayLeftBracket", + object: object + }, brackets.left), items, objectLink({ + className: "arrayRightBracket", + object: object + }, brackets.right), span({ + className: "arrayProperties", + role: "group" })); + } + }); + + /** + * Renders array item. Individual values are separated by + * a delimiter (a comma by default). + */ + var GripArrayItem = React.createFactory(React.createClass({ + displayName: "GripArrayItem", + + propTypes: { + delim: React.PropTypes.string + }, + + render: function () { + var _createFactories2 = createFactories(__webpack_require__(34)); + + var Rep = _createFactories2.Rep; + + + return span({}, Rep(Object.assign({}, this.props, { + mode: "tiny" + })), this.props.delim); + } + })); + + function supportsObject(grip, type) { + if (!isGrip(grip)) { + return false; + } + + return grip.preview && grip.preview.kind == "ArrayLike"; + } + + // Exports from this module + exports.GripArray = { + rep: GripArray, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 58 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + // Make this available to both AMD and CJS environments + + var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + // Dependencies + var React = __webpack_require__(2); + + var _require = __webpack_require__(35); + + var createFactories = _require.createFactories; + var isGrip = _require.isGrip; + + var _createFactories = createFactories(__webpack_require__(41)); + + var Caption = _createFactories.Caption; + + var _createFactories2 = createFactories(__webpack_require__(43)); + + var PropRep = _createFactories2.PropRep; + + // Shortcuts + + var span = React.DOM.span; + /** + * Renders an map. A map is represented by a list of its + * entries enclosed in curly brackets. + */ + + var GripMap = React.createClass({ + displayName: "GripMap", + + propTypes: { + object: React.PropTypes.object, + mode: React.PropTypes.string + }, + + getTitle: function (object) { + var title = object && object.class ? object.class : "Map"; + if (this.props.objectLink) { + return this.props.objectLink({ + object: object + }, title); + } + return title; + }, + + safeEntriesIterator: function (object, max) { + max = typeof max === "undefined" ? 3 : max; + try { + return this.entriesIterator(object, max); + } catch (err) { + console.error(err); + } + return []; + }, + + entriesIterator: function (object, max) { + // Entry filter. Show only interesting entries to the user. + var isInterestingEntry = this.props.isInterestingEntry || ((type, value) => { + return type == "boolean" || type == "number" || type == "string" && value.length != 0; + }); + + var mapEntries = object.preview && object.preview.entries ? object.preview.entries : []; + + var indexes = this.getEntriesIndexes(mapEntries, max, isInterestingEntry); + if (indexes.length < max && indexes.length < mapEntries.length) { + // There are not enough entries yet, so we add uninteresting entries. + indexes = indexes.concat(this.getEntriesIndexes(mapEntries, max - indexes.length, (t, value, name) => { + return !isInterestingEntry(t, value, name); + })); + } + + var entries = this.getEntries(mapEntries, indexes); + if (entries.length < mapEntries.length) { + // There are some undisplayed entries. Then display "more…". + var objectLink = this.props.objectLink || span; + + entries.push(Caption({ + key: "more", + object: objectLink({ + object: object + }, `${ mapEntries.length - max } more…`) + })); + } + + return entries; + }, + + /** + * Get entries ordered by index. + * + * @param {Array} entries Entries array. + * @param {Array} indexes Indexes of entries. + * @return {Array} Array of PropRep. + */ + getEntries: function (entries, indexes) { + // Make indexes ordered by ascending. + indexes.sort(function (a, b) { + return a - b; + }); + + return indexes.map((index, i) => { + var _entries$index = _slicedToArray(entries[index], 2); + + var key = _entries$index[0]; + var entryValue = _entries$index[1]; + + var value = entryValue.value !== undefined ? entryValue.value : entryValue; + + return PropRep({ + // key, + name: key, + equal: ": ", + object: value, + // Do not add a trailing comma on the last entry + // if there won't be a "more..." item. + delim: i < indexes.length - 1 || indexes.length < entries.length ? ", " : "", + mode: "tiny", + objectLink: this.props.objectLink + }); + }); + }, + + /** + * Get the indexes of entries in the map. + * + * @param {Array} entries Entries array. + * @param {Number} max The maximum length of indexes array. + * @param {Function} filter Filter the entry you want. + * @return {Array} Indexes of filtered entries in the map. + */ + getEntriesIndexes: function (entries, max, filter) { + return entries.reduce((indexes, _ref, i) => { + var _ref2 = _slicedToArray(_ref, 2); + + var key = _ref2[0]; + var entry = _ref2[1]; + + if (indexes.length < max) { + var value = entry && entry.value !== undefined ? entry.value : entry; + // Type is specified in grip's "class" field and for primitive + // values use typeof. + var type = (value && value.class ? value.class : typeof value).toLowerCase(); + + if (filter(type, value, key)) { + indexes.push(i); + } + } + + return indexes; + }, []); + }, + + render: function () { + var object = this.props.object; + var props = this.safeEntriesIterator(object, this.props.mode == "long" ? 100 : 3); + + var objectLink = this.props.objectLink || span; + if (this.props.mode == "tiny") { + return span({ className: "objectBox objectBox-object" }, this.getTitle(object), objectLink({ + className: "objectLeftBrace", + object: object + }, "")); + } + + return span({ className: "objectBox objectBox-object" }, this.getTitle(object), objectLink({ + className: "objectLeftBrace", + object: object + }, " { "), props, objectLink({ + className: "objectRightBrace", + object: object + }, " }")); + } + }); + + function supportsObject(grip, type) { + if (!isGrip(grip)) { + return false; + } + return grip.preview && grip.preview.kind == "MapLike"; + } + + // Exports from this module + exports.GripMap = { + rep: GripMap, + supportsObject: supportsObject + }; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + +/***/ }, +/* 59 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Copyright (c) 2007-2016, Alexandru Marasteanu <hello [at) alexei (dot] ro> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * 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 this software 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 AUTHORS OR COPYRIGHT HOLDERS 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. + * + */ + + /* globals window, exports, define */ + + (function (window) { + 'use strict'; + + var re = { + not_string: /[^s]/, + not_bool: /[^t]/, + not_type: /[^T]/, + not_primitive: /[^v]/, + number: /[diefg]/, + numeric_arg: /bcdiefguxX/, + json: /[j]/, + not_json: /[^j]/, + text: /^[^\x25]+/, + modulo: /^\x25{2}/, + placeholder: /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijosStTuvxX])/, + key: /^([a-z_][a-z_\d]*)/i, + key_access: /^\.([a-z_][a-z_\d]*)/i, + index_access: /^\[(\d+)\]/, + sign: /^[\+\-]/ + }; + + function sprintf() { + var key = arguments[0], + cache = sprintf.cache; + if (!(cache[key] && cache.hasOwnProperty(key))) { + cache[key] = sprintf.parse(key); + } + return sprintf.format.call(null, cache[key], arguments); + } + + sprintf.format = function (parse_tree, argv) { + var cursor = 1, + tree_length = parse_tree.length, + node_type = '', + arg, + output = [], + i, + k, + match, + pad, + pad_character, + pad_length, + is_positive = true, + sign = ''; + for (i = 0; i < tree_length; i++) { + node_type = get_type(parse_tree[i]); + if (node_type === 'string') { + output[output.length] = parse_tree[i]; + } else if (node_type === 'array') { + match = parse_tree[i]; // convenience purposes only + if (match[2]) { + // keyword argument + arg = argv[cursor]; + for (k = 0; k < match[2].length; k++) { + if (!arg.hasOwnProperty(match[2][k])) { + throw new Error(sprintf('[sprintf] property "%s" does not exist', match[2][k])); + } + arg = arg[match[2][k]]; + } + } else if (match[1]) { + // positional argument (explicit) + arg = argv[match[1]]; + } else { + // positional argument (implicit) + arg = argv[cursor++]; + } + + if (re.not_type.test(match[8]) && re.not_primitive.test(match[8]) && get_type(arg) == 'function') { + arg = arg(); + } + + if (re.numeric_arg.test(match[8]) && get_type(arg) != 'number' && isNaN(arg)) { + throw new TypeError(sprintf("[sprintf] expecting number but found %s", get_type(arg))); + } + + if (re.number.test(match[8])) { + is_positive = arg >= 0; + } + + switch (match[8]) { + case 'b': + arg = parseInt(arg, 10).toString(2); + break; + case 'c': + arg = String.fromCharCode(parseInt(arg, 10)); + break; + case 'd': + case 'i': + arg = parseInt(arg, 10); + break; + case 'j': + arg = JSON.stringify(arg, null, match[6] ? parseInt(match[6]) : 0); + break; + case 'e': + arg = match[7] ? parseFloat(arg).toExponential(match[7]) : parseFloat(arg).toExponential(); + break; + case 'f': + arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); + break; + case 'g': + arg = match[7] ? parseFloat(arg).toPrecision(match[7]) : parseFloat(arg); + break; + case 'o': + arg = arg.toString(8); + break; + case 's': + case 'S': + arg = String(arg); + arg = match[7] ? arg.substring(0, match[7]) : arg; + break; + case 't': + arg = String(!!arg); + arg = match[7] ? arg.substring(0, match[7]) : arg; + break; + case 'T': + arg = get_type(arg); + arg = match[7] ? arg.substring(0, match[7]) : arg; + break; + case 'u': + arg = parseInt(arg, 10) >>> 0; + break; + case 'v': + arg = arg.valueOf(); + arg = match[7] ? arg.substring(0, match[7]) : arg; + break; + case 'x': + arg = parseInt(arg, 10).toString(16); + break; + case 'X': + arg = parseInt(arg, 10).toString(16).toUpperCase(); + break; + } + if (re.json.test(match[8])) { + output[output.length] = arg; + } else { + if (re.number.test(match[8]) && (!is_positive || match[3])) { + sign = is_positive ? '+' : '-'; + arg = arg.toString().replace(re.sign, ''); + } else { + sign = ''; + } + pad_character = match[4] ? match[4] === '0' ? '0' : match[4].charAt(1) : ' '; + pad_length = match[6] - (sign + arg).length; + pad = match[6] ? pad_length > 0 ? str_repeat(pad_character, pad_length) : '' : ''; + output[output.length] = match[5] ? sign + arg + pad : pad_character === '0' ? sign + pad + arg : pad + sign + arg; + } + } + } + return output.join(''); + }; + + sprintf.cache = {}; + + sprintf.parse = function (fmt) { + var _fmt = fmt, + match = [], + parse_tree = [], + arg_names = 0; + while (_fmt) { + if ((match = re.text.exec(_fmt)) !== null) { + parse_tree[parse_tree.length] = match[0]; + } else if ((match = re.modulo.exec(_fmt)) !== null) { + parse_tree[parse_tree.length] = '%'; + } else if ((match = re.placeholder.exec(_fmt)) !== null) { + if (match[2]) { + arg_names |= 1; + var field_list = [], + replacement_field = match[2], + field_match = []; + if ((field_match = re.key.exec(replacement_field)) !== null) { + field_list[field_list.length] = field_match[1]; + while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { + if ((field_match = re.key_access.exec(replacement_field)) !== null) { + field_list[field_list.length] = field_match[1]; + } else if ((field_match = re.index_access.exec(replacement_field)) !== null) { + field_list[field_list.length] = field_match[1]; + } else { + throw new SyntaxError("[sprintf] failed to parse named argument key"); + } + } + } else { + throw new SyntaxError("[sprintf] failed to parse named argument key"); + } + match[2] = field_list; + } else { + arg_names |= 2; + } + if (arg_names === 3) { + throw new Error("[sprintf] mixing positional and named placeholders is not (yet) supported"); + } + parse_tree[parse_tree.length] = match; + } else { + throw new SyntaxError("[sprintf] unexpected placeholder"); + } + _fmt = _fmt.substring(match[0].length); + } + return parse_tree; + }; + + var vsprintf = function (fmt, argv, _argv) { + _argv = (argv || []).slice(0); + _argv.splice(0, 0, fmt); + return sprintf.apply(null, _argv); + }; + + /** + * helpers + */ + function get_type(variable) { + if (typeof variable === 'number') { + return 'number'; + } else if (typeof variable === 'string') { + return 'string'; + } else { + return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); + } + } + + var preformattedPadding = { + '0': ['', '0', '00', '000', '0000', '00000', '000000', '0000000'], + ' ': ['', ' ', ' ', ' ', ' ', ' ', ' ', ' '], + '_': ['', '_', '__', '___', '____', '_____', '______', '_______'] + }; + function str_repeat(input, multiplier) { + if (multiplier >= 0 && multiplier <= 7 && preformattedPadding[input]) { + return preformattedPadding[input][multiplier]; + } + return Array(multiplier + 1).join(input); + } + + /** + * export to either browser or node.js + */ + if (true) { + exports.sprintf = sprintf; + exports.vsprintf = vsprintf; + } else { + window.sprintf = sprintf; + window.vsprintf = vsprintf; + + if (typeof define === 'function' && define.amd) { + define(function () { + return { + sprintf: sprintf, + vsprintf: vsprintf + }; + }); + } + } + })(typeof window === 'undefined' ? this : window); + +/***/ }, +/* 60 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + /** + * EventEmitter. + */ + + var EventEmitter = function EventEmitter() {}; + module.exports = EventEmitter; + + var _require = __webpack_require__(61); + + var Cu = _require.Cu; + + var promise = __webpack_require__(66); + + /** + * Decorate an object with event emitter functionality. + * + * @param Object aObjectToDecorate + * Bind all public methods of EventEmitter to + * the aObjectToDecorate object. + */ + EventEmitter.decorate = function EventEmitter_decorate(aObjectToDecorate) { + var emitter = new EventEmitter(); + aObjectToDecorate.on = emitter.on.bind(emitter); + aObjectToDecorate.off = emitter.off.bind(emitter); + aObjectToDecorate.once = emitter.once.bind(emitter); + aObjectToDecorate.emit = emitter.emit.bind(emitter); + }; + + EventEmitter.prototype = { + /** + * Connect a listener. + * + * @param string aEvent + * The event name to which we're connecting. + * @param function aListener + * Called when the event is fired. + */ + on: function EventEmitter_on(aEvent, aListener) { + if (!this._eventEmitterListeners) this._eventEmitterListeners = new Map(); + if (!this._eventEmitterListeners.has(aEvent)) { + this._eventEmitterListeners.set(aEvent, []); + } + this._eventEmitterListeners.get(aEvent).push(aListener); + }, + + /** + * Listen for the next time an event is fired. + * + * @param string aEvent + * The event name to which we're connecting. + * @param function aListener + * (Optional) Called when the event is fired. Will be called at most + * one time. + * @return promise + * A promise which is resolved when the event next happens. The + * resolution value of the promise is the first event argument. If + * you need access to second or subsequent event arguments (it's rare + * that this is needed) then use aListener + */ + once: function EventEmitter_once(aEvent, aListener) { + var _this = this; + + var deferred = promise.defer(); + + var handler = function (aEvent, aFirstArg) { + for (var _len = arguments.length, aRest = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { + aRest[_key - 2] = arguments[_key]; + } + + _this.off(aEvent, handler); + if (aListener) { + aListener.apply(null, [aEvent, aFirstArg].concat(aRest)); + } + deferred.resolve(aFirstArg); + }; + + handler._originalListener = aListener; + this.on(aEvent, handler); + + return deferred.promise; + }, + + /** + * Remove a previously-registered event listener. Works for events + * registered with either on or once. + * + * @param string aEvent + * The event name whose listener we're disconnecting. + * @param function aListener + * The listener to remove. + */ + off: function EventEmitter_off(aEvent, aListener) { + if (!this._eventEmitterListeners) return; + var listeners = this._eventEmitterListeners.get(aEvent); + if (listeners) { + this._eventEmitterListeners.set(aEvent, listeners.filter(l => { + return l !== aListener && l._originalListener !== aListener; + })); + } + }, + + /** + * Emit an event. All arguments to this method will + * be sent to listener functions. + */ + emit: function EventEmitter_emit(aEvent) { + var _this2 = this, + _arguments = arguments; + + if (!this._eventEmitterListeners || !this._eventEmitterListeners.has(aEvent)) { + return; + } + + var originalListeners = this._eventEmitterListeners.get(aEvent); + + var _loop = function (listener) { + // If the object was destroyed during event emission, stop + // emitting. + if (!_this2._eventEmitterListeners) { + return "break"; + } + + // If listeners were removed during emission, make sure the + // event handler we're going to fire wasn't removed. + if (originalListeners === _this2._eventEmitterListeners.get(aEvent) || _this2._eventEmitterListeners.get(aEvent).some(l => l === listener)) { + try { + listener.apply(null, _arguments); + } catch (ex) { + // Prevent a bad listener from interfering with the others. + var msg = ex + ": " + ex.stack; + //console.error(msg); + console.log(msg); + } + } + }; + + for (var listener of this._eventEmitterListeners.get(aEvent)) { + var _ret = _loop(listener); + + if (_ret === "break") break; + } + } + }; + +/***/ }, +/* 61 */ +/***/ function(module, exports, __webpack_require__) { + + /* + * A sham for https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/chrome + */ + + var _require = __webpack_require__(62); + + var inDOMUtils = _require.inDOMUtils; + + + var ourServices = { + inIDOMUtils: inDOMUtils, + nsIClipboardHelper: { + copyString: () => {} + }, + nsIXULChromeRegistry: { + isLocaleRTL: () => { + return false; + } + }, + nsIDOMParser: {} + }; + + module.exports = { + Cc: name => { + if (typeof console !== "undefined") { + console.log('Cc sham for', name); + } + return { + getService: name => ourServices[name], + createInstance: iface => ourServices[iface] + }; + }, + CC: (name, iface, method) => { + if (typeof console !== "undefined") { + console.log('CC sham for', name, iface, method); + } + return {}; + }, + Ci: { + nsIThread: { + "DISPATCH_NORMAL": 0, + "DISPATCH_SYNC": 1 + }, + nsIDOMNode: typeof HTMLElement !== "undefined" ? HTMLElement : null, + nsIFocusManager: { + MOVEFOCUS_BACKWARD: 2, + MOVEFOCUS_FORWARD: 1 + }, + nsIDOMKeyEvent: {}, + nsIDOMCSSRule: { "UNKNOWN_RULE": 0, "STYLE_RULE": 1, "CHARSET_RULE": 2, "IMPORT_RULE": 3, "MEDIA_RULE": 4, "FONT_FACE_RULE": 5, "PAGE_RULE": 6, "KEYFRAMES_RULE": 7, "KEYFRAME_RULE": 8, "MOZ_KEYFRAMES_RULE": 7, "MOZ_KEYFRAME_RULE": 8, "NAMESPACE_RULE": 10, "COUNTER_STYLE_RULE": 11, "SUPPORTS_RULE": 12, "FONT_FEATURE_VALUES_RULE": 14 }, + inIDOMUtils: "inIDOMUtils", + nsIClipboardHelper: "nsIClipboardHelper", + nsIXULChromeRegistry: "nsIXULChromeRegistry" + }, + Cu: { + reportError: msg => { + typeof console !== "undefined" ? console.error(msg) : dump(msg); + }, + callFunctionWithAsyncStack: fn => fn() + }, + Cr: {}, + components: { + isSuccessCode: () => (returnCode & 0x80000000) === 0 + } + }; + +/***/ }, +/* 62 */ +/***/ function(module, exports, __webpack_require__) { + + // A sham for inDOMUtils. + + "use strict"; + + var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + + var _require = __webpack_require__(63); + + var CSSLexer = _require.CSSLexer; + + var _require2 = __webpack_require__(64); + + var cssColors = _require2.cssColors; + + var _require3 = __webpack_require__(65); + + var cssProperties = _require3.cssProperties; + + + var cssRGBMap; + + // From inIDOMUtils.idl. + var EXCLUDE_SHORTHANDS = 1 << 0; + var INCLUDE_ALIASES = 1 << 1; + var TYPE_LENGTH = 0; + var TYPE_PERCENTAGE = 1; + var TYPE_COLOR = 2; + var TYPE_URL = 3; + var TYPE_ANGLE = 4; + var TYPE_FREQUENCY = 5; + var TYPE_TIME = 6; + var TYPE_GRADIENT = 7; + var TYPE_TIMING_FUNCTION = 8; + var TYPE_IMAGE_RECT = 9; + var TYPE_NUMBER = 10; + + function getCSSLexer(text) { + return new CSSLexer(text); + } + + function rgbToColorName(r, g, b) { + if (!cssRGBMap) { + cssRGBMap = new Map(); + for (var name in cssColors) { + cssRGBMap.set(JSON.stringify(cssColors[name]), name); + } + } + var value = cssRGBMap.get(JSON.stringify([r, g, b])); + if (!value) { + throw new Error("no such color"); + } + return value; + } + + // Taken from dom/tests/mochitest/ajax/mochikit/MochiKit/Color.js + function _hslValue(n1, n2, hue) { + if (hue > 6.0) { + hue -= 6.0; + } else if (hue < 0.0) { + hue += 6.0; + } + var val; + if (hue < 1.0) { + val = n1 + (n2 - n1) * hue; + } else if (hue < 3.0) { + val = n2; + } else if (hue < 4.0) { + val = n1 + (n2 - n1) * (4.0 - hue); + } else { + val = n1; + } + return val; + } + + // Taken from dom/tests/mochitest/ajax/mochikit/MochiKit/Color.js + // and then modified. + function hslToRGB(_ref) { + var _ref2 = _slicedToArray(_ref, 3); + + var hue = _ref2[0]; + var saturation = _ref2[1]; + var lightness = _ref2[2]; + + var red; + var green; + var blue; + if (saturation === 0) { + red = lightness; + green = lightness; + blue = lightness; + } else { + var m2; + if (lightness <= 0.5) { + m2 = lightness * (1.0 + saturation); + } else { + m2 = lightness + saturation - lightness * saturation; + } + var m1 = 2.0 * lightness - m2; + var f = _hslValue; + var h6 = hue * 6.0; + red = f(m1, m2, h6 + 2); + green = f(m1, m2, h6); + blue = f(m1, m2, h6 - 2); + } + return [red, green, blue]; + } + + function colorToRGBA(name) { + name = name.trim().toLowerCase(); + if (name in cssColors) { + return cssColors[name]; + } + + if (name === "transparent") { + return [0, 0, 0, 0]; + } + + var lexer = getCSSLexer(name); + + var getToken = function () { + while (true) { + var token = lexer.nextToken(); + if (!token || token.tokenType !== "comment" || token.tokenType !== "whitespace") { + return token; + } + } + }; + + var requireComma = function (token) { + if (token.tokenType !== "symbol" || token.text !== ",") { + return null; + } + return getToken(); + }; + + var func = getToken(); + if (!func || func.tokenType !== "function") { + return null; + } + var alpha = false; + if (func.text === "rgb" || func.text === "hsl") { + // Nothing. + } else if (func.text === "rgba" || func.text === "hsla") { + alpha = true; + } else { + return null; + } + + var vals = []; + for (var i = 0; i < 3; ++i) { + var token = getToken(); + if (i > 0) { + token = requireComma(token); + } + if (token.tokenType !== "number" || !token.isInteger) { + return null; + } + var num = token.number; + if (num < 0) { + num = 0; + } else if (num > 255) { + num = 255; + } + vals.push(num); + } + + if (func.text === "hsl" || func.text === "hsla") { + vals = hslToRGB(vals); + } + + if (alpha) { + var _token = requireComma(getToken()); + if (_token.tokenType !== "number") { + return null; + } + var _num = _token.number; + if (_num < 0) { + _num = 0; + } else if (_num > 1) { + _num = 1; + } + vals.push(_num); + } else { + vals.push(1); + } + + var parenToken = getToken(); + if (!parenToken || parenToken.tokenType !== "symbol" || parenToken.text !== ")") { + return null; + } + if (getToken() !== null) { + return null; + } + + return vals; + } + + function isValidCSSColor(name) { + return colorToRGBA(name) !== null; + } + + function isVariable(name) { + return name.startsWith("--"); + } + + function cssPropertyIsShorthand(name) { + if (isVariable(name)) { + return false; + } + if (!(name in cssProperties)) { + throw Error("unknown property " + name); + } + return !!cssProperties[name].subproperties; + } + + function getSubpropertiesForCSSProperty(name) { + if (isVariable(name)) { + return [name]; + } + if (!(name in cssProperties)) { + throw Error("unknown property " + name); + } + if ("subproperties" in cssProperties[name]) { + return cssProperties[name].subproperties.slice(); + } + return [name]; + } + + function getCSSValuesForProperty(name) { + if (isVariable(name)) { + return ["initial", "inherit", "unset"]; + } + if (!(name in cssProperties)) { + throw Error("unknown property " + name); + } + return cssProperties[name].values.slice(); + } + + function getCSSPropertyNames(flags) { + var names = Object.keys(cssProperties); + if ((flags & EXCLUDE_SHORTHANDS) !== 0) { + names = names.filter(name => cssProperties[name].subproperties); + } + if ((flags & INCLUDE_ALIASES) === 0) { + names = names.filter(name => !cssProperties[name].alias); + } + return names; + } + + function cssPropertySupportsType(name, type) { + if (isVariable(name)) { + return false; + } + if (!(name in cssProperties)) { + throw Error("unknown property " + name); + } + return (cssProperties[name].supports & 1 << type) !== 0; + } + + function isInheritedProperty(name) { + if (isVariable(name)) { + return true; + } + if (!(name in cssProperties)) { + return false; + } + return cssProperties[name].inherited; + } + + function cssPropertyIsValid(name, value) { + if (isVariable(name)) { + return true; + } + if (!(name in cssProperties)) { + return false; + } + var elt = document.createElement("div"); + elt.style = name + ":" + value; + return elt.style.length > 0; + } + + exports.inDOMUtils = { + getCSSLexer, + rgbToColorName, + colorToRGBA, + isValidCSSColor, + cssPropertyIsShorthand, + getSubpropertiesForCSSProperty, + getCSSValuesForProperty, + getCSSPropertyNames, + cssPropertySupportsType, + isInheritedProperty, + cssPropertyIsValid, + + // Constants. + EXCLUDE_SHORTHANDS, + INCLUDE_ALIASES, + TYPE_LENGTH, + TYPE_PERCENTAGE, + TYPE_COLOR, + TYPE_URL, + TYPE_ANGLE, + TYPE_FREQUENCY, + TYPE_TIME, + TYPE_GRADIENT, + TYPE_TIMING_FUNCTION, + TYPE_IMAGE_RECT, + TYPE_NUMBER + }; + +/***/ }, +/* 63 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;"use strict"; + + (function (root, factory) { + // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, + // Rhino, and plain browser loading. + if (true) { + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [exports], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (typeof exports !== 'undefined') { + factory(exports); + } else { + factory(root); + } + })(this, function (exports) { + + function between(num, first, last) { + return num >= first && num <= last; + } + function digit(code) { + return between(code, 0x30, 0x39); + } + function hexdigit(code) { + return digit(code) || between(code, 0x41, 0x46) || between(code, 0x61, 0x66); + } + function uppercaseletter(code) { + return between(code, 0x41, 0x5a); + } + function lowercaseletter(code) { + return between(code, 0x61, 0x7a); + } + function letter(code) { + return uppercaseletter(code) || lowercaseletter(code); + } + function nonascii(code) { + return code >= 0x80; + } + function namestartchar(code) { + return letter(code) || nonascii(code) || code == 0x5f; + } + function namechar(code) { + return namestartchar(code) || digit(code) || code == 0x2d; + } + function nonprintable(code) { + return between(code, 0, 8) || code == 0xb || between(code, 0xe, 0x1f) || code == 0x7f; + } + function newline(code) { + return code == 0xa; + } + function whitespace(code) { + return newline(code) || code == 9 || code == 0x20; + } + + var maximumallowedcodepoint = 0x10ffff; + + var InvalidCharacterError = function (message) { + this.message = message; + }; + InvalidCharacterError.prototype = new Error(); + InvalidCharacterError.prototype.name = 'InvalidCharacterError'; + + function stringFromCode(code) { + if (code <= 0xffff) return String.fromCharCode(code); + // Otherwise, encode astral char as surrogate pair. + code -= Math.pow(2, 20); + var lead = Math.floor(code / Math.pow(2, 10)) + 0xd800; + var trail = code % Math.pow(2, 10) + 0xdc00; + return String.fromCharCode(lead) + String.fromCharCode(trail); + } + + function* tokenize(str, options) { + if (options === undefined) { + options = {}; + } + if (options.loc === undefined) { + options.loc = false; + } + if (options.offsets === undefined) { + options.offsets = false; + } + if (options.keepComments === undefined) { + options.keepComments = false; + } + if (options.startOffset === undefined) { + options.startOffset = 0; + } + + var i = options.startOffset - 1; + var code; + + // Line number information. + var line = 0; + var column = 0; + // The only use of lastLineLength is in reconsume(). + var lastLineLength = 0; + var incrLineno = function () { + line += 1; + lastLineLength = column; + column = 0; + }; + var locStart = { line: line, column: column }; + var offsetStart = i; + + var codepoint = function (i) { + if (i >= str.length) { + return -1; + } + return str.charCodeAt(i); + }; + var next = function (num) { + if (num === undefined) num = 1; + if (num > 3) throw "Spec Error: no more than three codepoints of lookahead."; + + var rcode; + for (var offset = i + 1; num-- > 0; ++offset) { + rcode = codepoint(offset); + if (rcode === 0xd && codepoint(offset + 1) === 0xa) { + ++offset; + rcode = 0xa; + } else if (rcode === 0xd || rcode === 0xc) { + rcode = 0xa; + } else if (rcode === 0x0) { + rcode = 0xfffd; + } + } + + return rcode; + }; + var consume = function (num) { + if (num === undefined) num = 1; + while (num-- > 0) { + ++i; + code = codepoint(i); + if (code === 0xd && codepoint(i + 1) === 0xa) { + ++i; + code = 0xa; + } else if (code === 0xd || code === 0xc) { + code = 0xa; + } else if (code === 0x0) { + code = 0xfffd; + } + if (newline(code)) incrLineno();else column++; + } + return true; + }; + var reconsume = function () { + i -= 1; // This is ok even in the \r\n case. + if (newline(code)) { + line -= 1; + column = lastLineLength; + } else { + column -= 1; + } + return true; + }; + var eof = function (codepoint) { + if (codepoint === undefined) codepoint = code; + return codepoint == -1; + }; + var donothing = function () {}; + var parseerror = function () { + console.log("Parse error at index " + i + ", processing codepoint 0x" + code.toString(16) + ".");return true; + }; + + var consumeAToken = function () { + consume(); + if (!options.keepComments) { + while (code == 0x2f && next() == 0x2a) { + consumeAComment(); + consume(); + } + } + locStart.line = line; + locStart.column = column; + offsetStart = i; + if (whitespace(code)) { + while (whitespace(next())) { + consume(); + }return new WhitespaceToken(); + } else if (code == 0x2f && next() == 0x2a) return consumeAComment();else if (code == 0x22) return consumeAStringToken();else if (code == 0x23) { + if (namechar(next()) || areAValidEscape(next(1), next(2))) { + var token = new HashToken(); + if (wouldStartAnIdentifier(next(1), next(2), next(3))) { + token.type = "id"; + token.tokenType = "id"; + } + token.value = consumeAName(); + token.text = token.value; + return token; + } else { + return new DelimToken(code); + } + } else if (code == 0x24) { + if (next() == 0x3d) { + consume(); + return new SuffixMatchToken(); + } else { + return new DelimToken(code); + } + } else if (code == 0x27) return consumeAStringToken();else if (code == 0x28) return new OpenParenToken();else if (code == 0x29) return new CloseParenToken();else if (code == 0x2a) { + if (next() == 0x3d) { + consume(); + return new SubstringMatchToken(); + } else { + return new DelimToken(code); + } + } else if (code == 0x2b) { + if (startsWithANumber()) { + reconsume(); + return consumeANumericToken(); + } else { + return new DelimToken(code); + } + } else if (code == 0x2c) return new CommaToken();else if (code == 0x2d) { + if (startsWithANumber()) { + reconsume(); + return consumeANumericToken(); + } else if (next(1) == 0x2d && next(2) == 0x3e) { + consume(2); + return new CDCToken(); + } else if (startsWithAnIdentifier()) { + reconsume(); + return consumeAnIdentlikeToken(); + } else { + return new DelimToken(code); + } + } else if (code == 0x2e) { + if (startsWithANumber()) { + reconsume(); + return consumeANumericToken(); + } else { + return new DelimToken(code); + } + } else if (code == 0x3a) return new ColonToken();else if (code == 0x3b) return new SemicolonToken();else if (code == 0x3c) { + if (next(1) == 0x21 && next(2) == 0x2d && next(3) == 0x2d) { + consume(3); + return new CDOToken(); + } else { + return new DelimToken(code); + } + } else if (code == 0x40) { + if (wouldStartAnIdentifier(next(1), next(2), next(3))) { + return new AtKeywordToken(consumeAName()); + } else { + return new DelimToken(code); + } + } else if (code == 0x5b) return new OpenSquareToken();else if (code == 0x5c) { + if (startsWithAValidEscape()) { + reconsume(); + return consumeAnIdentlikeToken(); + } else { + parseerror(); + return new DelimToken(code); + } + } else if (code == 0x5d) return new CloseSquareToken();else if (code == 0x5e) { + if (next() == 0x3d) { + consume(); + return new PrefixMatchToken(); + } else { + return new DelimToken(code); + } + } else if (code == 0x7b) return new OpenCurlyToken();else if (code == 0x7c) { + if (next() == 0x3d) { + consume(); + return new DashMatchToken(); + // } else if(next() == 0x7c) { + // consume(); + // return new ColumnToken(); + } else { + return new DelimToken(code); + } + } else if (code == 0x7d) return new CloseCurlyToken();else if (code == 0x7e) { + if (next() == 0x3d) { + consume(); + return new IncludeMatchToken(); + } else { + return new DelimToken(code); + } + } else if (digit(code)) { + reconsume(); + return consumeANumericToken(); + } else if (namestartchar(code)) { + reconsume(); + return consumeAnIdentlikeToken(); + } else if (eof()) return new EOFToken();else return new DelimToken(code); + }; + + var consumeAComment = function () { + consume(); + var comment = ""; + while (true) { + consume(); + if (code == 0x2a && next() == 0x2f) { + consume(); + break; + } else if (eof()) { + break; + } + comment += stringFromCode(code); + } + return new CommentToken(comment); + }; + + var consumeANumericToken = function () { + var num = consumeANumber(); + var token; + if (wouldStartAnIdentifier(next(1), next(2), next(3))) { + token = new DimensionToken(); + token.value = num.value; + token.repr = num.repr; + token.type = num.type; + token.unit = consumeAName(); + token.text = token.unit; + } else if (next() == 0x25) { + consume(); + token = new PercentageToken(); + token.value = num.value; + token.repr = num.repr; + } else { + var token = new NumberToken(); + token.value = num.value; + token.repr = num.repr; + token.type = num.type; + } + token.number = token.value; + token.isInteger = token.type === "integer"; + // FIXME hasSign + return token; + }; + + var consumeAnIdentlikeToken = function () { + var str = consumeAName(); + if (str.toLowerCase() == "url" && next() == 0x28) { + consume(); + while (whitespace(next(1)) && whitespace(next(2))) { + consume(); + }if (next() == 0x22 || next() == 0x27 || whitespace(next()) && (next(2) == 0x22 || next(2) == 0x27)) { + while (whitespace(next())) { + consume(); + }consume(); + var _str = consumeAStringToken(); + while (whitespace(next())) { + consume(); + } // The closing paren. + consume(); + return new URLToken(_str.text); + } else { + return consumeAURLToken(); + } + } else if (next() == 0x28) { + consume(); + return new FunctionToken(str); + } else { + return new IdentToken(str); + } + }; + + var consumeAStringToken = function (endingCodePoint) { + if (endingCodePoint === undefined) endingCodePoint = code; + var string = ""; + while (consume()) { + if (code == endingCodePoint || eof()) { + return new StringToken(string); + } else if (newline(code)) { + reconsume(); + return new BadStringToken(string); + } else if (code == 0x5c) { + if (eof(next())) { + donothing(); + } else if (newline(next())) { + consume(); + } else { + string += stringFromCode(consumeEscape()); + } + } else { + string += stringFromCode(code); + } + } + }; + + var consumeAURLToken = function () { + var token = new URLToken(""); + while (whitespace(next())) { + consume(); + }if (eof(next())) return token; + while (consume()) { + if (code == 0x29 || eof()) { + break; + } else if (whitespace(code)) { + while (whitespace(next())) { + consume(); + }if (next() == 0x29 || eof(next())) { + consume(); + break; + } else { + consumeTheRemnantsOfABadURL(); + return new BadURLToken(); + } + } else if (code == 0x22 || code == 0x27 || code == 0x28 || nonprintable(code)) { + parseerror(); + consumeTheRemnantsOfABadURL(); + return new BadURLToken(); + } else if (code == 0x5c) { + if (startsWithAValidEscape()) { + token.value += stringFromCode(consumeEscape()); + } else { + parseerror(); + consumeTheRemnantsOfABadURL(); + return new BadURLToken(); + } + } else { + token.value += stringFromCode(code); + } + } + token.text = token.value; + return token; + }; + + var consumeEscape = function () { + // Assume the the current character is the \ + // and the next code point is not a newline. + consume(); + if (hexdigit(code)) { + // Consume 1-6 hex digits + var digits = [code]; + for (var total = 0; total < 5; total++) { + if (hexdigit(next())) { + consume(); + digits.push(code); + } else { + break; + } + } + if (whitespace(next())) consume(); + var value = parseInt(digits.map(function (x) { + return String.fromCharCode(x); + }).join(''), 16); + if (value > maximumallowedcodepoint) value = 0xfffd; + return value; + } else if (eof()) { + return 0xfffd; + } else { + return code; + } + }; + + var areAValidEscape = function (c1, c2) { + if (c1 != 0x5c) return false; + if (newline(c2)) return false; + return true; + }; + var startsWithAValidEscape = function () { + return areAValidEscape(code, next()); + }; + + var wouldStartAnIdentifier = function (c1, c2, c3) { + if (c1 == 0x2d) { + return namestartchar(c2) || c2 == 0x2d || areAValidEscape(c2, c3); + } else if (namestartchar(c1)) { + return true; + } else if (c1 == 0x5c) { + return areAValidEscape(c1, c2); + } else { + return false; + } + }; + var startsWithAnIdentifier = function () { + return wouldStartAnIdentifier(code, next(1), next(2)); + }; + + var wouldStartANumber = function (c1, c2, c3) { + if (c1 == 0x2b || c1 == 0x2d) { + if (digit(c2)) return true; + if (c2 == 0x2e && digit(c3)) return true; + return false; + } else if (c1 == 0x2e) { + if (digit(c2)) return true; + return false; + } else if (digit(c1)) { + return true; + } else { + return false; + } + }; + var startsWithANumber = function () { + return wouldStartANumber(code, next(1), next(2)); + }; + + var consumeAName = function () { + var result = ""; + while (consume()) { + if (namechar(code)) { + result += stringFromCode(code); + } else if (startsWithAValidEscape()) { + result += stringFromCode(consumeEscape()); + } else { + reconsume(); + return result; + } + } + }; + + var consumeANumber = function () { + var repr = []; + var type = "integer"; + if (next() == 0x2b || next() == 0x2d) { + consume(); + repr += stringFromCode(code); + } + while (digit(next())) { + consume(); + repr += stringFromCode(code); + } + if (next(1) == 0x2e && digit(next(2))) { + consume(); + repr += stringFromCode(code); + consume(); + repr += stringFromCode(code); + type = "number"; + while (digit(next())) { + consume(); + repr += stringFromCode(code); + } + } + var c1 = next(1), + c2 = next(2), + c3 = next(3); + if ((c1 == 0x45 || c1 == 0x65) && digit(c2)) { + consume(); + repr += stringFromCode(code); + consume(); + repr += stringFromCode(code); + type = "number"; + while (digit(next())) { + consume(); + repr += stringFromCode(code); + } + } else if ((c1 == 0x45 || c1 == 0x65) && (c2 == 0x2b || c2 == 0x2d) && digit(c3)) { + consume(); + repr += stringFromCode(code); + consume(); + repr += stringFromCode(code); + consume(); + repr += stringFromCode(code); + type = "number"; + while (digit(next())) { + consume(); + repr += stringFromCode(code); + } + } + var value = convertAStringToANumber(repr); + return { type: type, value: value, repr: repr }; + }; + + var convertAStringToANumber = function (string) { + // CSS's number rules are identical to JS, afaik. + return +string; + }; + + var consumeTheRemnantsOfABadURL = function () { + while (consume()) { + if (code == 0x2d || eof()) { + return; + } else if (startsWithAValidEscape()) { + consumeEscape(); + donothing(); + } else { + donothing(); + } + } + }; + + var iterationCount = 0; + while (!eof(next())) { + var token = consumeAToken(); + if (options.loc) { + token.loc = {}; + token.loc.start = { line: locStart.line, column: locStart.column }; + token.loc.end = { line: line, column: column }; + } + if (options.offsets) { + token.startOffset = offsetStart; + token.endOffset = i + 1; + } + yield token; + iterationCount++; + if (iterationCount > str.length * 2) return "I'm infinite-looping!"; + } + } + + function CSSParserToken() { + throw "Abstract Base Class"; + } + CSSParserToken.prototype.toJSON = function () { + return { token: this.tokenType }; + }; + CSSParserToken.prototype.toString = function () { + return this.tokenType; + }; + CSSParserToken.prototype.toSource = function () { + return '' + this; + }; + + function BadStringToken(text) { + this.text = text; + return this; + } + BadStringToken.prototype = Object.create(CSSParserToken.prototype); + BadStringToken.prototype.tokenType = "bad_string"; + + function BadURLToken() { + return this; + } + BadURLToken.prototype = Object.create(CSSParserToken.prototype); + BadURLToken.prototype.tokenType = "bad_url"; + + function WhitespaceToken() { + return this; + } + WhitespaceToken.prototype = Object.create(CSSParserToken.prototype); + WhitespaceToken.prototype.tokenType = "whitespace"; + WhitespaceToken.prototype.toString = function () { + return "WS"; + }; + WhitespaceToken.prototype.toSource = function () { + return " "; + }; + + function CDOToken() { + return this; + } + CDOToken.prototype = Object.create(CSSParserToken.prototype); + CDOToken.prototype.tokenType = "htmlcomment"; + CDOToken.prototype.toSource = function () { + return "<!--"; + }; + + function CDCToken() { + return this; + } + CDCToken.prototype = Object.create(CSSParserToken.prototype); + CDCToken.prototype.tokenType = "htmlcomment"; + CDCToken.prototype.toSource = function () { + return "-->"; + }; + + function ColonToken() { + return this; + } + ColonToken.prototype = Object.create(CSSParserToken.prototype); + ColonToken.prototype.tokenType = "symbol"; + ColonToken.prototype.text = ":"; + + function SemicolonToken() { + return this; + } + SemicolonToken.prototype = Object.create(CSSParserToken.prototype); + SemicolonToken.prototype.tokenType = "symbol"; + SemicolonToken.prototype.text = ";"; + + function CommaToken() { + return this; + } + CommaToken.prototype = Object.create(CSSParserToken.prototype); + CommaToken.prototype.tokenType = "symbol"; + CommaToken.prototype.text = ","; + + function GroupingToken() { + throw "Abstract Base Class"; + } + GroupingToken.prototype = Object.create(CSSParserToken.prototype); + + function OpenCurlyToken() { + this.value = "{";this.mirror = "}";return this; + } + OpenCurlyToken.prototype = Object.create(GroupingToken.prototype); + OpenCurlyToken.prototype.tokenType = "symbol"; + OpenCurlyToken.prototype.text = "{"; + + function CloseCurlyToken() { + this.value = "}";this.mirror = "{";return this; + } + CloseCurlyToken.prototype = Object.create(GroupingToken.prototype); + CloseCurlyToken.prototype.tokenType = "symbol"; + CloseCurlyToken.prototype.text = "}"; + + function OpenSquareToken() { + this.value = "[";this.mirror = "]";return this; + } + OpenSquareToken.prototype = Object.create(GroupingToken.prototype); + OpenSquareToken.prototype.tokenType = "symbol"; + OpenSquareToken.prototype.text = "["; + + function CloseSquareToken() { + this.value = "]";this.mirror = "[";return this; + } + CloseSquareToken.prototype = Object.create(GroupingToken.prototype); + CloseSquareToken.prototype.tokenType = "symbol"; + CloseSquareToken.prototype.text = "]"; + + function OpenParenToken() { + this.value = "(";this.mirror = ")";return this; + } + OpenParenToken.prototype = Object.create(GroupingToken.prototype); + OpenParenToken.prototype.tokenType = "symbol"; + OpenParenToken.prototype.text = "("; + + function CloseParenToken() { + this.value = ")";this.mirror = "(";return this; + } + CloseParenToken.prototype = Object.create(GroupingToken.prototype); + CloseParenToken.prototype.tokenType = "symbol"; + CloseParenToken.prototype.text = ")"; + + function IncludeMatchToken() { + return this; + } + IncludeMatchToken.prototype = Object.create(CSSParserToken.prototype); + IncludeMatchToken.prototype.tokenType = "includes"; + + function DashMatchToken() { + return this; + } + DashMatchToken.prototype = Object.create(CSSParserToken.prototype); + DashMatchToken.prototype.tokenType = "dashmatch"; + + function PrefixMatchToken() { + return this; + } + PrefixMatchToken.prototype = Object.create(CSSParserToken.prototype); + PrefixMatchToken.prototype.tokenType = "beginsmatch"; + + function SuffixMatchToken() { + return this; + } + SuffixMatchToken.prototype = Object.create(CSSParserToken.prototype); + SuffixMatchToken.prototype.tokenType = "endsmatch"; + + function SubstringMatchToken() { + return this; + } + SubstringMatchToken.prototype = Object.create(CSSParserToken.prototype); + SubstringMatchToken.prototype.tokenType = "containsmatch"; + + function ColumnToken() { + return this; + } + ColumnToken.prototype = Object.create(CSSParserToken.prototype); + ColumnToken.prototype.tokenType = "||"; + + function EOFToken() { + return this; + } + EOFToken.prototype = Object.create(CSSParserToken.prototype); + EOFToken.prototype.tokenType = "EOF"; + EOFToken.prototype.toSource = function () { + return ""; + }; + + function DelimToken(code) { + this.value = stringFromCode(code); + this.text = this.value; + return this; + } + DelimToken.prototype = Object.create(CSSParserToken.prototype); + DelimToken.prototype.tokenType = "symbol"; + DelimToken.prototype.toString = function () { + return "DELIM(" + this.value + ")"; + }; + DelimToken.prototype.toJSON = function () { + var json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.value = this.value; + return json; + }; + DelimToken.prototype.toSource = function () { + if (this.value == "\\") return "\\\n";else return this.value; + }; + + function StringValuedToken() { + throw "Abstract Base Class"; + } + StringValuedToken.prototype = Object.create(CSSParserToken.prototype); + StringValuedToken.prototype.ASCIIMatch = function (str) { + return this.value.toLowerCase() == str.toLowerCase(); + }; + StringValuedToken.prototype.toJSON = function () { + var json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.value = this.value; + return json; + }; + + function IdentToken(val) { + this.value = val; + this.text = val; + } + IdentToken.prototype = Object.create(StringValuedToken.prototype); + IdentToken.prototype.tokenType = "ident"; + IdentToken.prototype.toString = function () { + return "IDENT(" + this.value + ")"; + }; + IdentToken.prototype.toSource = function () { + return escapeIdent(this.value); + }; + + function FunctionToken(val) { + this.value = val; + this.text = val; + this.mirror = ")"; + } + FunctionToken.prototype = Object.create(StringValuedToken.prototype); + FunctionToken.prototype.tokenType = "function"; + FunctionToken.prototype.toString = function () { + return "FUNCTION(" + this.value + ")"; + }; + FunctionToken.prototype.toSource = function () { + return escapeIdent(this.value) + "("; + }; + + function AtKeywordToken(val) { + this.value = val; + this.text = val; + } + AtKeywordToken.prototype = Object.create(StringValuedToken.prototype); + AtKeywordToken.prototype.tokenType = "at"; + AtKeywordToken.prototype.toString = function () { + return "AT(" + this.value + ")"; + }; + AtKeywordToken.prototype.toSource = function () { + return "@" + escapeIdent(this.value); + }; + + function HashToken(val) { + this.value = val; + this.text = val; + this.type = "unrestricted"; + } + HashToken.prototype = Object.create(StringValuedToken.prototype); + HashToken.prototype.tokenType = "hash"; + HashToken.prototype.toString = function () { + return "HASH(" + this.value + ")"; + }; + HashToken.prototype.toJSON = function () { + var json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.value = this.value; + json.type = this.type; + return json; + }; + HashToken.prototype.toSource = function () { + if (this.type == "id") { + return "#" + escapeIdent(this.value); + } else { + return "#" + escapeHash(this.value); + } + }; + + function StringToken(val) { + this.value = val; + this.text = val; + } + StringToken.prototype = Object.create(StringValuedToken.prototype); + StringToken.prototype.tokenType = "string"; + StringToken.prototype.toString = function () { + return '"' + escapeString(this.value) + '"'; + }; + + function CommentToken(val) { + this.value = val; + } + CommentToken.prototype = Object.create(StringValuedToken.prototype); + CommentToken.prototype.tokenType = "comment"; + CommentToken.prototype.toString = function () { + return '/*' + this.value + '*/'; + }; + CommentToken.prototype.toSource = CommentToken.prototype.toString; + + function URLToken(val) { + this.value = val; + this.text = val; + } + URLToken.prototype = Object.create(StringValuedToken.prototype); + URLToken.prototype.tokenType = "url"; + URLToken.prototype.toString = function () { + return "URL(" + this.value + ")"; + }; + URLToken.prototype.toSource = function () { + return 'url("' + escapeString(this.value) + '")'; + }; + + function NumberToken() { + this.value = null; + this.type = "integer"; + this.repr = ""; + } + NumberToken.prototype = Object.create(CSSParserToken.prototype); + NumberToken.prototype.tokenType = "number"; + NumberToken.prototype.toString = function () { + if (this.type == "integer") return "INT(" + this.value + ")"; + return "NUMBER(" + this.value + ")"; + }; + NumberToken.prototype.toJSON = function () { + var json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.value = this.value; + json.type = this.type; + json.repr = this.repr; + return json; + }; + NumberToken.prototype.toSource = function () { + return this.repr; + }; + + function PercentageToken() { + this.value = null; + this.repr = ""; + } + PercentageToken.prototype = Object.create(CSSParserToken.prototype); + PercentageToken.prototype.tokenType = "percentage"; + PercentageToken.prototype.toString = function () { + return "PERCENTAGE(" + this.value + ")"; + }; + PercentageToken.prototype.toJSON = function () { + var json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.value = this.value; + json.repr = this.repr; + return json; + }; + PercentageToken.prototype.toSource = function () { + return this.repr + "%"; + }; + + function DimensionToken() { + this.value = null; + this.type = "integer"; + this.repr = ""; + this.unit = ""; + } + DimensionToken.prototype = Object.create(CSSParserToken.prototype); + DimensionToken.prototype.tokenType = "dimension"; + DimensionToken.prototype.toString = function () { + return "DIM(" + this.value + "," + this.unit + ")"; + }; + DimensionToken.prototype.toJSON = function () { + var json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.value = this.value; + json.type = this.type; + json.repr = this.repr; + json.unit = this.unit; + return json; + }; + DimensionToken.prototype.toSource = function () { + var source = this.repr; + var unit = escapeIdent(this.unit); + if (unit[0].toLowerCase() == "e" && (unit[1] == "-" || between(unit.charCodeAt(1), 0x30, 0x39))) { + // Unit is ambiguous with scinot + // Remove the leading "e", replace with escape. + unit = "\\65 " + unit.slice(1, unit.length); + } + return source + unit; + }; + + function escapeIdent(string) { + string = '' + string; + var result = ''; + var firstcode = string.charCodeAt(0); + for (var i = 0; i < string.length; i++) { + var code = string.charCodeAt(i); + if (code === 0x0) { + throw new InvalidCharacterError('Invalid character: the input contains U+0000.'); + } + + if (between(code, 0x1, 0x1f) || code == 0x7f || i === 0 && between(code, 0x30, 0x39) || i == 1 && between(code, 0x30, 0x39) && firstcode == 0x2d) { + result += '\\' + code.toString(16) + ' '; + } else if (code >= 0x80 || code == 0x2d || code == 0x5f || between(code, 0x30, 0x39) || between(code, 0x41, 0x5a) || between(code, 0x61, 0x7a)) { + result += string[i]; + } else { + result += '\\' + string[i]; + } + } + return result; + } + + function escapeHash(string) { + // Escapes the contents of "unrestricted"-type hash tokens. + // Won't preserve the ID-ness of "id"-type hash tokens; + // use escapeIdent() for that. + string = '' + string; + var result = ''; + for (var i = 0; i < string.length; i++) { + var code = string.charCodeAt(i); + if (code === 0x0) { + throw new InvalidCharacterError('Invalid character: the input contains U+0000.'); + } + + if (code >= 0x80 || code == 0x2d || code == 0x5f || between(code, 0x30, 0x39) || between(code, 0x41, 0x5a) || between(code, 0x61, 0x7a)) { + result += string[i]; + } else { + result += '\\' + code.toString(16) + ' '; + } + } + return result; + } + + function escapeString(string) { + string = '' + string; + var result = ''; + for (var i = 0; i < string.length; i++) { + var code = string.charCodeAt(i); + + if (code === 0x0) { + throw new InvalidCharacterError('Invalid character: the input contains U+0000.'); + } + + if (between(code, 0x1, 0x1f) || code == 0x7f) { + result += '\\' + code.toString(16) + ' '; + } else if (code == 0x22 || code == 0x5c) { + result += '\\' + string[i]; + } else { + result += string[i]; + } + } + return result; + } + + // Exportation. + exports.tokenize = tokenize; + exports.IdentToken = IdentToken; + exports.FunctionToken = FunctionToken; + exports.AtKeywordToken = AtKeywordToken; + exports.HashToken = HashToken; + exports.StringToken = StringToken; + exports.BadStringToken = BadStringToken; + exports.URLToken = URLToken; + exports.BadURLToken = BadURLToken; + exports.DelimToken = DelimToken; + exports.NumberToken = NumberToken; + exports.PercentageToken = PercentageToken; + exports.DimensionToken = DimensionToken; + exports.IncludeMatchToken = IncludeMatchToken; + exports.DashMatchToken = DashMatchToken; + exports.PrefixMatchToken = PrefixMatchToken; + exports.SuffixMatchToken = SuffixMatchToken; + exports.SubstringMatchToken = SubstringMatchToken; + exports.ColumnToken = ColumnToken; + exports.WhitespaceToken = WhitespaceToken; + exports.CDOToken = CDOToken; + exports.CDCToken = CDCToken; + exports.ColonToken = ColonToken; + exports.SemicolonToken = SemicolonToken; + exports.CommaToken = CommaToken; + exports.OpenParenToken = OpenParenToken; + exports.CloseParenToken = CloseParenToken; + exports.OpenSquareToken = OpenSquareToken; + exports.CloseSquareToken = CloseSquareToken; + exports.OpenCurlyToken = OpenCurlyToken; + exports.CloseCurlyToken = CloseCurlyToken; + exports.EOFToken = EOFToken; + exports.CSSParserToken = CSSParserToken; + exports.GroupingToken = GroupingToken; + + function TokenStream(tokens) { + // Assume that tokens is a iterator. + this.tokens = tokens; + this.token = undefined; + this.stored = []; + } + TokenStream.prototype.consume = function (num) { + if (num === undefined) num = 1; + while (num-- > 0) { + if (this.stored.length > 0) { + this.token = this.stored.shift(); + } else { + var n = this.tokens.next(); + while (!n.done && n.value instanceof CommentToken) { + n = this.tokens.next(); + } + if (n.done) { + this.token = new EOFToken(); + break; + } + this.token = n.value; + } + } + //console.log(this.i, this.token); + return true; + }; + TokenStream.prototype.next = function () { + if (this.stored.length === 0) { + var n = this.tokens.next(); + while (!n.done && n.value instanceof CommentToken) { + n = this.tokens.next(); + } + if (n.done) return new EOFToken(); + this.stored.push(n.value); + } + return this.stored[0]; + }; + TokenStream.prototype.reconsume = function () { + this.stored.unshift(this.token); + }; + + function parseerror(s, msg) { + console.log("Parse error at token " + s.i + ": " + s.token + ".\n" + msg); + return true; + } + function donothing() { + return true; + } + + function consumeAListOfRules(s, topLevel) { + var rules = []; + var rule; + while (s.consume()) { + if (s.token instanceof WhitespaceToken) { + continue; + } else if (s.token instanceof EOFToken) { + return rules; + } else if (s.token instanceof CDOToken || s.token instanceof CDCToken) { + if (topLevel == "top-level") continue; + s.reconsume(); + if (rule = consumeAQualifiedRule(s)) rules.push(rule); + } else if (s.token instanceof AtKeywordToken) { + s.reconsume(); + if (rule = consumeAnAtRule(s)) rules.push(rule); + } else { + s.reconsume(); + if (rule = consumeAQualifiedRule(s)) rules.push(rule); + } + } + } + + function consumeAnAtRule(s) { + s.consume(); + var rule = new AtRule(s.token.value); + while (s.consume()) { + if (s.token instanceof SemicolonToken || s.token instanceof EOFToken) { + return rule; + } else if (s.token instanceof OpenCurlyToken) { + rule.value = consumeASimpleBlock(s); + return rule; + } else { + s.reconsume(); + rule.prelude.push(consumeAComponentValue(s)); + } + } + } + + function consumeAQualifiedRule(s) { + var rule = new QualifiedRule(); + while (s.consume()) { + if (s.token instanceof EOFToken) { + parseerror(s, "Hit EOF when trying to parse the prelude of a qualified rule."); + return; + } else if (s.token instanceof OpenCurlyToken) { + rule.value = consumeASimpleBlock(s); + return rule; + } else { + s.reconsume(); + rule.prelude.push(consumeAComponentValue(s)); + } + } + } + + function consumeAListOfDeclarations(s) { + var decls = []; + while (s.consume()) { + if (s.token instanceof WhitespaceToken || s.token instanceof SemicolonToken) { + donothing(); + } else if (s.token instanceof EOFToken) { + return decls; + } else if (s.token instanceof AtKeywordToken) { + s.reconsume(); + decls.push(consumeAnAtRule(s)); + } else if (s.token instanceof IdentToken) { + var temp = [s.token]; + while (!(s.next() instanceof SemicolonToken || s.next() instanceof EOFToken)) { + temp.push(consumeAComponentValue(s)); + }var decl; + if (decl = consumeADeclaration(new TokenStream(temp))) decls.push(decl); + } else { + parseerror(s); + s.reconsume(); + while (!(s.next() instanceof SemicolonToken || s.next() instanceof EOFToken)) { + consumeAComponentValue(s); + } + } + } + } + + function consumeADeclaration(s) { + // Assumes that the next input token will be an ident token. + s.consume(); + var decl = new Declaration(s.token.value); + while (s.next() instanceof WhitespaceToken) { + s.consume(); + }if (!(s.next() instanceof ColonToken)) { + parseerror(s); + return; + } else { + s.consume(); + } + while (!(s.next() instanceof EOFToken)) { + decl.value.push(consumeAComponentValue(s)); + } + var foundImportant = false; + for (var i = decl.value.length - 1; i >= 0; i--) { + if (decl.value[i] instanceof WhitespaceToken) { + continue; + } else if (decl.value[i] instanceof IdentToken && decl.value[i].ASCIIMatch("important")) { + foundImportant = true; + } else if (foundImportant && decl.value[i] instanceof DelimToken && decl.value[i].value == "!") { + decl.value.splice(i, decl.value.length); + decl.important = true; + break; + } else { + break; + } + } + return decl; + } + + function consumeAComponentValue(s) { + s.consume(); + if (s.token instanceof OpenCurlyToken || s.token instanceof OpenSquareToken || s.token instanceof OpenParenToken) return consumeASimpleBlock(s); + if (s.token instanceof FunctionToken) return consumeAFunction(s); + return s.token; + } + + function consumeASimpleBlock(s) { + var mirror = s.token.mirror; + var block = new SimpleBlock(s.token.value); + block.startToken = s.token; + while (s.consume()) { + if (s.token instanceof EOFToken || s.token instanceof GroupingToken && s.token.value == mirror) return block;else { + s.reconsume(); + block.value.push(consumeAComponentValue(s)); + } + } + } + + function consumeAFunction(s) { + var func = new Func(s.token.value); + while (s.consume()) { + if (s.token instanceof EOFToken || s.token instanceof CloseParenToken) return func;else { + s.reconsume(); + func.value.push(consumeAComponentValue(s)); + } + } + } + + function normalizeInput(input) { + if (typeof input == "string") return new TokenStream(tokenize(input)); + if (input instanceof TokenStream) return input; + if (typeof input.next == "function") return new TokenStream(input); + if (input.length !== undefined) return new TokenStream(input[Symbol.iterator]());else throw SyntaxError(input); + } + + function parseAStylesheet(s) { + s = normalizeInput(s); + var sheet = new Stylesheet(); + sheet.value = consumeAListOfRules(s, "top-level"); + return sheet; + } + + function parseAListOfRules(s) { + s = normalizeInput(s); + return consumeAListOfRules(s); + } + + function parseARule(s) { + s = normalizeInput(s); + while (s.next() instanceof WhitespaceToken) { + s.consume(); + }if (s.next() instanceof EOFToken) throw SyntaxError(); + var rule; + var startToken = s.next(); + if (startToken instanceof AtKeywordToken) { + rule = consumeAnAtRule(s); + } else { + rule = consumeAQualifiedRule(s); + if (!rule) throw SyntaxError(); + } + rule.startToken = startToken; + rule.endToken = s.token; + return rule; + } + + function parseADeclaration(s) { + s = normalizeInput(s); + while (s.next() instanceof WhitespaceToken) { + s.consume(); + }if (!(s.next() instanceof IdentToken)) throw SyntaxError(); + var decl = consumeADeclaration(s); + if (decl) return decl;else throw SyntaxError(); + } + + function parseAListOfDeclarations(s) { + s = normalizeInput(s); + return consumeAListOfDeclarations(s); + } + + function parseAComponentValue(s) { + s = normalizeInput(s); + while (s.next() instanceof WhitespaceToken) { + s.consume(); + }if (s.next() instanceof EOFToken) throw SyntaxError(); + var val = consumeAComponentValue(s); + if (!val) throw SyntaxError(); + while (s.next() instanceof WhitespaceToken) { + s.consume(); + }if (s.next() instanceof EOFToken) return val; + throw SyntaxError(); + } + + function parseAListOfComponentValues(s) { + s = normalizeInput(s); + var vals = []; + while (true) { + var val = consumeAComponentValue(s); + if (val instanceof EOFToken) return vals;else vals.push(val); + } + } + + function parseACommaSeparatedListOfComponentValues(s) { + s = normalizeInput(s); + var listOfCVLs = []; + while (true) { + var vals = []; + while (true) { + var val = consumeAComponentValue(s); + if (val instanceof EOFToken) { + listOfCVLs.push(vals); + return listOfCVLs; + } else if (val instanceof CommaToken) { + listOfCVLs.push(vals); + break; + } else { + vals.push(val); + } + } + } + } + + function CSSParserRule() { + throw "Abstract Base Class"; + } + CSSParserRule.prototype.toString = function (indent) { + return JSON.stringify(this, null, indent); + }; + CSSParserRule.prototype.toJSON = function () { + return { type: this.type, value: this.value }; + }; + + function Stylesheet() { + this.value = []; + return this; + } + Stylesheet.prototype = Object.create(CSSParserRule.prototype); + Stylesheet.prototype.type = "STYLESHEET"; + + function AtRule(name) { + this.name = name; + this.prelude = []; + this.value = null; + return this; + } + AtRule.prototype = Object.create(CSSParserRule.prototype); + AtRule.prototype.type = "AT-RULE"; + AtRule.prototype.toJSON = function () { + var json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.name = this.name; + json.prelude = this.prelude; + return json; + }; + + function QualifiedRule() { + this.prelude = []; + this.value = []; + return this; + } + QualifiedRule.prototype = Object.create(CSSParserRule.prototype); + QualifiedRule.prototype.type = "QUALIFIED-RULE"; + QualifiedRule.prototype.toJSON = function () { + var json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.prelude = this.prelude; + return json; + }; + + function Declaration(name) { + this.name = name; + this.value = []; + this.important = false; + return this; + } + Declaration.prototype = Object.create(CSSParserRule.prototype); + Declaration.prototype.type = "DECLARATION"; + Declaration.prototype.toJSON = function () { + var json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.name = this.name; + json.important = this.important; + return json; + }; + + function SimpleBlock(type) { + this.name = type; + this.value = []; + return this; + } + SimpleBlock.prototype = Object.create(CSSParserRule.prototype); + SimpleBlock.prototype.type = "BLOCK"; + SimpleBlock.prototype.toJSON = function () { + var json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.name = this.name; + return json; + }; + + function Func(name) { + this.name = name; + this.value = []; + return this; + } + Func.prototype = Object.create(CSSParserRule.prototype); + Func.prototype.type = "FUNCTION"; + Func.prototype.toJSON = function () { + var json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.name = this.name; + return json; + }; + + function CSSLexer(text) { + this.stream = tokenize(text, { + loc: true, + offsets: true, + keepComments: true + }); + this.lineNumber = 0; + this.columnNumber = 0; + return this; + } + + CSSLexer.prototype.performEOFFixup = function (input, preserveBackslash) { + // Just lie for now. + return ""; + }; + + CSSLexer.prototype.nextToken = function () { + if (!this.stream) { + return null; + } + var v = this.stream.next(); + if (v.done || v.value.tokenType === "EOF") { + this.stream = null; + return null; + } + this.lineNumber = v.value.loc.start.line; + this.columnNumber = v.value.loc.start.column; + return v.value; + }; + + // Exportation. + exports.CSSParserRule = CSSParserRule; + exports.Stylesheet = Stylesheet; + exports.AtRule = AtRule; + exports.QualifiedRule = QualifiedRule; + exports.Declaration = Declaration; + exports.SimpleBlock = SimpleBlock; + exports.Func = Func; + exports.parseAStylesheet = parseAStylesheet; + exports.parseAListOfRules = parseAListOfRules; + exports.parseARule = parseARule; + exports.parseADeclaration = parseADeclaration; + exports.parseAListOfDeclarations = parseAListOfDeclarations; + exports.parseAComponentValue = parseAComponentValue; + exports.parseAListOfComponentValues = parseAListOfComponentValues; + exports.parseACommaSeparatedListOfComponentValues = parseACommaSeparatedListOfComponentValues; + exports.CSSLexer = CSSLexer; + }); + +/***/ }, +/* 64 */ +/***/ function(module, exports) { + + // auto-generated from nsColorNameList.h + var cssColors = { + aliceblue: [240, 248, 255], + antiquewhite: [250, 235, 215], + aqua: [0, 255, 255], + aquamarine: [127, 255, 212], + azure: [240, 255, 255], + beige: [245, 245, 220], + bisque: [255, 228, 196], + black: [0, 0, 0], + blanchedalmond: [255, 235, 205], + blue: [0, 0, 255], + blueviolet: [138, 43, 226], + brown: [165, 42, 42], + burlywood: [222, 184, 135], + cadetblue: [95, 158, 160], + chartreuse: [127, 255, 0], + chocolate: [210, 105, 30], + coral: [255, 127, 80], + cornflowerblue: [100, 149, 237], + cornsilk: [255, 248, 220], + crimson: [220, 20, 60], + cyan: [0, 255, 255], + darkblue: [0, 0, 139], + darkcyan: [0, 139, 139], + darkgoldenrod: [184, 134, 11], + darkgray: [169, 169, 169], + darkgreen: [0, 100, 0], + darkgrey: [169, 169, 169], + darkkhaki: [189, 183, 107], + darkmagenta: [139, 0, 139], + darkolivegreen: [85, 107, 47], + darkorange: [255, 140, 0], + darkorchid: [153, 50, 204], + darkred: [139, 0, 0], + darksalmon: [233, 150, 122], + darkseagreen: [143, 188, 143], + darkslateblue: [72, 61, 139], + darkslategray: [47, 79, 79], + darkslategrey: [47, 79, 79], + darkturquoise: [0, 206, 209], + darkviolet: [148, 0, 211], + deeppink: [255, 20, 147], + deepskyblue: [0, 191, 255], + dimgray: [105, 105, 105], + dimgrey: [105, 105, 105], + dodgerblue: [30, 144, 255], + firebrick: [178, 34, 34], + floralwhite: [255, 250, 240], + forestgreen: [34, 139, 34], + fuchsia: [255, 0, 255], + gainsboro: [220, 220, 220], + ghostwhite: [248, 248, 255], + gold: [255, 215, 0], + goldenrod: [218, 165, 32], + gray: [128, 128, 128], + grey: [128, 128, 128], + green: [0, 128, 0], + greenyellow: [173, 255, 47], + honeydew: [240, 255, 240], + hotpink: [255, 105, 180], + indianred: [205, 92, 92], + indigo: [75, 0, 130], + ivory: [255, 255, 240], + khaki: [240, 230, 140], + lavender: [230, 230, 250], + lavenderblush: [255, 240, 245], + lawngreen: [124, 252, 0], + lemonchiffon: [255, 250, 205], + lightblue: [173, 216, 230], + lightcoral: [240, 128, 128], + lightcyan: [224, 255, 255], + lightgoldenrodyellow: [250, 250, 210], + lightgray: [211, 211, 211], + lightgreen: [144, 238, 144], + lightgrey: [211, 211, 211], + lightpink: [255, 182, 193], + lightsalmon: [255, 160, 122], + lightseagreen: [32, 178, 170], + lightskyblue: [135, 206, 250], + lightslategray: [119, 136, 153], + lightslategrey: [119, 136, 153], + lightsteelblue: [176, 196, 222], + lightyellow: [255, 255, 224], + lime: [0, 255, 0], + limegreen: [50, 205, 50], + linen: [250, 240, 230], + magenta: [255, 0, 255], + maroon: [128, 0, 0], + mediumaquamarine: [102, 205, 170], + mediumblue: [0, 0, 205], + mediumorchid: [186, 85, 211], + mediumpurple: [147, 112, 219], + mediumseagreen: [60, 179, 113], + mediumslateblue: [123, 104, 238], + mediumspringgreen: [0, 250, 154], + mediumturquoise: [72, 209, 204], + mediumvioletred: [199, 21, 133], + midnightblue: [25, 25, 112], + mintcream: [245, 255, 250], + mistyrose: [255, 228, 225], + moccasin: [255, 228, 181], + navajowhite: [255, 222, 173], + navy: [0, 0, 128], + oldlace: [253, 245, 230], + olive: [128, 128, 0], + olivedrab: [107, 142, 35], + orange: [255, 165, 0], + orangered: [255, 69, 0], + orchid: [218, 112, 214], + palegoldenrod: [238, 232, 170], + palegreen: [152, 251, 152], + paleturquoise: [175, 238, 238], + palevioletred: [219, 112, 147], + papayawhip: [255, 239, 213], + peachpuff: [255, 218, 185], + peru: [205, 133, 63], + pink: [255, 192, 203], + plum: [221, 160, 221], + powderblue: [176, 224, 230], + purple: [128, 0, 128], + rebeccapurple: [102, 51, 153], + red: [255, 0, 0], + rosybrown: [188, 143, 143], + royalblue: [65, 105, 225], + saddlebrown: [139, 69, 19], + salmon: [250, 128, 114], + sandybrown: [244, 164, 96], + seagreen: [46, 139, 87], + seashell: [255, 245, 238], + sienna: [160, 82, 45], + silver: [192, 192, 192], + skyblue: [135, 206, 235], + slateblue: [106, 90, 205], + slategray: [112, 128, 144], + slategrey: [112, 128, 144], + snow: [255, 250, 250], + springgreen: [0, 255, 127], + steelblue: [70, 130, 180], + tan: [210, 180, 140], + teal: [0, 128, 128], + thistle: [216, 191, 216], + tomato: [255, 99, 71], + turquoise: [64, 224, 208], + violet: [238, 130, 238], + wheat: [245, 222, 179], + white: [255, 255, 255], + whitesmoke: [245, 245, 245], + yellow: [255, 255, 0], + yellowgreen: [154, 205, 50] + }; + module.exports = { cssColors }; + +/***/ }, +/* 65 */ +/***/ function(module, exports) { + + // auto-generated by means you would rather not know + var cssProperties={"-moz-appearance":{inherited:false,supports:0,values:["-moz-gtk-info-bar","-moz-mac-disclosure-button-closed","-moz-mac-disclosure-button-open","-moz-mac-fullscreen-button","-moz-mac-help-button","-moz-mac-vibrancy-dark","-moz-mac-vibrancy-light","-moz-win-borderless-glass","-moz-win-browsertabbar-toolbox","-moz-win-communications-toolbox","-moz-win-exclude-glass","-moz-win-glass","-moz-win-media-toolbox","-moz-window-button-box","-moz-window-button-box-maximized","-moz-window-button-close","-moz-window-button-maximize","-moz-window-button-minimize","-moz-window-button-restore","-moz-window-frame-bottom","-moz-window-frame-left","-moz-window-frame-right","-moz-window-titlebar","-moz-window-titlebar-maximized","button","button-arrow-down","button-arrow-next","button-arrow-previous","button-arrow-up","button-bevel","button-focus","caret","checkbox","checkbox-container","checkbox-label","checkmenuitem","dialog","dualbutton","groupbox","inherit","initial","listbox","listitem","menuarrow","menubar","menucheckbox","menuimage","menuitem","menuitemtext","menulist","menulist-button","menulist-text","menulist-textfield","menupopup","menuradio","menuseparator","meterbar","meterchunk","none","number-input","progressbar","progressbar-vertical","progresschunk","progresschunk-vertical","radio","radio-container","radio-label","radiomenuitem","range","range-thumb","resizer","resizerpanel","scale-horizontal","scale-vertical","scalethumb-horizontal","scalethumb-vertical","scalethumbend","scalethumbstart","scalethumbtick","scrollbar","scrollbar-small","scrollbarbutton-down","scrollbarbutton-left","scrollbarbutton-right","scrollbarbutton-up","scrollbarthumb-horizontal","scrollbarthumb-vertical","scrollbartrack-horizontal","scrollbartrack-vertical","searchfield","separator","spinner","spinner-downbutton","spinner-textfield","spinner-upbutton","splitter","statusbar","statusbarpanel","tab","tab-scroll-arrow-back","tab-scroll-arrow-forward","tabpanel","tabpanels","textfield","textfield-multiline","toolbar","toolbarbutton","toolbarbutton-dropdown","toolbargripper","toolbox","tooltip","treeheader","treeheadercell","treeheadersortarrow","treeitem","treeline","treetwisty","treetwistyopen","treeview","unset","window"]},"-moz-outline-radius-topleft":{inherited:false,supports:3,values:["inherit","initial","unset"]},"-moz-outline-radius-topright":{inherited:false,supports:3,values:["inherit","initial","unset"]},"-moz-outline-radius-bottomright":{inherited:false,supports:3,values:["inherit","initial","unset"]},"-moz-outline-radius-bottomleft":{inherited:false,supports:3,values:["inherit","initial","unset"]},"-moz-tab-size":{inherited:true,supports:1024,values:["inherit","initial","unset"]},"animation-delay":{inherited:false,supports:64,values:["inherit","initial","unset"]},"animation-direction":{inherited:false,supports:0,values:["alternate","alternate-reverse","inherit","initial","normal","reverse","unset"]},"animation-duration":{inherited:false,supports:64,values:["inherit","initial","unset"]},"animation-fill-mode":{inherited:false,supports:0,values:["backwards","both","forwards","inherit","initial","none","unset"]},"animation-iteration-count":{inherited:false,supports:1024,values:["infinite","inherit","initial","unset"]},"animation-name":{inherited:false,supports:0,values:["inherit","initial","none","unset"]},"animation-play-state":{inherited:false,supports:0,values:["inherit","initial","paused","running","unset"]},"animation-timing-function":{inherited:false,supports:256,values:["cubic-bezier","ease","ease-in","ease-in-out","ease-out","inherit","initial","linear","step-end","step-start","steps","unset"]},"background-attachment":{inherited:false,supports:0,values:["fixed","inherit","initial","local","scroll","unset"]},"background-clip":{inherited:false,supports:0,values:["border-box","content-box","inherit","initial","padding-box","unset"]},"background-color":{inherited:false,supports:4,values:["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"background-image":{inherited:false,supports:648,values:["-moz-element","-moz-image-rect","-moz-linear-gradient","-moz-radial-gradient","-moz-repeating-linear-gradient","-moz-repeating-radial-gradient","inherit","initial","linear-gradient","none","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","unset","url"]},"background-blend-mode":{inherited:false,supports:0,values:["color","color-burn","color-dodge","darken","difference","exclusion","hard-light","hue","inherit","initial","lighten","luminosity","multiply","normal","overlay","saturation","screen","soft-light","unset"]},"background-origin":{inherited:false,supports:0,values:["border-box","content-box","inherit","initial","padding-box","unset"]},"background-position":{inherited:false,supports:3,values:["inherit","initial","unset"]},"background-repeat":{inherited:false,supports:0,values:["inherit","initial","no-repeat","repeat","repeat-x","repeat-y","unset"]},"background-size":{inherited:false,supports:3,values:["inherit","initial","unset"]},"-moz-binding":{inherited:false,supports:8,values:["inherit","initial","none","unset","url"]},"block-size":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"border-block-end-color":{inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-block-end-style":{inherited:false,supports:0,values:["dashed","dotted","double","groove","hidden","inherit","initial","inset","none","outset","ridge","solid","unset"]},"border-block-end-width":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","medium","thick","thin","unset"]},"border-block-start-color":{inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-block-start-style":{inherited:false,supports:0,values:["dashed","dotted","double","groove","hidden","inherit","initial","inset","none","outset","ridge","solid","unset"]},"border-block-start-width":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","medium","thick","thin","unset"]},"border-bottom-color":{inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"-moz-border-bottom-colors":{inherited:false,supports:4,values:["inherit","initial","unset"]},"border-bottom-style":{inherited:false,supports:0,values:["dashed","dotted","double","groove","hidden","inherit","initial","inset","none","outset","ridge","solid","unset"]},"border-bottom-width":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","medium","thick","thin","unset"]},"border-collapse":{inherited:true,supports:0,values:["collapse","inherit","initial","separate","unset"]},"border-image-source":{inherited:false,supports:648,values:["-moz-element","-moz-image-rect","-moz-linear-gradient","-moz-radial-gradient","-moz-repeating-linear-gradient","-moz-repeating-radial-gradient","inherit","initial","linear-gradient","none","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","unset","url"]},"border-image-slice":{inherited:false,supports:1026,values:["inherit","initial","unset"]},"border-image-width":{inherited:false,supports:1027,values:["inherit","initial","unset"]},"border-image-outset":{inherited:false,supports:1025,values:["inherit","initial","unset"]},"border-image-repeat":{inherited:false,supports:0,values:["inherit","initial","unset"]},"border-inline-end-color":{inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-inline-end-style":{inherited:false,supports:0,values:["dashed","dotted","double","groove","hidden","inherit","initial","inset","none","outset","ridge","solid","unset"]},"border-inline-end-width":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","medium","thick","thin","unset"]},"border-inline-start-color":{inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-inline-start-style":{inherited:false,supports:0,values:["dashed","dotted","double","groove","hidden","inherit","initial","inset","none","outset","ridge","solid","unset"]},"border-inline-start-width":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","medium","thick","thin","unset"]},"border-left-color":{inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"-moz-border-left-colors":{inherited:false,supports:4,values:["inherit","initial","unset"]},"border-left-style":{inherited:false,supports:0,values:["dashed","dotted","double","groove","hidden","inherit","initial","inset","none","outset","ridge","solid","unset"]},"border-left-width":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","medium","thick","thin","unset"]},"border-right-color":{inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"-moz-border-right-colors":{inherited:false,supports:4,values:["inherit","initial","unset"]},"border-right-style":{inherited:false,supports:0,values:["dashed","dotted","double","groove","hidden","inherit","initial","inset","none","outset","ridge","solid","unset"]},"border-right-width":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","medium","thick","thin","unset"]},"border-spacing":{inherited:true,supports:1,values:["inherit","initial","unset"]},"border-top-color":{inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"-moz-border-top-colors":{inherited:false,supports:4,values:["inherit","initial","unset"]},"border-top-style":{inherited:false,supports:0,values:["dashed","dotted","double","groove","hidden","inherit","initial","inset","none","outset","ridge","solid","unset"]},"border-top-width":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","medium","thick","thin","unset"]},"border-top-left-radius":{inherited:false,supports:3,values:["inherit","initial","unset"]},"border-top-right-radius":{inherited:false,supports:3,values:["inherit","initial","unset"]},"border-bottom-right-radius":{inherited:false,supports:3,values:["inherit","initial","unset"]},"border-bottom-left-radius":{inherited:false,supports:3,values:["inherit","initial","unset"]},"bottom":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"box-decoration-break":{inherited:false,supports:0,values:["clone","inherit","initial","slice","unset"]},"box-shadow":{inherited:false,supports:5,values:["inherit","initial","unset"]},"box-sizing":{inherited:false,supports:0,values:["border-box","content-box","inherit","initial","padding-box","unset"]},"caption-side":{inherited:true,supports:0,values:["bottom","bottom-outside","inherit","initial","left","right","top","top-outside","unset"]},"clear":{inherited:false,supports:0,values:["both","inherit","initial","inline-end","inline-start","left","none","right","unset"]},"clip":{inherited:false,supports:0,values:["inherit","initial","unset"]},"color":{inherited:true,supports:4,values:["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"-moz-column-count":{inherited:false,supports:1024,values:["auto","inherit","initial","unset"]},"-moz-column-fill":{inherited:false,supports:0,values:["auto","balance","inherit","initial","unset"]},"-moz-column-width":{inherited:false,supports:1,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"-moz-column-gap":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","normal","unset"]},"-moz-column-rule-color":{inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"-moz-column-rule-style":{inherited:false,supports:0,values:["dashed","dotted","double","groove","hidden","inherit","initial","inset","none","outset","ridge","solid","unset"]},"-moz-column-rule-width":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","medium","thick","thin","unset"]},"contain":{inherited:false,supports:0,values:["inherit","initial","layout","none","paint","strict","style","unset"]},"content":{inherited:false,supports:8,values:["inherit","initial","unset"]},"-moz-control-character-visibility":{inherited:true,supports:0,values:["hidden","inherit","initial","unset","visible"]},"counter-increment":{inherited:false,supports:0,values:["inherit","initial","unset"]},"counter-reset":{inherited:false,supports:0,values:["inherit","initial","unset"]},"cursor":{inherited:true,supports:8,values:["inherit","initial","unset"]},"direction":{inherited:true,supports:0,values:["inherit","initial","ltr","rtl","unset"]},"display":{inherited:false,supports:0,values:["-moz-box","-moz-deck","-moz-grid","-moz-grid-group","-moz-grid-line","-moz-groupbox","-moz-inline-box","-moz-inline-grid","-moz-inline-stack","-moz-popup","-moz-stack","block","contents","flex","grid","inherit","initial","inline","inline-block","inline-flex","inline-grid","inline-table","list-item","none","ruby","ruby-base","ruby-base-container","ruby-text","ruby-text-container","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","unset"]},"empty-cells":{inherited:true,supports:0,values:["hide","inherit","initial","show","unset"]},"align-content":{inherited:false,supports:0,values:["inherit","initial","unset"]},"align-items":{inherited:false,supports:0,values:["inherit","initial","unset"]},"align-self":{inherited:false,supports:0,values:["inherit","initial","unset"]},"flex-basis":{inherited:false,supports:3,values:["-moz-available","-moz-calc","-moz-fit-content","-moz-max-content","-moz-min-content","auto","calc","inherit","initial","unset"]},"flex-direction":{inherited:false,supports:0,values:["column","column-reverse","inherit","initial","row","row-reverse","unset"]},"flex-grow":{inherited:false,supports:1024,values:["inherit","initial","unset"]},"flex-shrink":{inherited:false,supports:1024,values:["inherit","initial","unset"]},"flex-wrap":{inherited:false,supports:0,values:["inherit","initial","nowrap","unset","wrap","wrap-reverse"]},"order":{inherited:false,supports:1024,values:["inherit","initial","unset"]},"justify-content":{inherited:false,supports:0,values:["inherit","initial","unset"]},"justify-items":{inherited:false,supports:0,values:["inherit","initial","unset"]},"justify-self":{inherited:false,supports:0,values:["inherit","initial","unset"]},"float":{inherited:false,supports:0,values:["inherit","initial","inline-end","inline-start","left","none","right","unset"]},"-moz-float-edge":{inherited:false,supports:0,values:["content-box","inherit","initial","margin-box","unset"]},"font-family":{inherited:true,supports:0,values:["inherit","initial","unset"]},"font-feature-settings":{inherited:true,supports:0,values:["inherit","initial","unset"]},"font-kerning":{inherited:true,supports:0,values:["auto","inherit","initial","none","normal","unset"]},"font-language-override":{inherited:true,supports:0,values:["inherit","initial","normal","unset"]},"font-size":{inherited:true,supports:3,values:["-moz-calc","calc","inherit","initial","large","larger","medium","small","smaller","unset","x-large","x-small","xx-large","xx-small"]},"font-size-adjust":{inherited:true,supports:1024,values:["inherit","initial","none","unset"]},"font-stretch":{inherited:true,supports:0,values:["condensed","expanded","extra-condensed","extra-expanded","inherit","initial","normal","semi-condensed","semi-expanded","ultra-condensed","ultra-expanded","unset"]},"font-style":{inherited:true,supports:0,values:["inherit","initial","italic","normal","oblique","unset"]},"font-synthesis":{inherited:true,supports:0,values:["inherit","initial","unset"]},"font-variant-alternates":{inherited:true,supports:0,values:["inherit","initial","unset"]},"font-variant-caps":{inherited:true,supports:0,values:["all-petite-caps","all-small-caps","inherit","initial","normal","petite-caps","small-caps","titling-caps","unicase","unset"]},"font-variant-east-asian":{inherited:true,supports:0,values:["inherit","initial","unset"]},"font-variant-ligatures":{inherited:true,supports:0,values:["inherit","initial","unset"]},"font-variant-numeric":{inherited:true,supports:0,values:["inherit","initial","unset"]},"font-variant-position":{inherited:true,supports:0,values:["inherit","initial","normal","sub","super","unset"]},"font-weight":{inherited:true,supports:1024,values:["inherit","initial","unset"]},"-moz-force-broken-image-icon":{inherited:false,supports:1024,values:["inherit","initial","unset"]},"grid-auto-flow":{inherited:false,supports:0,values:["inherit","initial","unset"]},"grid-auto-columns":{inherited:false,supports:3,values:["inherit","initial","unset"]},"grid-auto-rows":{inherited:false,supports:3,values:["inherit","initial","unset"]},"grid-template-areas":{inherited:false,supports:0,values:["inherit","initial","unset"]},"grid-template-columns":{inherited:false,supports:3,values:["inherit","initial","unset"]},"grid-template-rows":{inherited:false,supports:3,values:["inherit","initial","unset"]},"grid-column-start":{inherited:false,supports:1024,values:["inherit","initial","unset"]},"grid-column-end":{inherited:false,supports:1024,values:["inherit","initial","unset"]},"grid-row-start":{inherited:false,supports:1024,values:["inherit","initial","unset"]},"grid-row-end":{inherited:false,supports:1024,values:["inherit","initial","unset"]},"grid-column-gap":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","unset"]},"grid-row-gap":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","unset"]},"height":{inherited:false,supports:3,values:["-moz-available","-moz-calc","-moz-fit-content","-moz-max-content","-moz-min-content","auto","calc","inherit","initial","unset"]},"image-orientation":{inherited:true,supports:16,values:["inherit","initial","unset"]},"-moz-image-region":{inherited:true,supports:0,values:["inherit","initial","unset"]},"ime-mode":{inherited:false,supports:0,values:["active","auto","disabled","inactive","inherit","initial","normal","unset"]},"inline-size":{inherited:false,supports:3,values:["-moz-available","-moz-calc","-moz-fit-content","-moz-max-content","-moz-min-content","auto","calc","inherit","initial","unset"]},"left":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"letter-spacing":{inherited:true,supports:1,values:["-moz-calc","calc","inherit","initial","normal","unset"]},"line-height":{inherited:true,supports:1027,values:["-moz-block-height","inherit","initial","normal","unset"]},"list-style-image":{inherited:true,supports:8,values:["inherit","initial","none","unset","url"]},"list-style-position":{inherited:true,supports:0,values:["inherit","initial","inside","outside","unset"]},"list-style-type":{inherited:true,supports:0,values:["inherit","initial","unset"]},"margin-block-end":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"margin-block-start":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"margin-bottom":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"margin-inline-end":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"margin-inline-start":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"margin-left":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"margin-right":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"margin-top":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"marker-offset":{inherited:false,supports:1,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"max-block-size":{inherited:false,supports:3,values:["-moz-calc","calc","inherit","initial","none","unset"]},"max-height":{inherited:false,supports:3,values:["-moz-available","-moz-calc","-moz-fit-content","-moz-max-content","-moz-min-content","calc","inherit","initial","none","unset"]},"max-inline-size":{inherited:false,supports:3,values:["-moz-available","-moz-calc","-moz-fit-content","-moz-max-content","-moz-min-content","calc","inherit","initial","none","unset"]},"max-width":{inherited:false,supports:3,values:["-moz-available","-moz-calc","-moz-fit-content","-moz-max-content","-moz-min-content","calc","inherit","initial","none","unset"]},"min-height":{inherited:false,supports:3,values:["-moz-available","-moz-calc","-moz-fit-content","-moz-max-content","-moz-min-content","auto","calc","inherit","initial","unset"]},"min-block-size":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"min-inline-size":{inherited:false,supports:3,values:["-moz-available","-moz-calc","-moz-fit-content","-moz-max-content","-moz-min-content","auto","calc","inherit","initial","unset"]},"min-width":{inherited:false,supports:3,values:["-moz-available","-moz-calc","-moz-fit-content","-moz-max-content","-moz-min-content","auto","calc","inherit","initial","unset"]},"mix-blend-mode":{inherited:false,supports:0,values:["color","color-burn","color-dodge","darken","difference","exclusion","hard-light","hue","inherit","initial","lighten","luminosity","multiply","normal","overlay","saturation","screen","soft-light","unset"]},"isolation":{inherited:false,supports:0,values:["auto","inherit","initial","isolate","unset"]},"object-fit":{inherited:false,supports:0,values:["contain","cover","fill","inherit","initial","none","scale-down","unset"]},"object-position":{inherited:false,supports:3,values:["inherit","initial","unset"]},"offset-block-end":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"offset-block-start":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"offset-inline-end":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"offset-inline-start":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"opacity":{inherited:false,supports:1024,values:["inherit","initial","unset"]},"-moz-orient":{inherited:false,supports:0,values:["block","horizontal","inherit","initial","inline","unset","vertical"]},"outline-color":{inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"outline-style":{inherited:false,supports:0,values:["auto","dashed","dotted","double","groove","inherit","initial","inset","none","outset","ridge","solid","unset"]},"outline-width":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","medium","thick","thin","unset"]},"outline-offset":{inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","unset"]},"overflow-x":{inherited:false,supports:0,values:["-moz-hidden-unscrollable","auto","hidden","inherit","initial","scroll","unset","visible"]},"overflow-y":{inherited:false,supports:0,values:["-moz-hidden-unscrollable","auto","hidden","inherit","initial","scroll","unset","visible"]},"padding-block-end":{inherited:false,supports:3,values:["-moz-calc","calc","inherit","initial","unset"]},"padding-block-start":{inherited:false,supports:3,values:["-moz-calc","calc","inherit","initial","unset"]},"padding-bottom":{inherited:false,supports:3,values:["-moz-calc","calc","inherit","initial","unset"]},"padding-inline-end":{inherited:false,supports:3,values:["-moz-calc","calc","inherit","initial","unset"]},"padding-inline-start":{inherited:false,supports:3,values:["-moz-calc","calc","inherit","initial","unset"]},"padding-left":{inherited:false,supports:3,values:["-moz-calc","calc","inherit","initial","unset"]},"padding-right":{inherited:false,supports:3,values:["-moz-calc","calc","inherit","initial","unset"]},"padding-top":{inherited:false,supports:3,values:["-moz-calc","calc","inherit","initial","unset"]},"page-break-after":{inherited:false,supports:0,values:["always","auto","avoid","inherit","initial","left","right","unset"]},"page-break-before":{inherited:false,supports:0,values:["always","auto","avoid","inherit","initial","left","right","unset"]},"page-break-inside":{inherited:false,supports:0,values:["auto","avoid","inherit","initial","unset"]},"paint-order":{inherited:true,supports:0,values:["inherit","initial","unset"]},"pointer-events":{inherited:true,supports:0,values:["all","auto","fill","inherit","initial","none","painted","stroke","unset","visible","visiblefill","visiblepainted","visiblestroke"]},"position":{inherited:false,supports:0,values:["absolute","fixed","inherit","initial","relative","static","sticky","unset"]},"quotes":{inherited:true,supports:0,values:["inherit","initial","unset"]},"resize":{inherited:false,supports:0,values:["both","horizontal","inherit","initial","none","unset","vertical"]},"right":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"ruby-align":{inherited:true,supports:0,values:["center","inherit","initial","space-around","space-between","start","unset"]},"ruby-position":{inherited:true,supports:0,values:["inherit","initial","over","under","unset"]},"scroll-behavior":{inherited:false,supports:0,values:["auto","inherit","initial","smooth","unset"]},"scroll-snap-coordinate":{inherited:false,supports:3,values:["inherit","initial","unset"]},"scroll-snap-destination":{inherited:false,supports:3,values:["inherit","initial","unset"]},"scroll-snap-points-x":{inherited:false,supports:0,values:["inherit","initial","unset"]},"scroll-snap-points-y":{inherited:false,supports:0,values:["inherit","initial","unset"]},"scroll-snap-type-x":{inherited:false,supports:0,values:["inherit","initial","mandatory","none","proximity","unset"]},"scroll-snap-type-y":{inherited:false,supports:0,values:["inherit","initial","mandatory","none","proximity","unset"]},"table-layout":{inherited:false,supports:0,values:["auto","fixed","inherit","initial","unset"]},"text-align":{inherited:true,supports:0,values:["-moz-center","-moz-left","-moz-right","center","end","inherit","initial","justify","left","right","start","unset"]},"-moz-text-align-last":{inherited:true,supports:0,values:["auto","center","end","inherit","initial","justify","left","right","start","unset"]},"text-decoration-color":{inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"text-decoration-line":{inherited:false,supports:0,values:["inherit","initial","unset"]},"text-decoration-style":{inherited:false,supports:0,values:["-moz-none","dashed","dotted","double","inherit","initial","solid","unset","wavy"]},"text-indent":{inherited:true,supports:3,values:["-moz-calc","calc","inherit","initial","unset"]},"text-orientation":{inherited:true,supports:0,values:["inherit","initial","mixed","sideways","sideways-right","unset","upright"]},"text-overflow":{inherited:false,supports:0,values:["inherit","initial","unset"]},"text-shadow":{inherited:true,supports:5,values:["inherit","initial","unset"]},"-moz-text-size-adjust":{inherited:true,supports:0,values:["auto","inherit","initial","none","unset"]},"text-transform":{inherited:true,supports:0,values:["capitalize","full-width","inherit","initial","lowercase","none","unset","uppercase"]},"transform":{inherited:false,supports:0,values:["inherit","initial","unset"]},"transform-box":{inherited:false,supports:0,values:["border-box","fill-box","inherit","initial","unset","view-box"]},"transform-origin":{inherited:false,supports:3,values:["inherit","initial","unset"]},"perspective-origin":{inherited:false,supports:3,values:["inherit","initial","unset"]},"perspective":{inherited:false,supports:1,values:["inherit","initial","none","unset"]},"transform-style":{inherited:false,supports:0,values:["flat","inherit","initial","preserve-3d","unset"]},"backface-visibility":{inherited:false,supports:0,values:["hidden","inherit","initial","unset","visible"]},"top":{inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"transition-delay":{inherited:false,supports:64,values:["inherit","initial","unset"]},"transition-duration":{inherited:false,supports:64,values:["inherit","initial","unset"]},"transition-property":{inherited:false,supports:0,values:["all","inherit","initial","none","unset"]},"transition-timing-function":{inherited:false,supports:256,values:["cubic-bezier","ease","ease-in","ease-in-out","ease-out","inherit","initial","linear","step-end","step-start","steps","unset"]},"unicode-bidi":{inherited:false,supports:0,values:["-moz-isolate","-moz-isolate-override","-moz-plaintext","bidi-override","embed","inherit","initial","normal","unset"]},"-moz-user-focus":{inherited:true,supports:0,values:["ignore","inherit","initial","none","normal","select-after","select-all","select-before","select-menu","select-same","unset"]},"-moz-user-input":{inherited:true,supports:0,values:["auto","disabled","enabled","inherit","initial","none","unset"]},"-moz-user-modify":{inherited:true,supports:0,values:["inherit","initial","read-only","read-write","unset","write-only"]},"-moz-user-select":{inherited:false,supports:0,values:["-moz-all","-moz-none","-moz-text","all","auto","element","elements","inherit","initial","none","text","toggle","tri-state","unset"]},"vertical-align":{inherited:false,supports:3,values:["-moz-calc","-moz-middle-with-baseline","baseline","bottom","calc","inherit","initial","middle","sub","super","text-bottom","text-top","top","unset"]},"visibility":{inherited:true,supports:0,values:["collapse","hidden","inherit","initial","unset","visible"]},"white-space":{inherited:true,supports:0,values:["-moz-pre-space","inherit","initial","normal","nowrap","pre","pre-line","pre-wrap","unset"]},"width":{inherited:false,supports:3,values:["-moz-available","-moz-calc","-moz-fit-content","-moz-max-content","-moz-min-content","auto","calc","inherit","initial","unset"]},"-moz-window-dragging":{inherited:true,supports:0,values:["drag","inherit","initial","no-drag","unset"]},"word-break":{inherited:true,supports:0,values:["break-all","inherit","initial","keep-all","normal","unset"]},"word-spacing":{inherited:true,supports:3,values:["-moz-calc","calc","inherit","initial","normal","unset"]},"word-wrap":{inherited:true,supports:0,values:["break-word","inherit","initial","normal","unset"]},"hyphens":{inherited:true,supports:0,values:["auto","inherit","initial","manual","none","unset"]},"writing-mode":{inherited:true,supports:0,values:["horizontal-tb","inherit","initial","lr","lr-tb","rl","rl-tb","sideways-lr","sideways-rl","tb","tb-rl","unset","vertical-lr","vertical-rl"]},"z-index":{inherited:false,supports:1024,values:["auto","inherit","initial","unset"]},"-moz-box-align":{inherited:false,supports:0,values:["baseline","center","end","inherit","initial","start","stretch","unset"]},"-moz-box-direction":{inherited:false,supports:0,values:["inherit","initial","normal","reverse","unset"]},"-moz-box-flex":{inherited:false,supports:1024,values:["inherit","initial","unset"]},"-moz-box-orient":{inherited:false,supports:0,values:["block-axis","horizontal","inherit","initial","inline-axis","unset","vertical"]},"-moz-box-pack":{inherited:false,supports:0,values:["center","end","inherit","initial","justify","start","unset"]},"-moz-box-ordinal-group":{inherited:false,supports:1024,values:["inherit","initial","unset"]},"-moz-stack-sizing":{inherited:false,supports:0,values:["ignore","inherit","initial","stretch-to-fit","unset"]},"clip-path":{inherited:false,supports:8,values:["inherit","initial","unset"]},"clip-rule":{inherited:true,supports:0,values:["evenodd","inherit","initial","nonzero","unset"]},"color-interpolation":{inherited:true,supports:0,values:["auto","inherit","initial","linearrgb","srgb","unset"]},"color-interpolation-filters":{inherited:true,supports:0,values:["auto","inherit","initial","linearrgb","srgb","unset"]},"dominant-baseline":{inherited:false,supports:0,values:["alphabetic","auto","central","hanging","ideographic","inherit","initial","mathematical","middle","no-change","reset-size","text-after-edge","text-before-edge","unset","use-script"]},"fill":{inherited:true,supports:12,values:["inherit","initial","unset"]},"fill-opacity":{inherited:true,supports:1024,values:["inherit","initial","unset"]},"fill-rule":{inherited:true,supports:0,values:["evenodd","inherit","initial","nonzero","unset"]},"filter":{inherited:false,supports:8,values:["inherit","initial","unset"]},"flood-color":{inherited:false,supports:4,values:["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"flood-opacity":{inherited:false,supports:1024,values:["inherit","initial","unset"]},"image-rendering":{inherited:true,supports:0,values:["-moz-crisp-edges","auto","inherit","initial","optimizequality","optimizespeed","unset"]},"lighting-color":{inherited:false,supports:4,values:["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"marker-end":{inherited:true,supports:8,values:["inherit","initial","none","unset","url"]},"marker-mid":{inherited:true,supports:8,values:["inherit","initial","none","unset","url"]},"marker-start":{inherited:true,supports:8,values:["inherit","initial","none","unset","url"]},"mask":{inherited:false,supports:8,values:["inherit","initial","none","unset","url"]},"mask-type":{inherited:false,supports:0,values:["alpha","inherit","initial","luminance","unset"]},"shape-rendering":{inherited:true,supports:0,values:["auto","crispedges","geometricprecision","inherit","initial","optimizespeed","unset"]},"stop-color":{inherited:false,supports:4,values:["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"stop-opacity":{inherited:false,supports:1024,values:["inherit","initial","unset"]},"stroke":{inherited:true,supports:12,values:["inherit","initial","unset"]},"stroke-dasharray":{inherited:true,supports:1027,values:["inherit","initial","unset"]},"stroke-dashoffset":{inherited:true,supports:1027,values:["inherit","initial","unset"]},"stroke-linecap":{inherited:true,supports:0,values:["butt","inherit","initial","round","square","unset"]},"stroke-linejoin":{inherited:true,supports:0,values:["bevel","inherit","initial","miter","round","unset"]},"stroke-miterlimit":{inherited:true,supports:1024,values:["inherit","initial","unset"]},"stroke-opacity":{inherited:true,supports:1024,values:["inherit","initial","unset"]},"stroke-width":{inherited:true,supports:1027,values:["inherit","initial","unset"]},"text-anchor":{inherited:true,supports:0,values:["end","inherit","initial","middle","start","unset"]},"text-rendering":{inherited:true,supports:0,values:["auto","geometricprecision","inherit","initial","optimizelegibility","optimizespeed","unset"]},"vector-effect":{inherited:false,supports:0,values:["inherit","initial","non-scaling-stroke","none","unset"]},"will-change":{inherited:false,supports:0,values:["inherit","initial","unset"]},"-moz-outline-radius":{subproperties:["-moz-outline-radius-topleft","-moz-outline-radius-topright","-moz-outline-radius-bottomright","-moz-outline-radius-bottomleft"],inherited:false,supports:3,values:["inherit","initial","unset"]},"all":{subproperties:["-moz-appearance","-moz-outline-radius-topleft","-moz-outline-radius-topright","-moz-outline-radius-bottomright","-moz-outline-radius-bottomleft","-moz-tab-size","-x-system-font","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","background-attachment","background-clip","background-color","background-image","background-blend-mode","background-origin","background-position","background-repeat","background-size","-moz-binding","block-size","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start-color","border-block-start-style","border-block-start-width","border-bottom-color","-moz-border-bottom-colors","border-bottom-style","border-bottom-width","border-collapse","border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-left-color","-moz-border-left-colors","border-left-style","border-left-width","border-right-color","-moz-border-right-colors","border-right-style","border-right-width","border-spacing","border-top-color","-moz-border-top-colors","border-top-style","border-top-width","border-top-left-radius","border-top-right-radius","border-bottom-right-radius","border-bottom-left-radius","bottom","box-decoration-break","box-shadow","box-sizing","caption-side","clear","clip","color","-moz-column-count","-moz-column-fill","-moz-column-width","-moz-column-gap","-moz-column-rule-color","-moz-column-rule-style","-moz-column-rule-width","contain","content","-moz-control-character-visibility","counter-increment","counter-reset","cursor","display","empty-cells","align-content","align-items","align-self","flex-basis","flex-direction","flex-grow","flex-shrink","flex-wrap","order","justify-content","justify-items","justify-self","float","-moz-float-edge","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","-moz-osx-font-smoothing","font-stretch","font-style","font-synthesis","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-weight","-moz-force-broken-image-icon","grid-auto-flow","grid-auto-columns","grid-auto-rows","grid-template-areas","grid-template-columns","grid-template-rows","grid-column-start","grid-column-end","grid-row-start","grid-row-end","grid-column-gap","grid-row-gap","height","image-orientation","-moz-image-region","ime-mode","inline-size","left","letter-spacing","line-height","list-style-image","list-style-position","list-style-type","margin-block-end","margin-block-start","margin-bottom","margin-inline-end","margin-inline-start","margin-left","margin-right","margin-top","marker-offset","max-block-size","max-height","max-inline-size","max-width","-moz-min-font-size-ratio","min-height","min-block-size","min-inline-size","min-width","mix-blend-mode","isolation","object-fit","object-position","offset-block-end","offset-block-start","offset-inline-end","offset-inline-start","opacity","-moz-orient","outline-color","outline-style","outline-width","outline-offset","overflow-clip-box","overflow-x","overflow-y","padding-block-end","padding-block-start","padding-bottom","padding-inline-end","padding-inline-start","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","paint-order","pointer-events","position","quotes","resize","right","ruby-align","ruby-position","scroll-behavior","scroll-snap-coordinate","scroll-snap-destination","scroll-snap-points-x","scroll-snap-points-y","scroll-snap-type-x","scroll-snap-type-y","table-layout","text-align","-moz-text-align-last","text-combine-upright","text-decoration-color","text-decoration-line","text-decoration-style","text-indent","text-orientation","text-overflow","text-shadow","-moz-text-size-adjust","text-transform","transform","transform-box","transform-origin","perspective-origin","perspective","transform-style","backface-visibility","top","-moz-top-layer","touch-action","transition-delay","transition-duration","transition-property","transition-timing-function","-moz-user-focus","-moz-user-input","-moz-user-modify","-moz-user-select","vertical-align","visibility","white-space","width","-moz-window-dragging","-moz-window-shadow","word-break","word-spacing","word-wrap","hyphens","writing-mode","z-index","-moz-box-align","-moz-box-direction","-moz-box-flex","-moz-box-orient","-moz-box-pack","-moz-box-ordinal-group","-moz-stack-sizing","clip-path","clip-rule","color-interpolation","color-interpolation-filters","dominant-baseline","fill","fill-opacity","fill-rule","filter","flood-color","flood-opacity","image-rendering","lighting-color","marker-end","marker-mid","marker-start","mask","mask-type","shape-rendering","stop-color","stop-opacity","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-anchor","text-rendering","vector-effect","will-change"],inherited:false,supports:2015,values:["-moz-all","-moz-available","-moz-block-height","-moz-box","-moz-calc","-moz-center","-moz-crisp-edges","-moz-deck","-moz-element","-moz-fit-content","-moz-grid","-moz-grid-group","-moz-grid-line","-moz-groupbox","-moz-gtk-info-bar","-moz-hidden-unscrollable","-moz-image-rect","-moz-inline-box","-moz-inline-grid","-moz-inline-stack","-moz-left","-moz-linear-gradient","-moz-mac-disclosure-button-closed","-moz-mac-disclosure-button-open","-moz-mac-fullscreen-button","-moz-mac-help-button","-moz-mac-vibrancy-dark","-moz-mac-vibrancy-light","-moz-max-content","-moz-middle-with-baseline","-moz-min-content","-moz-none","-moz-popup","-moz-pre-space","-moz-radial-gradient","-moz-repeating-linear-gradient","-moz-repeating-radial-gradient","-moz-right","-moz-stack","-moz-text","-moz-use-text-color","-moz-win-borderless-glass","-moz-win-browsertabbar-toolbox","-moz-win-communications-toolbox","-moz-win-exclude-glass","-moz-win-glass","-moz-win-media-toolbox","-moz-window-button-box","-moz-window-button-box-maximized","-moz-window-button-close","-moz-window-button-maximize","-moz-window-button-minimize","-moz-window-button-restore","-moz-window-frame-bottom","-moz-window-frame-left","-moz-window-frame-right","-moz-window-titlebar","-moz-window-titlebar-maximized","absolute","active","aliceblue","all","all-petite-caps","all-small-caps","alpha","alphabetic","alternate","alternate-reverse","always","antiquewhite","aqua","aquamarine","auto","avoid","azure","backwards","balance","baseline","beige","bevel","bisque","black","blanchedalmond","block","block-axis","blue","blueviolet","border-box","both","bottom","bottom-outside","break-all","break-word","brown","burlywood","butt","button","button-arrow-down","button-arrow-next","button-arrow-previous","button-arrow-up","button-bevel","button-focus","cadetblue","calc","capitalize","caret","center","central","chartreuse","checkbox","checkbox-container","checkbox-label","checkmenuitem","chocolate","clone","collapse","color","color-burn","color-dodge","column","column-reverse","condensed","contain","content-box","contents","coral","cornflowerblue","cornsilk","cover","crimson","crispedges","cubic-bezier","currentColor","cyan","darkblue","darkcyan","darken","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dialog","difference","dimgray","dimgrey","disabled","dodgerblue","dotted","double","drag","dualbutton","ease","ease-in","ease-in-out","ease-out","element","elements","enabled","end","evenodd","exclusion","expanded","extra-condensed","extra-expanded","fill","fill-box","firebrick","fixed","flat","flex","floralwhite","forestgreen","forwards","fuchsia","full-width","gainsboro","geometricprecision","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","grid","groove","groupbox","hanging","hard-light","hidden","hide","honeydew","horizontal","horizontal-tb","hotpink","hsl","hsla","hue","ideographic","ignore","inactive","indianred","indigo","infinite","inherit","initial","inline","inline-axis","inline-block","inline-end","inline-flex","inline-grid","inline-start","inline-table","inset","inside","isolate","italic","ivory","justify","keep-all","khaki","large","larger","lavender","lavenderblush","lawngreen","layout","left","lemonchiffon","lightblue","lightcoral","lightcyan","lighten","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linear","linear-gradient","linearrgb","linen","list-item","listbox","listitem","local","lowercase","lr","lr-tb","luminance","luminosity","magenta","mandatory","manual","margin-box","maroon","mathematical","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","menuarrow","menubar","menucheckbox","menuimage","menuitem","menuitemtext","menulist","menulist-button","menulist-text","menulist-textfield","menupopup","menuradio","menuseparator","meterbar","meterchunk","middle","midnightblue","mintcream","mistyrose","miter","mixed","moccasin","multiply","navajowhite","navy","no-change","no-drag","no-repeat","non-scaling-stroke","none","nonzero","normal","nowrap","number-input","oblique","oldlace","olive","olivedrab","optimizelegibility","optimizequality","optimizespeed","orange","orangered","orchid","outset","outside","over","overlay","padding-box","paint","painted","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","paused","peachpuff","peru","petite-caps","pink","plum","powderblue","pre","pre-line","pre-wrap","preserve-3d","progressbar","progressbar-vertical","progresschunk","progresschunk-vertical","proximity","purple","radial-gradient","radio","radio-container","radio-label","radiomenuitem","range","range-thumb","read-only","read-write","rebeccapurple","red","relative","repeat","repeat-x","repeat-y","repeating-linear-gradient","repeating-radial-gradient","reset-size","resizer","resizerpanel","reverse","rgb","rgba","ridge","right","rl","rl-tb","rosybrown","round","row","row-reverse","royalblue","ruby","ruby-base","ruby-base-container","ruby-text","ruby-text-container","running","saddlebrown","salmon","sandybrown","saturation","scale-down","scale-horizontal","scale-vertical","scalethumb-horizontal","scalethumb-vertical","scalethumbend","scalethumbstart","scalethumbtick","screen","scroll","scrollbar","scrollbar-small","scrollbarbutton-down","scrollbarbutton-left","scrollbarbutton-right","scrollbarbutton-up","scrollbarthumb-horizontal","scrollbarthumb-vertical","scrollbartrack-horizontal","scrollbartrack-vertical","seagreen","searchfield","seashell","select-after","select-all","select-before","select-menu","select-same","semi-condensed","semi-expanded","separate","separator","show","sideways","sideways-lr","sideways-right","sideways-rl","sienna","silver","skyblue","slateblue","slategray","slategrey","slice","small","small-caps","smaller","smooth","snow","soft-light","solid","space-around","space-between","spinner","spinner-downbutton","spinner-textfield","spinner-upbutton","splitter","springgreen","square","srgb","start","static","statusbar","statusbarpanel","steelblue","step-end","step-start","steps","sticky","stretch","stretch-to-fit","strict","stroke","style","sub","super","tab","tab-scroll-arrow-back","tab-scroll-arrow-forward","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tabpanel","tabpanels","tan","tb","tb-rl","teal","text","text-after-edge","text-before-edge","text-bottom","text-top","textfield","textfield-multiline","thick","thin","thistle","titling-caps","toggle","tomato","toolbar","toolbarbutton","toolbarbutton-dropdown","toolbargripper","toolbox","tooltip","top","top-outside","transparent","treeheader","treeheadercell","treeheadersortarrow","treeitem","treeline","treetwisty","treetwistyopen","treeview","tri-state","turquoise","ultra-condensed","ultra-expanded","under","unicase","unset","uppercase","upright","url","use-script","vertical","vertical-lr","vertical-rl","view-box","violet","visible","visiblefill","visiblepainted","visiblestroke","wavy","wheat","white","whitesmoke","window","wrap","wrap-reverse","write-only","x-large","x-small","xx-large","xx-small","yellow","yellowgreen"]},"animation":{subproperties:["animation-duration","animation-timing-function","animation-delay","animation-direction","animation-fill-mode","animation-iteration-count","animation-play-state","animation-name"],inherited:false,supports:1344,values:["alternate","alternate-reverse","backwards","both","cubic-bezier","ease","ease-in","ease-in-out","ease-out","forwards","infinite","inherit","initial","linear","none","normal","paused","reverse","running","step-end","step-start","steps","unset"]},"background":{subproperties:["background-color","background-image","background-repeat","background-attachment","background-position","background-clip","background-origin","background-size"],inherited:false,supports:655,values:["-moz-element","-moz-image-rect","-moz-linear-gradient","-moz-radial-gradient","-moz-repeating-linear-gradient","-moz-repeating-radial-gradient","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","border-box","brown","burlywood","cadetblue","chartreuse","chocolate","content-box","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","fixed","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linear-gradient","linen","local","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","no-repeat","none","oldlace","olive","olivedrab","orange","orangered","orchid","padding-box","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","radial-gradient","rebeccapurple","red","repeat","repeat-x","repeat-y","repeating-linear-gradient","repeating-radial-gradient","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","scroll","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","url","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border":{subproperties:["border-top-width","border-right-width","border-bottom-width","border-left-width","border-top-style","border-right-style","border-bottom-style","border-left-style","border-top-color","border-right-color","border-bottom-color","border-left-color","-moz-border-top-colors","-moz-border-right-colors","-moz-border-bottom-colors","-moz-border-left-colors","border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat"],inherited:false,supports:5,values:["-moz-calc","-moz-element","-moz-image-rect","-moz-linear-gradient","-moz-radial-gradient","-moz-repeating-linear-gradient","-moz-repeating-radial-gradient","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","calc","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","groove","hidden","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","inset","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linear-gradient","linen","magenta","maroon","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","none","oldlace","olive","olivedrab","orange","orangered","orchid","outset","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","radial-gradient","rebeccapurple","red","repeating-linear-gradient","repeating-radial-gradient","rgb","rgba","ridge","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thick","thin","thistle","tomato","transparent","turquoise","unset","url","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-block-end":{subproperties:["border-block-end-width","border-block-end-style","border-block-end-color"],inherited:false,supports:5,values:["-moz-calc","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","calc","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","groove","hidden","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","inset","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","none","oldlace","olive","olivedrab","orange","orangered","orchid","outset","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","ridge","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thick","thin","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-block-start":{subproperties:["border-block-start-width","border-block-start-style","border-block-start-color"],inherited:false,supports:5,values:["-moz-calc","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","calc","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","groove","hidden","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","inset","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","none","oldlace","olive","olivedrab","orange","orangered","orchid","outset","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","ridge","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thick","thin","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-bottom":{subproperties:["border-bottom-width","border-bottom-style","border-bottom-color"],inherited:false,supports:5,values:["-moz-calc","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","calc","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","groove","hidden","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","inset","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","none","oldlace","olive","olivedrab","orange","orangered","orchid","outset","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","ridge","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thick","thin","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-color":{subproperties:["border-top-color","border-right-color","border-bottom-color","border-left-color"],inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-image":{subproperties:["border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat"],inherited:false,supports:1675,values:["-moz-element","-moz-image-rect","-moz-linear-gradient","-moz-radial-gradient","-moz-repeating-linear-gradient","-moz-repeating-radial-gradient","inherit","initial","linear-gradient","none","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","unset","url"]},"border-inline-end":{subproperties:["border-inline-end-width","border-inline-end-style","border-inline-end-color"],inherited:false,supports:5,values:["-moz-calc","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","calc","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","groove","hidden","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","inset","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","none","oldlace","olive","olivedrab","orange","orangered","orchid","outset","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","ridge","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thick","thin","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-inline-start":{subproperties:["border-inline-start-width","border-inline-start-style","border-inline-start-color"],inherited:false,supports:5,values:["-moz-calc","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","calc","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","groove","hidden","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","inset","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","none","oldlace","olive","olivedrab","orange","orangered","orchid","outset","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","ridge","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thick","thin","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-left":{subproperties:["border-left-width","border-left-style","border-left-color"],inherited:false,supports:5,values:["-moz-calc","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","calc","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","groove","hidden","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","inset","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","none","oldlace","olive","olivedrab","orange","orangered","orchid","outset","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","ridge","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thick","thin","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-right":{subproperties:["border-right-width","border-right-style","border-right-color"],inherited:false,supports:5,values:["-moz-calc","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","calc","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","groove","hidden","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","inset","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","none","oldlace","olive","olivedrab","orange","orangered","orchid","outset","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","ridge","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thick","thin","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-style":{subproperties:["border-top-style","border-right-style","border-bottom-style","border-left-style"],inherited:false,supports:0,values:["dashed","dotted","double","groove","hidden","inherit","initial","inset","none","outset","ridge","solid","unset"]},"border-top":{subproperties:["border-top-width","border-top-style","border-top-color"],inherited:false,supports:5,values:["-moz-calc","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","calc","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","groove","hidden","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","inset","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","none","oldlace","olive","olivedrab","orange","orangered","orchid","outset","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","ridge","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thick","thin","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"border-width":{subproperties:["border-top-width","border-right-width","border-bottom-width","border-left-width"],inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","medium","thick","thin","unset"]},"border-radius":{subproperties:["border-top-left-radius","border-top-right-radius","border-bottom-right-radius","border-bottom-left-radius"],inherited:false,supports:3,values:["inherit","initial","unset"]},"-moz-columns":{subproperties:["-moz-column-count","-moz-column-width"],inherited:false,supports:1025,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"-moz-column-rule":{subproperties:["-moz-column-rule-width","-moz-column-rule-style","-moz-column-rule-color"],inherited:false,supports:5,values:["-moz-calc","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","calc","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","groove","hidden","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","inset","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","none","oldlace","olive","olivedrab","orange","orangered","orchid","outset","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","ridge","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thick","thin","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"flex":{subproperties:["flex-grow","flex-shrink","flex-basis"],inherited:false,supports:1027,values:["-moz-available","-moz-calc","-moz-fit-content","-moz-max-content","-moz-min-content","auto","calc","inherit","initial","unset"]},"flex-flow":{subproperties:["flex-direction","flex-wrap"],inherited:false,supports:0,values:["column","column-reverse","inherit","initial","nowrap","row","row-reverse","unset","wrap","wrap-reverse"]},"font":{subproperties:["font-family","font-style","font-weight","font-size","line-height","font-size-adjust","font-stretch","-x-system-font","font-feature-settings","font-language-override","font-kerning","font-synthesis","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position"],inherited:true,supports:1027,values:["-moz-block-height","-moz-calc","all-petite-caps","all-small-caps","auto","calc","condensed","expanded","extra-condensed","extra-expanded","inherit","initial","italic","large","larger","medium","none","normal","oblique","petite-caps","semi-condensed","semi-expanded","small","small-caps","smaller","sub","super","titling-caps","ultra-condensed","ultra-expanded","unicase","unset","x-large","x-small","xx-large","xx-small"]},"font-variant":{subproperties:["font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position"],inherited:true,supports:0,values:["all-petite-caps","all-small-caps","inherit","initial","normal","petite-caps","small-caps","sub","super","titling-caps","unicase","unset"]},"grid-template":{subproperties:["grid-template-areas","grid-template-columns","grid-template-rows"],inherited:false,supports:3,values:["inherit","initial","unset"]},"grid":{subproperties:["grid-template-areas","grid-template-columns","grid-template-rows","grid-auto-flow","grid-auto-columns","grid-auto-rows","grid-column-gap","grid-row-gap"],inherited:false,supports:3,values:["-moz-calc","calc","inherit","initial","unset"]},"grid-column":{subproperties:["grid-column-start","grid-column-end"],inherited:false,supports:1024,values:["inherit","initial","unset"]},"grid-row":{subproperties:["grid-row-start","grid-row-end"],inherited:false,supports:1024,values:["inherit","initial","unset"]},"grid-area":{subproperties:["grid-row-start","grid-column-start","grid-row-end","grid-column-end"],inherited:false,supports:1024,values:["inherit","initial","unset"]},"grid-gap":{subproperties:["grid-column-gap","grid-row-gap"],inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","unset"]},"list-style":{subproperties:["list-style-type","list-style-image","list-style-position"],inherited:true,supports:8,values:["inherit","initial","inside","none","outside","unset","url"]},"margin":{subproperties:["margin-top","margin-right","margin-bottom","margin-left"],inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"outline":{subproperties:["outline-width","outline-style","outline-color"],inherited:false,supports:5,values:["-moz-calc","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","auto","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","calc","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","groove","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","inset","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","none","oldlace","olive","olivedrab","orange","orangered","orchid","outset","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","ridge","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thick","thin","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"overflow":{subproperties:["overflow-x","overflow-y"],inherited:false,supports:0,values:["-moz-hidden-unscrollable","auto","hidden","inherit","initial","scroll","unset","visible"]},"padding":{subproperties:["padding-top","padding-right","padding-bottom","padding-left"],inherited:false,supports:3,values:["-moz-calc","calc","inherit","initial","unset"]},"scroll-snap-type":{subproperties:["scroll-snap-type-x","scroll-snap-type-y"],inherited:false,supports:0,values:["inherit","initial","mandatory","none","proximity","unset"]},"text-decoration":{subproperties:["text-decoration-color","text-decoration-line","text-decoration-style"],inherited:false,supports:4,values:["-moz-none","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wavy","wheat","white","whitesmoke","yellow","yellowgreen"]},"transition":{subproperties:["transition-property","transition-duration","transition-timing-function","transition-delay"],inherited:false,supports:320,values:["all","cubic-bezier","ease","ease-in","ease-in-out","ease-out","inherit","initial","linear","none","step-end","step-start","steps","unset"]},"marker":{subproperties:["marker-start","marker-mid","marker-end"],inherited:true,supports:8,values:["inherit","initial","none","unset","url"]},"-moz-transform":{alias:true,subproperties:["transform"],inherited:false,supports:0,values:["inherit","initial","unset"]},"-moz-transform-origin":{alias:true,inherited:false,supports:3,values:["inherit","initial","unset"]},"-moz-perspective-origin":{alias:true,inherited:false,supports:3,values:["inherit","initial","unset"]},"-moz-perspective":{alias:true,inherited:false,supports:1,values:["inherit","initial","none","unset"]},"-moz-transform-style":{alias:true,inherited:false,supports:0,values:["flat","inherit","initial","preserve-3d","unset"]},"-moz-backface-visibility":{alias:true,inherited:false,supports:0,values:["hidden","inherit","initial","unset","visible"]},"-moz-border-image":{alias:true,subproperties:["border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat"],inherited:false,supports:1675,values:["-moz-element","-moz-image-rect","-moz-linear-gradient","-moz-radial-gradient","-moz-repeating-linear-gradient","-moz-repeating-radial-gradient","inherit","initial","linear-gradient","none","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","unset","url"]},"-moz-transition":{alias:true,subproperties:["transition-property","transition-duration","transition-timing-function","transition-delay"],inherited:false,supports:320,values:["all","cubic-bezier","ease","ease-in","ease-in-out","ease-out","inherit","initial","linear","none","step-end","step-start","steps","unset"]},"-moz-transition-delay":{alias:true,inherited:false,supports:64,values:["inherit","initial","unset"]},"-moz-transition-duration":{alias:true,inherited:false,supports:64,values:["inherit","initial","unset"]},"-moz-transition-property":{alias:true,inherited:false,supports:0,values:["all","inherit","initial","none","unset"]},"-moz-transition-timing-function":{alias:true,inherited:false,supports:256,values:["cubic-bezier","ease","ease-in","ease-in-out","ease-out","inherit","initial","linear","step-end","step-start","steps","unset"]},"-moz-animation":{alias:true,subproperties:["animation-duration","animation-timing-function","animation-delay","animation-direction","animation-fill-mode","animation-iteration-count","animation-play-state","animation-name"],inherited:false,supports:1344,values:["alternate","alternate-reverse","backwards","both","cubic-bezier","ease","ease-in","ease-in-out","ease-out","forwards","infinite","inherit","initial","linear","none","normal","paused","reverse","running","step-end","step-start","steps","unset"]},"-moz-animation-delay":{alias:true,inherited:false,supports:64,values:["inherit","initial","unset"]},"-moz-animation-direction":{alias:true,inherited:false,supports:0,values:["alternate","alternate-reverse","inherit","initial","normal","reverse","unset"]},"-moz-animation-duration":{alias:true,inherited:false,supports:64,values:["inherit","initial","unset"]},"-moz-animation-fill-mode":{alias:true,inherited:false,supports:0,values:["backwards","both","forwards","inherit","initial","none","unset"]},"-moz-animation-iteration-count":{alias:true,inherited:false,supports:1024,values:["infinite","inherit","initial","unset"]},"-moz-animation-name":{alias:true,inherited:false,supports:0,values:["inherit","initial","none","unset"]},"-moz-animation-play-state":{alias:true,inherited:false,supports:0,values:["inherit","initial","paused","running","unset"]},"-moz-animation-timing-function":{alias:true,inherited:false,supports:256,values:["cubic-bezier","ease","ease-in","ease-in-out","ease-out","inherit","initial","linear","step-end","step-start","steps","unset"]},"-moz-box-sizing":{alias:true,inherited:false,supports:0,values:["border-box","content-box","inherit","initial","padding-box","unset"]},"-moz-font-feature-settings":{alias:true,inherited:true,supports:0,values:["inherit","initial","unset"]},"-moz-font-language-override":{alias:true,inherited:true,supports:0,values:["inherit","initial","normal","unset"]},"-moz-padding-end":{alias:true,inherited:false,supports:3,values:["-moz-calc","calc","inherit","initial","unset"]},"-moz-padding-start":{alias:true,inherited:false,supports:3,values:["-moz-calc","calc","inherit","initial","unset"]},"-moz-margin-end":{alias:true,inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"-moz-margin-start":{alias:true,inherited:false,supports:3,values:["-moz-calc","auto","calc","inherit","initial","unset"]},"-moz-border-end":{alias:true,subproperties:["border-inline-end-width","border-inline-end-style","border-inline-end-color"],inherited:false,supports:5,values:["-moz-calc","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","calc","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","groove","hidden","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","inset","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","none","oldlace","olive","olivedrab","orange","orangered","orchid","outset","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","ridge","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thick","thin","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"-moz-border-end-color":{alias:true,inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"-moz-border-end-style":{alias:true,inherited:false,supports:0,values:["dashed","dotted","double","groove","hidden","inherit","initial","inset","none","outset","ridge","solid","unset"]},"-moz-border-end-width":{alias:true,inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","medium","thick","thin","unset"]},"-moz-border-start":{alias:true,subproperties:["border-inline-start-width","border-inline-start-style","border-inline-start-color"],inherited:false,supports:5,values:["-moz-calc","-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","calc","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","dashed","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","dotted","double","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","groove","hidden","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","inset","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","medium","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","none","oldlace","olive","olivedrab","orange","orangered","orchid","outset","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","ridge","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","solid","springgreen","steelblue","tan","teal","thick","thin","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"-moz-border-start-color":{alias:true,inherited:false,supports:4,values:["-moz-use-text-color","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","currentColor","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","hsl","hsla","indianred","indigo","inherit","initial","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rgb","rgba","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","transparent","turquoise","unset","violet","wheat","white","whitesmoke","yellow","yellowgreen"]},"-moz-border-start-style":{alias:true,inherited:false,supports:0,values:["dashed","dotted","double","groove","hidden","inherit","initial","inset","none","outset","ridge","solid","unset"]},"-moz-border-start-width":{alias:true,inherited:false,supports:1,values:["-moz-calc","calc","inherit","initial","medium","thick","thin","unset"]},"-moz-hyphens":{alias:true,inherited:true,supports:0,values:["auto","inherit","initial","manual","none","unset"]},"-webkit-animation":{alias:true,subproperties:["animation-duration","animation-timing-function","animation-delay","animation-direction","animation-fill-mode","animation-iteration-count","animation-play-state","animation-name"],inherited:false,supports:1344,values:["alternate","alternate-reverse","backwards","both","cubic-bezier","ease","ease-in","ease-in-out","ease-out","forwards","infinite","inherit","initial","linear","none","normal","paused","reverse","running","step-end","step-start","steps","unset"]},"-webkit-animation-delay":{alias:true,inherited:false,supports:64,values:["inherit","initial","unset"]},"-webkit-animation-direction":{alias:true,inherited:false,supports:0,values:["alternate","alternate-reverse","inherit","initial","normal","reverse","unset"]},"-webkit-animation-duration":{alias:true,inherited:false,supports:64,values:["inherit","initial","unset"]},"-webkit-animation-fill-mode":{alias:true,inherited:false,supports:0,values:["backwards","both","forwards","inherit","initial","none","unset"]},"-webkit-animation-iteration-count":{alias:true,inherited:false,supports:1024,values:["infinite","inherit","initial","unset"]},"-webkit-animation-name":{alias:true,inherited:false,supports:0,values:["inherit","initial","none","unset"]},"-webkit-animation-play-state":{alias:true,inherited:false,supports:0,values:["inherit","initial","paused","running","unset"]},"-webkit-animation-timing-function":{alias:true,inherited:false,supports:256,values:["cubic-bezier","ease","ease-in","ease-in-out","ease-out","inherit","initial","linear","step-end","step-start","steps","unset"]},"-webkit-text-size-adjust":{alias:true,inherited:true,supports:0,values:["auto","inherit","initial","none","unset"]},"-webkit-transform":{alias:true,inherited:false,supports:0,values:["inherit","initial","unset"]},"-webkit-transform-origin":{alias:true,inherited:false,supports:3,values:["inherit","initial","unset"]},"-webkit-transform-style":{alias:true,inherited:false,supports:0,values:["flat","inherit","initial","preserve-3d","unset"]},"-webkit-backface-visibility":{alias:true,inherited:false,supports:0,values:["hidden","inherit","initial","unset","visible"]},"-webkit-perspective":{alias:true,inherited:false,supports:1,values:["inherit","initial","none","unset"]},"-webkit-perspective-origin":{alias:true,inherited:false,supports:3,values:["inherit","initial","unset"]},"-webkit-transition":{alias:true,subproperties:["transition-property","transition-duration","transition-timing-function","transition-delay"],inherited:false,supports:320,values:["all","cubic-bezier","ease","ease-in","ease-in-out","ease-out","inherit","initial","linear","none","step-end","step-start","steps","unset"]},"-webkit-transition-delay":{alias:true,inherited:false,supports:64,values:["inherit","initial","unset"]},"-webkit-transition-duration":{alias:true,inherited:false,supports:64,values:["inherit","initial","unset"]},"-webkit-transition-property":{alias:true,inherited:false,supports:0,values:["all","inherit","initial","none","unset"]},"-webkit-transition-timing-function":{alias:true,inherited:false,supports:256,values:["cubic-bezier","ease","ease-in","ease-in-out","ease-out","inherit","initial","linear","step-end","step-start","steps","unset"]},"-webkit-border-radius":{alias:true,subproperties:["border-top-left-radius","border-top-right-radius","border-bottom-right-radius","border-bottom-left-radius"],inherited:false,supports:3,values:["inherit","initial","unset"]},"-webkit-border-top-left-radius":{alias:true,inherited:false,supports:3,values:["inherit","initial","unset"]},"-webkit-border-top-right-radius":{alias:true,inherited:false,supports:3,values:["inherit","initial","unset"]},"-webkit-border-bottom-left-radius":{alias:true,inherited:false,supports:3,values:["inherit","initial","unset"]},"-webkit-border-bottom-right-radius":{alias:true,inherited:false,supports:3,values:["inherit","initial","unset"]},"-webkit-appearance":{alias:true,inherited:false,supports:0,values:["-moz-gtk-info-bar","-moz-mac-disclosure-button-closed","-moz-mac-disclosure-button-open","-moz-mac-fullscreen-button","-moz-mac-help-button","-moz-mac-vibrancy-dark","-moz-mac-vibrancy-light","-moz-win-borderless-glass","-moz-win-browsertabbar-toolbox","-moz-win-communications-toolbox","-moz-win-exclude-glass","-moz-win-glass","-moz-win-media-toolbox","-moz-window-button-box","-moz-window-button-box-maximized","-moz-window-button-close","-moz-window-button-maximize","-moz-window-button-minimize","-moz-window-button-restore","-moz-window-frame-bottom","-moz-window-frame-left","-moz-window-frame-right","-moz-window-titlebar","-moz-window-titlebar-maximized","button","button-arrow-down","button-arrow-next","button-arrow-previous","button-arrow-up","button-bevel","button-focus","caret","checkbox","checkbox-container","checkbox-label","checkmenuitem","dialog","dualbutton","groupbox","inherit","initial","listbox","listitem","menuarrow","menubar","menucheckbox","menuimage","menuitem","menuitemtext","menulist","menulist-button","menulist-text","menulist-textfield","menupopup","menuradio","menuseparator","meterbar","meterchunk","none","number-input","progressbar","progressbar-vertical","progresschunk","progresschunk-vertical","radio","radio-container","radio-label","radiomenuitem","range","range-thumb","resizer","resizerpanel","scale-horizontal","scale-vertical","scalethumb-horizontal","scalethumb-vertical","scalethumbend","scalethumbstart","scalethumbtick","scrollbar","scrollbar-small","scrollbarbutton-down","scrollbarbutton-left","scrollbarbutton-right","scrollbarbutton-up","scrollbarthumb-horizontal","scrollbarthumb-vertical","scrollbartrack-horizontal","scrollbartrack-vertical","searchfield","separator","spinner","spinner-downbutton","spinner-textfield","spinner-upbutton","splitter","statusbar","statusbarpanel","tab","tab-scroll-arrow-back","tab-scroll-arrow-forward","tabpanel","tabpanels","textfield","textfield-multiline","toolbar","toolbarbutton","toolbarbutton-dropdown","toolbargripper","toolbox","tooltip","treeheader","treeheadercell","treeheadersortarrow","treeitem","treeline","treetwisty","treetwistyopen","treeview","unset","window"]},"-webkit-background-clip":{alias:true,inherited:false,supports:0,values:["border-box","content-box","inherit","initial","padding-box","unset"]},"-webkit-background-origin":{alias:true,inherited:false,supports:0,values:["border-box","content-box","inherit","initial","padding-box","unset"]},"-webkit-background-size":{alias:true,inherited:false,supports:3,values:["inherit","initial","unset"]},"-webkit-border-image":{alias:true,subproperties:["border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat"],inherited:false,supports:1675,values:["-moz-element","-moz-image-rect","-moz-linear-gradient","-moz-radial-gradient","-moz-repeating-linear-gradient","-moz-repeating-radial-gradient","inherit","initial","linear-gradient","none","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","unset","url"]},"-webkit-border-image-outset":{alias:true,inherited:false,supports:1025,values:["inherit","initial","unset"]},"-webkit-border-image-repeat":{alias:true,inherited:false,supports:0,values:["inherit","initial","unset"]},"-webkit-border-image-slice":{alias:true,inherited:false,supports:1026,values:["inherit","initial","unset"]},"-webkit-border-image-source":{alias:true,inherited:false,supports:648,values:["-moz-element","-moz-image-rect","-moz-linear-gradient","-moz-radial-gradient","-moz-repeating-linear-gradient","-moz-repeating-radial-gradient","inherit","initial","linear-gradient","none","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","unset","url"]},"-webkit-border-image-width":{alias:true,inherited:false,supports:1027,values:["inherit","initial","unset"]},"-webkit-box-shadow":{alias:true,inherited:false,supports:5,values:["inherit","initial","unset"]},"-webkit-box-sizing":{alias:true,inherited:false,supports:0,values:["border-box","content-box","inherit","initial","padding-box","unset"]},"-webkit-box-flex":{alias:true,inherited:false,supports:1024,values:["inherit","initial","unset"]},"-webkit-box-ordinal-group":{alias:true,inherited:false,supports:1024,values:["inherit","initial","unset"]},"-webkit-box-align":{alias:true,inherited:false,supports:0,values:["inherit","initial","unset"]},"-webkit-box-pack":{alias:true,inherited:false,supports:0,values:["inherit","initial","unset"]},"-webkit-user-select":{alias:true,inherited:false,supports:0,values:["-moz-all","-moz-none","-moz-text","all","auto","element","elements","inherit","initial","none","text","toggle","tri-state","unset"]}};module.exports={cssProperties}; + +/***/ }, +/* 66 */ +/***/ function(module, exports) { + + /* + * A sham for https://dxr.mozilla.org/mozilla-central/source/toolkit/modules/Promise.jsm + */ + + /** + * Promise.jsm is mostly the Promise web API with a `defer` method. Just drop this in here, + * and use the native web API (although building with webpack/babel, it may replace this + * with it's own version if we want to target environments that do not have `Promise`. + */ + + var p = typeof window != "undefined" ? window.Promise : Promise; + p.defer = function defer() { + var resolve, reject; + var promise = new Promise(function () { + resolve = arguments[0]; + reject = arguments[1]; + }); + return { + resolve: resolve, + reject: reject, + promise: promise + }; + }; + + module.exports = p; + +/***/ }, +/* 67 */ +/***/ function(module, exports, __webpack_require__) { + + /* eslint-env browser */ + /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + // TODO: Get rid of this code once the marionette server loads transport.js as + // an SDK module (see bug 1000814) + + "use strict"; + + var DevToolsUtils = __webpack_require__(68); + var dumpn = DevToolsUtils.dumpn; + var dumpv = DevToolsUtils.dumpv; + + var StreamUtils = __webpack_require__(74); + + var _require = __webpack_require__(75); + + var Packet = _require.Packet; + var JSONPacket = _require.JSONPacket; + var BulkPacket = _require.BulkPacket; + + var promise = __webpack_require__(66); + var EventEmitter = __webpack_require__(60); + var utf8 = __webpack_require__(78); + + var PACKET_HEADER_MAX = 200; + + /** + * An adapter that handles data transfers between the debugger client and + * server. It can work with both nsIPipe and nsIServerSocket transports so + * long as the properly created input and output streams are specified. + * (However, for intra-process connections, LocalDebuggerTransport, below, + * is more efficient than using an nsIPipe pair with DebuggerTransport.) + * + * @param input nsIAsyncInputStream + * The input stream. + * @param output nsIAsyncOutputStream + * The output stream. + * + * Given a DebuggerTransport instance dt: + * 1) Set dt.hooks to a packet handler object (described below). + * 2) Call dt.ready() to begin watching for input packets. + * 3) Call dt.send() / dt.startBulkSend() to send packets. + * 4) Call dt.close() to close the connection, and disengage from the event + * loop. + * + * A packet handler is an object with the following methods: + * + * - onPacket(packet) - called when we have received a complete packet. + * |packet| is the parsed form of the packet --- a JavaScript value, not + * a JSON-syntax string. + * + * - onBulkPacket(packet) - called when we have switched to bulk packet + * receiving mode. |packet| is an object containing: + * * actor: Name of actor that will receive the packet + * * type: Name of actor's method that should be called on receipt + * * length: Size of the data to be read + * * stream: This input stream should only be used directly if you can ensure + * that you will read exactly |length| bytes and will not close the + * stream when reading is complete + * * done: If you use the stream directly (instead of |copyTo| below), you + * must signal completion by resolving / rejecting this deferred. + * If it's rejected, the transport will be closed. If an Error is + * supplied as a rejection value, it will be logged via |dumpn|. + * If you do use |copyTo|, resolving is taken care of for you when + * copying completes. + * * copyTo: A helper function for getting your data out of the stream that + * meets the stream handling requirements above, and has the + * following signature: + * @param output nsIAsyncOutputStream + * The stream to copy to. + * @return Promise + * The promise is resolved when copying completes or rejected if any + * (unexpected) errors occur. + * This object also emits "progress" events for each chunk that is + * copied. See stream-utils.js. + * + * - onClosed(reason) - called when the connection is closed. |reason| is + * an optional nsresult or object, typically passed when the transport is + * closed due to some error in a underlying stream. + * + * See ./packets.js and the Remote Debugging Protocol specification for more + * details on the format of these packets. + */ + function DebuggerTransport(socket) { + EventEmitter.decorate(this); + + this._socket = socket; + + // The current incoming (possibly partial) header, which will determine which + // type of Packet |_incoming| below will become. + this._incomingHeader = ""; + // The current incoming Packet object + this._incoming = null; + // A queue of outgoing Packet objects + this._outgoing = []; + + this.hooks = null; + this.active = false; + + this._incomingEnabled = true; + this._outgoingEnabled = true; + + this.close = this.close.bind(this); + } + + DebuggerTransport.prototype = { + /** + * Transmit an object as a JSON packet. + * + * This method returns immediately, without waiting for the entire + * packet to be transmitted, registering event handlers as needed to + * transmit the entire packet. Packets are transmitted in the order + * they are passed to this method. + */ + send: function (object) { + this.emit("send", object); + + var packet = new JSONPacket(this); + packet.object = object; + this._outgoing.push(packet); + this._flushOutgoing(); + }, + + /** + * Transmit streaming data via a bulk packet. + * + * This method initiates the bulk send process by queuing up the header data. + * The caller receives eventual access to a stream for writing. + * + * N.B.: Do *not* attempt to close the stream handed to you, as it will + * continue to be used by this transport afterwards. Most users should + * instead use the provided |copyFrom| function instead. + * + * @param header Object + * This is modeled after the format of JSON packets above, but does not + * actually contain the data, but is instead just a routing header: + * * actor: Name of actor that will receive the packet + * * type: Name of actor's method that should be called on receipt + * * length: Size of the data to be sent + * @return Promise + * The promise will be resolved when you are allowed to write to the + * stream with an object containing: + * * stream: This output stream should only be used directly if + * you can ensure that you will write exactly |length| + * bytes and will not close the stream when writing is + * complete + * * done: If you use the stream directly (instead of |copyFrom| + * below), you must signal completion by resolving / + * rejecting this deferred. If it's rejected, the + * transport will be closed. If an Error is supplied as + * a rejection value, it will be logged via |dumpn|. If + * you do use |copyFrom|, resolving is taken care of for + * you when copying completes. + * * copyFrom: A helper function for getting your data onto the + * stream that meets the stream handling requirements + * above, and has the following signature: + * @param input nsIAsyncInputStream + * The stream to copy from. + * @return Promise + * The promise is resolved when copying completes or + * rejected if any (unexpected) errors occur. + * This object also emits "progress" events for each chunk + * that is copied. See stream-utils.js. + */ + startBulkSend: function (header) { + this.emit("startBulkSend", header); + + var packet = new BulkPacket(this); + packet.header = header; + this._outgoing.push(packet); + this._flushOutgoing(); + return packet.streamReadyForWriting; + }, + + /** + * Close the transport. + * @param reason nsresult / object (optional) + * The status code or error message that corresponds to the reason for + * closing the transport (likely because a stream closed or failed). + */ + close: function (reason) { + this.emit("onClosed", reason); + + this.active = false; + this._socket.close(); + this._destroyIncoming(); + this._destroyAllOutgoing(); + if (this.hooks) { + this.hooks.onClosed(reason); + this.hooks = null; + } + if (reason) { + dumpn("Transport closed: " + DevToolsUtils.safeErrorString(reason)); + } else { + dumpn("Transport closed."); + } + }, + + /** + * The currently outgoing packet (at the top of the queue). + */ + get _currentOutgoing() { + return this._outgoing[0]; + }, + + /** + * Flush data to the outgoing stream. Waits until the output stream notifies + * us that it is ready to be written to (via onOutputStreamReady). + */ + _flushOutgoing: function () { + if (!this._outgoingEnabled || this._outgoing.length === 0) { + return; + } + + // If the top of the packet queue has nothing more to send, remove it. + if (this._currentOutgoing.done) { + this._finishCurrentOutgoing(); + } + + if (this._outgoing.length > 0) { + setTimeout(this.onOutputStreamReady.bind(this), 0); + } + }, + + /** + * Pause this transport's attempts to write to the output stream. This is + * used when we've temporarily handed off our output stream for writing bulk + * data. + */ + pauseOutgoing: function () { + this._outgoingEnabled = false; + }, + + /** + * Resume this transport's attempts to write to the output stream. + */ + resumeOutgoing: function () { + this._outgoingEnabled = true; + this._flushOutgoing(); + }, + + // nsIOutputStreamCallback + /** + * This is called when the output stream is ready for more data to be written. + * The current outgoing packet will attempt to write some amount of data, but + * may not complete. + */ + onOutputStreamReady: DevToolsUtils.makeInfallible(function () { + if (!this._outgoingEnabled || this._outgoing.length === 0) { + return; + } + + try { + this._currentOutgoing.write({ + write: data => { + var count = data.length; + this._socket.send(data); + return count; + } + }); + } catch (e) { + if (e.result != Cr.NS_BASE_STREAM_WOULD_BLOCK) { + this.close(e.result); + return; + } else { + throw e; + } + } + + this._flushOutgoing(); + }, "DebuggerTransport.prototype.onOutputStreamReady"), + + /** + * Remove the current outgoing packet from the queue upon completion. + */ + _finishCurrentOutgoing: function () { + if (this._currentOutgoing) { + this._currentOutgoing.destroy(); + this._outgoing.shift(); + } + }, + + /** + * Clear the entire outgoing queue. + */ + _destroyAllOutgoing: function () { + for (var packet of this._outgoing) { + packet.destroy(); + } + this._outgoing = []; + }, + + /** + * Initialize the input stream for reading. Once this method has been called, + * we watch for packets on the input stream, and pass them to the appropriate + * handlers via this.hooks. + */ + ready: function () { + this.active = true; + this._waitForIncoming(); + }, + + /** + * Asks the input stream to notify us (via onInputStreamReady) when it is + * ready for reading. + */ + _waitForIncoming: function () { + if (this._incomingEnabled && !this._socket.onmessage) { + this._socket.onmessage = this.onInputStreamReady.bind(this); + } + }, + + /** + * Pause this transport's attempts to read from the input stream. This is + * used when we've temporarily handed off our input stream for reading bulk + * data. + */ + pauseIncoming: function () { + this._incomingEnabled = false; + }, + + /** + * Resume this transport's attempts to read from the input stream. + */ + resumeIncoming: function () { + this._incomingEnabled = true; + this._flushIncoming(); + this._waitForIncoming(); + }, + + // nsIInputStreamCallback + /** + * Called when the stream is either readable or closed. + */ + onInputStreamReady: DevToolsUtils.makeInfallible(function (event) { + var data = event.data; + // TODO: ws-tcp-proxy decodes utf-8, but the transport expects to see the + // encoded bytes. Simplest step is to re-encode for now. + data = utf8.encode(data); + var stream = { + available() { + return data.length; + }, + readBytes(count) { + var result = data.slice(0, count); + data = data.slice(count); + return result; + } + }; + + try { + while (data && this._incomingEnabled && this._processIncoming(stream, stream.available())) {} + this._waitForIncoming(); + } catch (e) { + if (e.result != Cr.NS_BASE_STREAM_WOULD_BLOCK) { + this.close(e.result); + } else { + throw e; + } + } + }, "DebuggerTransport.prototype.onInputStreamReady"), + + /** + * Process the incoming data. Will create a new currently incoming Packet if + * needed. Tells the incoming Packet to read as much data as it can, but + * reading may not complete. The Packet signals that its data is ready for + * delivery by calling one of this transport's _on*Ready methods (see + * ./packets.js and the _on*Ready methods below). + * @return boolean + * Whether incoming stream processing should continue for any + * remaining data. + */ + _processIncoming: function (stream, count) { + dumpv("Data available: " + count); + + if (!count) { + dumpv("Nothing to read, skipping"); + return false; + } + + try { + if (!this._incoming) { + dumpv("Creating a new packet from incoming"); + + if (!this._readHeader(stream)) { + return false; // Not enough data to read packet type + } + + // Attempt to create a new Packet by trying to parse each possible + // header pattern. + this._incoming = Packet.fromHeader(this._incomingHeader, this); + if (!this._incoming) { + throw new Error("No packet types for header: " + this._incomingHeader); + } + } + + if (!this._incoming.done) { + // We have an incomplete packet, keep reading it. + dumpv("Existing packet incomplete, keep reading"); + this._incoming.read(stream); + } + } catch (e) { + var msg = "Error reading incoming packet: (" + e + " - " + e.stack + ")"; + dumpn(msg); + + // Now in an invalid state, shut down the transport. + this.close(); + return false; + } + + if (!this._incoming.done) { + // Still not complete, we'll wait for more data. + dumpv("Packet not done, wait for more"); + return true; + } + + // Ready for next packet + this._flushIncoming(); + return true; + }, + + /** + * Read as far as we can into the incoming data, attempting to build up a + * complete packet header (which terminates with ":"). We'll only read up to + * PACKET_HEADER_MAX characters. + * @return boolean + * True if we now have a complete header. + */ + _readHeader: function (stream) { + var amountToRead = PACKET_HEADER_MAX - this._incomingHeader.length; + this._incomingHeader += StreamUtils.delimitedRead(stream, ":", amountToRead); + if (dumpv.wantVerbose) { + dumpv("Header read: " + this._incomingHeader); + } + + if (this._incomingHeader.endsWith(":")) { + if (dumpv.wantVerbose) { + dumpv("Found packet header successfully: " + this._incomingHeader); + } + return true; + } + + if (this._incomingHeader.length >= PACKET_HEADER_MAX) { + throw new Error("Failed to parse packet header!"); + } + + // Not enough data yet. + return false; + }, + + /** + * If the incoming packet is done, log it as needed and clear the buffer. + */ + _flushIncoming: function () { + if (!this._incoming.done) { + return; + } + if (dumpn.wantLogging) { + dumpn("Got: " + this._incoming); + } + this._destroyIncoming(); + }, + + /** + * Handler triggered by an incoming JSONPacket completing it's |read| method. + * Delivers the packet to this.hooks.onPacket. + */ + _onJSONObjectReady: function (object) { + DevToolsUtils.executeSoon(DevToolsUtils.makeInfallible(() => { + // Ensure the transport is still alive by the time this runs. + if (this.active) { + this.emit("onPacket", object); + this.hooks.onPacket(object); + } + }, "DebuggerTransport instance's this.hooks.onPacket")); + }, + + /** + * Handler triggered by an incoming BulkPacket entering the |read| phase for + * the stream portion of the packet. Delivers info about the incoming + * streaming data to this.hooks.onBulkPacket. See the main comment on the + * transport at the top of this file for more details. + */ + _onBulkReadReady: function () { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + DevToolsUtils.executeSoon(DevToolsUtils.makeInfallible(() => { + // Ensure the transport is still alive by the time this runs. + if (this.active) { + var _hooks; + + this.emit.apply(this, ["onBulkPacket"].concat(args)); + (_hooks = this.hooks).onBulkPacket.apply(_hooks, args); + } + }, "DebuggerTransport instance's this.hooks.onBulkPacket")); + }, + + /** + * Remove all handlers and references related to the current incoming packet, + * either because it is now complete or because the transport is closing. + */ + _destroyIncoming: function () { + if (this._incoming) { + this._incoming.destroy(); + } + this._incomingHeader = ""; + this._incoming = null; + } + + }; + + exports.DebuggerTransport = DebuggerTransport; + + /** + * An adapter that handles data transfers between the debugger client and + * server when they both run in the same process. It presents the same API as + * DebuggerTransport, but instead of transmitting serialized messages across a + * connection it merely calls the packet dispatcher of the other side. + * + * @param other LocalDebuggerTransport + * The other endpoint for this debugger connection. + * + * @see DebuggerTransport + */ + function LocalDebuggerTransport(other) { + EventEmitter.decorate(this); + + this.other = other; + this.hooks = null; + + /* + * A packet number, shared between this and this.other. This isn't used + * by the protocol at all, but it makes the packet traces a lot easier to + * follow. + */ + this._serial = this.other ? this.other._serial : { count: 0 }; + this.close = this.close.bind(this); + } + + LocalDebuggerTransport.prototype = { + /** + * Transmit a message by directly calling the onPacket handler of the other + * endpoint. + */ + send: function (packet) { + this.emit("send", packet); + + var serial = this._serial.count++; + if (dumpn.wantLogging) { + /* Check 'from' first, as 'echo' packets have both. */ + if (packet.from) { + dumpn("Packet " + serial + " sent from " + uneval(packet.from)); + } else if (packet.to) { + dumpn("Packet " + serial + " sent to " + uneval(packet.to)); + } + } + this._deepFreeze(packet); + var other = this.other; + if (other) { + DevToolsUtils.executeSoon(DevToolsUtils.makeInfallible(() => { + // Avoid the cost of JSON.stringify() when logging is disabled. + if (dumpn.wantLogging) { + dumpn("Received packet " + serial + ": " + JSON.stringify(packet, null, 2)); + } + if (other.hooks) { + other.emit("onPacket", packet); + other.hooks.onPacket(packet); + } + }, "LocalDebuggerTransport instance's this.other.hooks.onPacket")); + } + }, + + /** + * Send a streaming bulk packet directly to the onBulkPacket handler of the + * other endpoint. + * + * This case is much simpler than the full DebuggerTransport, since there is + * no primary stream we have to worry about managing while we hand it off to + * others temporarily. Instead, we can just make a single use pipe and be + * done with it. + */ + startBulkSend: function (_ref) { + var actor = _ref.actor; + var type = _ref.type; + var length = _ref.length; + + this.emit("startBulkSend", { actor, type, length }); + + var serial = this._serial.count++; + + dumpn("Sent bulk packet " + serial + " for actor " + actor); + if (!this.other) { + return; + } + + var pipe = new Pipe(true, true, 0, 0, null); + + DevToolsUtils.executeSoon(DevToolsUtils.makeInfallible(() => { + dumpn("Received bulk packet " + serial); + if (!this.other.hooks) { + return; + } + + // Receiver + var deferred = promise.defer(); + var packet = { + actor: actor, + type: type, + length: length, + copyTo: output => { + var copying = StreamUtils.copyStream(pipe.inputStream, output, length); + deferred.resolve(copying); + return copying; + }, + stream: pipe.inputStream, + done: deferred + }; + + this.other.emit("onBulkPacket", packet); + this.other.hooks.onBulkPacket(packet); + + // Await the result of reading from the stream + deferred.promise.then(() => pipe.inputStream.close(), this.close); + }, "LocalDebuggerTransport instance's this.other.hooks.onBulkPacket")); + + // Sender + var sendDeferred = promise.defer(); + + // The remote transport is not capable of resolving immediately here, so we + // shouldn't be able to either. + DevToolsUtils.executeSoon(() => { + var copyDeferred = promise.defer(); + + sendDeferred.resolve({ + copyFrom: input => { + var copying = StreamUtils.copyStream(input, pipe.outputStream, length); + copyDeferred.resolve(copying); + return copying; + }, + stream: pipe.outputStream, + done: copyDeferred + }); + + // Await the result of writing to the stream + copyDeferred.promise.then(() => pipe.outputStream.close(), this.close); + }); + + return sendDeferred.promise; + }, + + /** + * Close the transport. + */ + close: function () { + this.emit("close"); + + if (this.other) { + // Remove the reference to the other endpoint before calling close(), to + // avoid infinite recursion. + var other = this.other; + this.other = null; + other.close(); + } + if (this.hooks) { + try { + this.hooks.onClosed(); + } catch (ex) { + console.error(ex); + } + this.hooks = null; + } + }, + + /** + * An empty method for emulating the DebuggerTransport API. + */ + ready: function () {}, + + /** + * Helper function that makes an object fully immutable. + */ + _deepFreeze: function (object) { + Object.freeze(object); + for (var prop in object) { + // Freeze the properties that are objects, not on the prototype, and not + // already frozen. Note that this might leave an unfrozen reference + // somewhere in the object if there is an already frozen object containing + // an unfrozen object. + if (object.hasOwnProperty(prop) && typeof object === "object" && !Object.isFrozen(object)) { + this._deepFreeze(o[prop]); + } + } + } + }; + + exports.LocalDebuggerTransport = LocalDebuggerTransport; + + /** + * A transport for the debugging protocol that uses nsIMessageSenders to + * exchange packets with servers running in child processes. + * + * In the parent process, |sender| should be the nsIMessageSender for the + * child process. In a child process, |sender| should be the child process + * message manager, which sends packets to the parent. + * + * |prefix| is a string included in the message names, to distinguish + * multiple servers running in the same child process. + * + * This transport exchanges messages named 'debug:<prefix>:packet', where + * <prefix> is |prefix|, whose data is the protocol packet. + */ + function ChildDebuggerTransport(sender, prefix) { + EventEmitter.decorate(this); + + this._sender = sender.QueryInterface(Ci.nsIMessageSender); + this._messageName = "debug:" + prefix + ":packet"; + } + + /* + * To avoid confusion, we use 'message' to mean something that + * nsIMessageSender conveys, and 'packet' to mean a remote debugging + * protocol packet. + */ + ChildDebuggerTransport.prototype = { + constructor: ChildDebuggerTransport, + + hooks: null, + + ready: function () { + this._sender.addMessageListener(this._messageName, this); + }, + + close: function () { + this._sender.removeMessageListener(this._messageName, this); + this.emit("onClosed"); + this.hooks.onClosed(); + }, + + receiveMessage: function (_ref2) { + var data = _ref2.data; + + this.emit("onPacket", data); + this.hooks.onPacket(data); + }, + + send: function (packet) { + this.emit("send", packet); + this._sender.sendAsyncMessage(this._messageName, packet); + }, + + startBulkSend: function () { + throw new Error("Can't send bulk data to child processes."); + } + }; + + exports.ChildDebuggerTransport = ChildDebuggerTransport; + + // WorkerDebuggerTransport is defined differently depending on whether we are + // on the main thread or a worker thread. In the former case, we are required + // by the devtools loader, and isWorker will be false. Otherwise, we are + // required by the worker loader, and isWorker will be true. + // + // Each worker debugger supports only a single connection to the main thread. + // However, its theoretically possible for multiple servers to connect to the + // same worker. Consequently, each transport has a connection id, to allow + // messages from multiple connections to be multiplexed on a single channel. + + if (typeof WorkerGlobalScope === 'undefined') { + // i.e. not in a worker + (function () { + // Main thread + /** + * A transport that uses a WorkerDebugger to send packets from the main + * thread to a worker thread. + */ + function WorkerDebuggerTransport(dbg, id) { + this._dbg = dbg; + this._id = id; + this.onMessage = this._onMessage.bind(this); + } + + WorkerDebuggerTransport.prototype = { + constructor: WorkerDebuggerTransport, + + ready: function () { + this._dbg.addListener(this); + }, + + close: function () { + this._dbg.removeListener(this); + if (this.hooks) { + this.hooks.onClosed(); + } + }, + + send: function (packet) { + this._dbg.postMessage(JSON.stringify({ + type: "message", + id: this._id, + message: packet + })); + }, + + startBulkSend: function () { + throw new Error("Can't send bulk data from worker threads!"); + }, + + _onMessage: function (message) { + var packet = JSON.parse(message); + if (packet.type !== "message" || packet.id !== this._id) { + return; + } + + if (this.hooks) { + this.hooks.onPacket(packet.message); + } + } + }; + + exports.WorkerDebuggerTransport = WorkerDebuggerTransport; + }).call(this); + } else { + (function () { + // Worker thread + /* + * A transport that uses a WorkerDebuggerGlobalScope to send packets from a + * worker thread to the main thread. + */ + function WorkerDebuggerTransport(scope, id) { + this._scope = scope; + this._id = id; + this._onMessage = this._onMessage.bind(this); + } + + WorkerDebuggerTransport.prototype = { + constructor: WorkerDebuggerTransport, + + ready: function () { + this._scope.addEventListener("message", this._onMessage); + }, + + close: function () { + this._scope.removeEventListener("message", this._onMessage); + if (this.hooks) { + this.hooks.onClosed(); + } + }, + + send: function (packet) { + this._scope.postMessage(JSON.stringify({ + type: "message", + id: this._id, + message: packet + })); + }, + + startBulkSend: function () { + throw new Error("Can't send bulk data from worker threads!"); + }, + + _onMessage: function (event) { + var packet = JSON.parse(event.data); + if (packet.type !== "message" || packet.id !== this._id) { + return; + } + + if (this.hooks) { + this.hooks.onPacket(packet.message); + } + } + }; + + exports.WorkerDebuggerTransport = WorkerDebuggerTransport; + }).call(this); + } + +/***/ }, +/* 68 */ +/***/ function(module, exports, __webpack_require__) { + + var _this = this; + + function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + /* General utilities used throughout devtools. */ + var _require = __webpack_require__(61); + + var Ci = _require.Ci; + var Cu = _require.Cu; + var Cc = _require.Cc; + var components = _require.components; + + var _require2 = __webpack_require__(30); + + var Services = _require2.Services; + + var promise = __webpack_require__(66); + + var _require3 = __webpack_require__(69); + + var FileUtils = _require3.FileUtils; + + /** + * Turn the error |aError| into a string, without fail. + */ + + exports.safeErrorString = function safeErrorString(aError) { + try { + var errorString = aError.toString(); + if (typeof errorString == "string") { + // Attempt to attach a stack to |errorString|. If it throws an error, or + // isn't a string, don't use it. + try { + if (aError.stack) { + var stack = aError.stack.toString(); + if (typeof stack == "string") { + errorString += "\nStack: " + stack; + } + } + } catch (ee) {} + + // Append additional line and column number information to the output, + // since it might not be part of the stringified error. + if (typeof aError.lineNumber == "number" && typeof aError.columnNumber == "number") { + errorString += "Line: " + aError.lineNumber + ", column: " + aError.columnNumber; + } + + return errorString; + } + } catch (ee) {} + + // We failed to find a good error description, so do the next best thing. + return Object.prototype.toString.call(aError); + }; + + /** + * Report that |aWho| threw an exception, |aException|. + */ + exports.reportException = function reportException(aWho, aException) { + var msg = aWho + " threw an exception: " + exports.safeErrorString(aException); + + console.log(msg); + + // if (Cu && console.error) { + // /* + // * Note that the xpcshell test harness registers an observer for + // * console messages, so when we're running tests, this will cause + // * the test to quit. + // */ + // console.error(msg); + // } + }; + + /** + * Given a handler function that may throw, return an infallible handler + * function that calls the fallible handler, and logs any exceptions it + * throws. + * + * @param aHandler function + * A handler function, which may throw. + * @param aName string + * A name for aHandler, for use in error messages. If omitted, we use + * aHandler.name. + * + * (SpiderMonkey does generate good names for anonymous functions, but we + * don't have a way to get at them from JavaScript at the moment.) + */ + exports.makeInfallible = function makeInfallible(aHandler, aName) { + if (!aName) aName = aHandler.name; + + return function () /* arguments */{ + // try { + return aHandler.apply(this, arguments); + // } catch (ex) { + // let who = "Handler function"; + // if (aName) { + // who += " " + aName; + // } + // return exports.reportException(who, ex); + // } + }; + }; + + /** + * Waits for the next tick in the event loop to execute a callback. + */ + exports.executeSoon = function executeSoon(aFn) { + setTimeout(aFn, 0); + }; + + /** + * Waits for the next tick in the event loop. + * + * @return Promise + * A promise that is resolved after the next tick in the event loop. + */ + exports.waitForTick = function waitForTick() { + var deferred = promise.defer(); + exports.executeSoon(deferred.resolve); + return deferred.promise; + }; + + /** + * Waits for the specified amount of time to pass. + * + * @param number aDelay + * The amount of time to wait, in milliseconds. + * @return Promise + * A promise that is resolved after the specified amount of time passes. + */ + exports.waitForTime = function waitForTime(aDelay) { + var deferred = promise.defer(); + setTimeout(deferred.resolve, aDelay); + return deferred.promise; + }; + + /** + * Like Array.prototype.forEach, but doesn't cause jankiness when iterating over + * very large arrays by yielding to the browser and continuing execution on the + * next tick. + * + * @param Array aArray + * The array being iterated over. + * @param Function aFn + * The function called on each item in the array. If a promise is + * returned by this function, iterating over the array will be paused + * until the respective promise is resolved. + * @returns Promise + * A promise that is resolved once the whole array has been iterated + * over, and all promises returned by the aFn callback are resolved. + */ + exports.yieldingEach = function yieldingEach(aArray, aFn) { + var deferred = promise.defer(); + + var i = 0; + var len = aArray.length; + var outstanding = [deferred.promise]; + + (function loop() { + var start = Date.now(); + + while (i < len) { + // Don't block the main thread for longer than 16 ms at a time. To + // maintain 60fps, you have to render every frame in at least 16ms; we + // aren't including time spent in non-JS here, but this is Good + // Enough(tm). + if (Date.now() - start > 16) { + exports.executeSoon(loop); + return; + } + + try { + outstanding.push(aFn(aArray[i], i++)); + } catch (e) { + deferred.reject(e); + return; + } + } + + deferred.resolve(); + })(); + + return promise.all(outstanding); + }; + + /** + * Like XPCOMUtils.defineLazyGetter, but with a |this| sensitive getter that + * allows the lazy getter to be defined on a prototype and work correctly with + * instances. + * + * @param Object aObject + * The prototype object to define the lazy getter on. + * @param String aKey + * The key to define the lazy getter on. + * @param Function aCallback + * The callback that will be called to determine the value. Will be + * called with the |this| value of the current instance. + */ + exports.defineLazyPrototypeGetter = function defineLazyPrototypeGetter(aObject, aKey, aCallback) { + Object.defineProperty(aObject, aKey, { + configurable: true, + get: function () { + var value = aCallback.call(this); + + Object.defineProperty(this, aKey, { + configurable: true, + writable: true, + value: value + }); + + return value; + } + }); + }; + + /** + * Safely get the property value from a Debugger.Object for a given key. Walks + * the prototype chain until the property is found. + * + * @param Debugger.Object aObject + * The Debugger.Object to get the value from. + * @param String aKey + * The key to look for. + * @return Any + */ + exports.getProperty = function getProperty(aObj, aKey) { + var root = aObj; + try { + do { + var desc = aObj.getOwnPropertyDescriptor(aKey); + if (desc) { + if ("value" in desc) { + return desc.value; + } + // Call the getter if it's safe. + return exports.hasSafeGetter(desc) ? desc.get.call(root).return : undefined; + } + aObj = aObj.proto; + } while (aObj); + } catch (e) { + // If anything goes wrong report the error and return undefined. + exports.reportException("getProperty", e); + } + return undefined; + }; + + /** + * Determines if a descriptor has a getter which doesn't call into JavaScript. + * + * @param Object aDesc + * The descriptor to check for a safe getter. + * @return Boolean + * Whether a safe getter was found. + */ + exports.hasSafeGetter = function hasSafeGetter(aDesc) { + // Scripted functions that are CCWs will not appear scripted until after + // unwrapping. + try { + var fn = aDesc.get.unwrap(); + return fn && fn.callable && fn.class == "Function" && fn.script === undefined; + } catch (e) { + // Avoid exception 'Object in compartment marked as invisible to Debugger' + return false; + } + }; + + /** + * Check if it is safe to read properties and execute methods from the given JS + * object. Safety is defined as being protected from unintended code execution + * from content scripts (or cross-compartment code). + * + * See bugs 945920 and 946752 for discussion. + * + * @type Object aObj + * The object to check. + * @return Boolean + * True if it is safe to read properties from aObj, or false otherwise. + */ + exports.isSafeJSObject = function isSafeJSObject(aObj) { + // If we are running on a worker thread, Cu is not available. In this case, + // we always return false, just to be on the safe side. + if (isWorker) { + return false; + } + + if (Cu.getGlobalForObject(aObj) == Cu.getGlobalForObject(exports.isSafeJSObject)) { + return true; // aObj is not a cross-compartment wrapper. + } + + var principal = Cu.getObjectPrincipal(aObj); + if (Services.scriptSecurityManager.isSystemPrincipal(principal)) { + return true; // allow chrome objects + } + + return Cu.isXrayWrapper(aObj); + }; + + exports.dumpn = function dumpn(str) { + if (exports.dumpn.wantLogging) { + console.log("DBG-SERVER: " + str + "\n"); + } + }; + + // We want wantLogging to be writable. The exports object is frozen by the + // loader, so define it on dumpn instead. + exports.dumpn.wantLogging = false; + + /** + * A verbose logger for low-level tracing. + */ + exports.dumpv = function (msg) { + if (exports.dumpv.wantVerbose) { + exports.dumpn(msg); + } + }; + + // We want wantLogging to be writable. The exports object is frozen by the + // loader, so define it on dumpn instead. + exports.dumpv.wantVerbose = false; + + /** + * Utility function for updating an object with the properties of + * other objects. + * + * @param aTarget Object + * The object being updated. + * @param aNewAttrs Object + * The rest params are objects to update aTarget with. You + * can pass as many as you like. + */ + exports.update = function update(aTarget) { + for (var _len = arguments.length, aArgs = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + aArgs[_key - 1] = arguments[_key]; + } + + for (var attrs of aArgs) { + for (var key in attrs) { + var desc = Object.getOwnPropertyDescriptor(attrs, key); + + if (desc) { + Object.defineProperty(aTarget, key, desc); + } + } + } + + return aTarget; + }; + + /** + * Utility function for getting the values from an object as an array + * + * @param aObject Object + * The object to iterate over + */ + exports.values = function values(aObject) { + return Object.keys(aObject).map(k => aObject[k]); + }; + + /** + * Defines a getter on a specified object that will be created upon first use. + * + * @param aObject + * The object to define the lazy getter on. + * @param aName + * The name of the getter to define on aObject. + * @param aLambda + * A function that returns what the getter should return. This will + * only ever be called once. + */ + exports.defineLazyGetter = function defineLazyGetter(aObject, aName, aLambda) { + Object.defineProperty(aObject, aName, { + get: function () { + delete aObject[aName]; + return aObject[aName] = aLambda.apply(aObject); + }, + configurable: true, + enumerable: true + }); + }; + + // DEPRECATED: use DevToolsUtils.assert(condition, message) instead! + var haveLoggedDeprecationMessage = false; + exports.dbg_assert = function dbg_assert(cond, e) { + if (!haveLoggedDeprecationMessage) { + haveLoggedDeprecationMessage = true; + var deprecationMessage = "DevToolsUtils.dbg_assert is deprecated! Use DevToolsUtils.assert instead!" + Error().stack; + console.log(deprecationMessage); + if (typeof console === "object" && console && console.warn) { + console.warn(deprecationMessage); + } + } + + if (!cond) { + return e; + } + }; + + var _require4 = __webpack_require__(70); + + var AppConstants = _require4.AppConstants; + + /** + * No operation. The empty function. + */ + + exports.noop = function () {}; + + function reallyAssert(condition, message) { + if (!condition) { + var err = new Error("Assertion failure: " + message); + exports.reportException("DevToolsUtils.assert", err); + throw err; + } + } + + /** + * DevToolsUtils.assert(condition, message) + * + * @param Boolean condition + * @param String message + * + * Assertions are enabled when any of the following are true: + * - This is a DEBUG_JS_MODULES build + * - This is a DEBUG build + * - DevToolsUtils.testing is set to true + * + * If assertions are enabled, then `condition` is checked and if false-y, the + * assertion failure is logged and then an error is thrown. + * + * If assertions are not enabled, then this function is a no-op. + * + * This is an improvement over `dbg_assert`, which doesn't actually cause any + * fatal behavior, and is therefore much easier to accidentally ignore. + */ + Object.defineProperty(exports, "assert", { + get: () => AppConstants.DEBUG || AppConstants.DEBUG_JS_MODULES || _this.testing ? reallyAssert : exports.noop + }); + + /** + * Defines a getter on a specified object for a module. The module will not + * be imported until first use. + * + * @param aObject + * The object to define the lazy getter on. + * @param aName + * The name of the getter to define on aObject for the module. + * @param aResource + * The URL used to obtain the module. + * @param aSymbol + * The name of the symbol exported by the module. + * This parameter is optional and defaults to aName. + */ + exports.defineLazyModuleGetter = function defineLazyModuleGetter(aObject, aName, aResource, aSymbol) { + this.defineLazyGetter(aObject, aName, function XPCU_moduleLambda() { + var temp = {}; + Cu.import(aResource, temp); + return temp[aSymbol || aName]; + }); + }; + + var _require5 = __webpack_require__(71); + + var NetUtil = _require5.NetUtil; + + var _require6 = __webpack_require__(72); + + var TextDecoder = _require6.TextDecoder; + var OS = _require6.OS; + + + var NetworkHelper = __webpack_require__(73); + + /** + * Performs a request to load the desired URL and returns a promise. + * + * @param aURL String + * The URL we will request. + * @param aOptions Object + * An object with the following optional properties: + * - loadFromCache: if false, will bypass the cache and + * always load fresh from the network (default: true) + * - policy: the nsIContentPolicy type to apply when fetching the URL + * - window: the window to get the loadGroup from + * - charset: the charset to use if the channel doesn't provide one + * @returns Promise that resolves with an object with the following members on + * success: + * - content: the document at that URL, as a string, + * - contentType: the content type of the document + * + * If an error occurs, the promise is rejected with that error. + * + * XXX: It may be better to use nsITraceableChannel to get to the sources + * without relying on caching when we can (not for eval, etc.): + * http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/ + */ + function mainThreadFetch(aURL) { + var aOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { loadFromCache: true, + policy: Ci.nsIContentPolicy.TYPE_OTHER, + window: null, + charset: null }; + + // Create a channel. + var url = aURL.split(" -> ").pop(); + var channel = void 0; + try { + channel = newChannelForURL(url, aOptions); + } catch (ex) { + return promise.reject(ex); + } + + // Set the channel options. + channel.loadFlags = aOptions.loadFromCache ? channel.LOAD_FROM_CACHE : channel.LOAD_BYPASS_CACHE; + + if (aOptions.window) { + // Respect private browsing. + channel.loadGroup = aOptions.window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocumentLoader).loadGroup; + } + + var deferred = promise.defer(); + var onResponse = (stream, status, request) => { + if (!components.isSuccessCode(status)) { + deferred.reject(new Error(`Failed to fetch ${ url }. Code ${ status }.`)); + return; + } + + try { + // We cannot use NetUtil to do the charset conversion as if charset + // information is not available and our default guess is wrong the method + // might fail and we lose the stream data. This means we can't fall back + // to using the locale default encoding (bug 1181345). + + // Read and decode the data according to the locale default encoding. + var available = stream.available(); + var source = NetUtil.readInputStreamToString(stream, available); + stream.close(); + + // If the channel or the caller has correct charset information, the + // content will be decoded correctly. If we have to fall back to UTF-8 and + // the guess is wrong, the conversion fails and convertToUnicode returns + // the input unmodified. Essentially we try to decode the data as UTF-8 + // and if that fails, we use the locale specific default encoding. This is + // the best we can do if the source does not provide charset info. + var charset = channel.contentCharset || aOptions.charset || "UTF-8"; + var unicodeSource = NetworkHelper.convertToUnicode(source, charset); + + deferred.resolve({ + content: unicodeSource, + contentType: request.contentType + }); + } catch (ex) { + var uri = request.originalURI; + if (ex.name === "NS_BASE_STREAM_CLOSED" && uri instanceof Ci.nsIFileURL) { + // Empty files cause NS_BASE_STREAM_CLOSED exception. Use OS.File to + // differentiate between empty files and other errors (bug 1170864). + // This can be removed when bug 982654 is fixed. + + uri.QueryInterface(Ci.nsIFileURL); + var result = OS.File.read(uri.file.path).then(bytes => { + // Convert the bytearray to a String. + var decoder = new TextDecoder(); + var content = decoder.decode(bytes); + + // We can't detect the contentType without opening a channel + // and that failed already. This is the best we can do here. + return { + content, + contentType: "text/plain" + }; + }); + + deferred.resolve(result); + } else { + deferred.reject(ex); + } + } + }; + + // Open the channel + try { + NetUtil.asyncFetch(channel, onResponse); + } catch (ex) { + return promise.reject(ex); + } + + return deferred.promise; + } + + /** + * Opens a channel for given URL. Tries a bit harder than NetUtil.newChannel. + * + * @param {String} url - The URL to open a channel for. + * @param {Object} options - The options object passed to @method fetch. + * @return {nsIChannel} - The newly created channel. Throws on failure. + */ + function newChannelForURL(url, _ref) { + var policy = _ref.policy; + + var channelOptions = { + contentPolicyType: policy, + loadUsingSystemPrincipal: true, + uri: url + }; + + try { + return NetUtil.newChannel(channelOptions); + } catch (e) { + // In the xpcshell tests, the script url is the absolute path of the test + // file, which will make a malformed URI error be thrown. Add the file + // scheme to see if it helps. + channelOptions.uri = "file://" + url; + + return NetUtil.newChannel(channelOptions); + } + } + + // Fetch is defined differently depending on whether we are on the main thread + // or a worker thread. + if (typeof WorkerGlobalScope === "undefined") { + // i.e. not in a worker + exports.fetch = mainThreadFetch; + } else { + // Services is not available in worker threads, nor is there any other way + // to fetch a URL. We need to enlist the help from the main thread here, by + // issuing an rpc request, to fetch the URL on our behalf. + exports.fetch = function (url, options) { + return rpc("fetch", url, options); + }; + } + + /** + * Returns a promise that is resolved or rejected when all promises have settled + * (resolved or rejected). + * + * This differs from Promise.all, which will reject immediately after the first + * rejection, instead of waiting for the remaining promises to settle. + * + * @param values + * Iterable of promises that may be pending, resolved, or rejected. When + * when all promises have settled (resolved or rejected), the returned + * promise will be resolved or rejected as well. + * + * @return A new promise that is fulfilled when all values have settled + * (resolved or rejected). Its resolution value will be an array of all + * resolved values in the given order, or undefined if values is an + * empty array. The reject reason will be forwarded from the first + * promise in the list of given promises to be rejected. + */ + exports.settleAll = values => { + if (values === null || typeof values[Symbol.iterator] != "function") { + throw new Error("settleAll() expects an iterable."); + } + + var deferred = promise.defer(); + + values = Array.isArray(values) ? values : [].concat(_toConsumableArray(values)); + var countdown = values.length; + var resolutionValues = new Array(countdown); + var rejectionValue = void 0; + var rejectionOccurred = false; + + if (!countdown) { + deferred.resolve(resolutionValues); + return deferred.promise; + } + + function checkForCompletion() { + if (--countdown > 0) { + return; + } + if (!rejectionOccurred) { + deferred.resolve(resolutionValues); + } else { + deferred.reject(rejectionValue); + } + } + + var _loop = function (i) { + var index = i; + var value = values[i]; + var resolver = result => { + resolutionValues[index] = result; + checkForCompletion(); + }; + var rejecter = error => { + if (!rejectionOccurred) { + rejectionValue = error; + rejectionOccurred = true; + } + checkForCompletion(); + }; + + if (value && typeof value.then == "function") { + value.then(resolver, rejecter); + } else { + // Given value is not a promise, forward it as a resolution value. + resolver(value); + } + }; + + for (var i = 0; i < values.length; i++) { + _loop(i); + } + + return deferred.promise; + }; + + /** + * When the testing flag is set, various behaviors may be altered from + * production mode, typically to enable easier testing or enhanced debugging. + */ + var testing = false; + Object.defineProperty(exports, "testing", { + get: function () { + return testing; + }, + set: function (state) { + testing = state; + } + }); + + /** + * Open the file at the given path for reading. + * + * @param {String} filePath + * + * @returns Promise<nsIInputStream> + */ + exports.openFileStream = function (filePath) { + return new Promise((resolve, reject) => { + var uri = NetUtil.newURI(new FileUtils.File(filePath)); + NetUtil.asyncFetch({ uri, loadUsingSystemPrincipal: true }, (stream, result) => { + if (!components.isSuccessCode(result)) { + reject(new Error(`Could not open "${ filePath }": result = ${ result }`)); + return; + } + + resolve(stream); + }); + }); + }; + + exports.isGenerator = function (fn) { + if (typeof fn !== "function") { + return false; + } + var proto = Object.getPrototypeOf(fn); + if (!proto) { + return false; + } + var ctor = proto.constructor; + if (!ctor) { + return false; + } + return ctor.name == "GeneratorFunction"; + }; + + exports.isPromise = function (p) { + return p && typeof p.then === "function"; + }; + + /** + * Return true if `thing` is a SavedFrame, false otherwise. + */ + exports.isSavedFrame = function (thing) { + return Object.prototype.toString.call(thing) === "[object SavedFrame]"; + }; + +/***/ }, +/* 69 */ +/***/ function(module, exports) { + + /* + * A sham for https://dxr.mozilla.org/mozilla-central/source/toolkit/modules/FileUtils.jsm + */ + +/***/ }, +/* 70 */ +/***/ function(module, exports) { + + /* + * A sham for https://dxr.mozilla.org/mozilla-central/source/toolkit/modules/AppConstants.jsm + */ + + module.exports = { AppConstants: {} }; + +/***/ }, +/* 71 */ +/***/ function(module, exports) { + + /* + * A sham for https://dxr.mozilla.org/mozilla-central/source/netwerk/base/NetUtil.jsm + */ + +/***/ }, +/* 72 */ +/***/ function(module, exports) { + + /* + * A sham for https://dxr.mozilla.org/mozilla-central/source/toolkit/components/osfile/osfile.jsm + */ + +/***/ }, +/* 73 */ +/***/ function(module, exports, __webpack_require__) { + + /* vim:set ts=2 sw=2 sts=2 et: */ + /* + * Software License Agreement (BSD License) + * + * Copyright (c) 2007, Parakey Inc. + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * 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 Parakey Inc. nor the names of its + * contributors may be used to endorse or promote products + * derived from this software without specific prior + * written permission of Parakey Inc. + * + * 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. + */ + + /* + * Creator: + * Joe Hewitt + * Contributors + * John J. Barton (IBM Almaden) + * Jan Odvarko (Mozilla Corp.) + * Max Stepanov (Aptana Inc.) + * Rob Campbell (Mozilla Corp.) + * Hans Hillen (Paciello Group, Mozilla) + * Curtis Bartley (Mozilla Corp.) + * Mike Collins (IBM Almaden) + * Kevin Decker + * Mike Ratcliffe (Comartis AG) + * Hernan Rodríguez Colmeiro + * Austin Andrews + * Christoph Dorn + * Steven Roussey (AppCenter Inc, Network54) + * Mihai Sucan (Mozilla Corp.) + */ + + "use strict"; + + var _require = __webpack_require__(61); + + var components = _require.components; + var Cc = _require.Cc; + var Ci = _require.Ci; + var Cu = _require.Cu; + + var _require2 = __webpack_require__(71); + + var NetUtil = _require2.NetUtil; + + var DevToolsUtils = __webpack_require__(68); + + // The cache used in the `nsIURL` function. + var gNSURLStore = new Map(); + + /** + * Helper object for networking stuff. + * + * Most of the following functions have been taken from the Firebug source. They + * have been modified to match the Firefox coding rules. + */ + var NetworkHelper = { + /** + * Converts aText with a given aCharset to unicode. + * + * @param string aText + * Text to convert. + * @param string aCharset + * Charset to convert the text to. + * @returns string + * Converted text. + */ + convertToUnicode: function NH_convertToUnicode(aText, aCharset) { + var conv = Cc("@mozilla.org/intl/scriptableunicodeconverter").createInstance(Ci.nsIScriptableUnicodeConverter); + try { + conv.charset = aCharset || "UTF-8"; + return conv.ConvertToUnicode(aText); + } catch (ex) { + return aText; + } + }, + + /** + * Reads all available bytes from aStream and converts them to aCharset. + * + * @param nsIInputStream aStream + * @param string aCharset + * @returns string + * UTF-16 encoded string based on the content of aStream and aCharset. + */ + readAndConvertFromStream: function NH_readAndConvertFromStream(aStream, aCharset) { + var text = null; + try { + text = NetUtil.readInputStreamToString(aStream, aStream.available()); + return this.convertToUnicode(text, aCharset); + } catch (err) { + return text; + } + }, + + /** + * Reads the posted text from aRequest. + * + * @param nsIHttpChannel aRequest + * @param string aCharset + * The content document charset, used when reading the POSTed data. + * @returns string or null + * Returns the posted string if it was possible to read from aRequest + * otherwise null. + */ + readPostTextFromRequest: function NH_readPostTextFromRequest(aRequest, aCharset) { + if (aRequest instanceof Ci.nsIUploadChannel) { + var iStream = aRequest.uploadStream; + + var isSeekableStream = false; + if (iStream instanceof Ci.nsISeekableStream) { + isSeekableStream = true; + } + + var prevOffset = void 0; + if (isSeekableStream) { + prevOffset = iStream.tell(); + iStream.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0); + } + + // Read data from the stream. + var text = this.readAndConvertFromStream(iStream, aCharset); + + // Seek locks the file, so seek to the beginning only if necko hasn't + // read it yet, since necko doesn't seek to 0 before reading (at lest + // not till 459384 is fixed). + if (isSeekableStream && prevOffset == 0) { + iStream.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0); + } + return text; + } + return null; + }, + + /** + * Reads the posted text from the page's cache. + * + * @param nsIDocShell aDocShell + * @param string aCharset + * @returns string or null + * Returns the posted string if it was possible to read from + * aDocShell otherwise null. + */ + readPostTextFromPage: function NH_readPostTextFromPage(aDocShell, aCharset) { + var webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation); + return this.readPostTextFromPageViaWebNav(webNav, aCharset); + }, + + /** + * Reads the posted text from the page's cache, given an nsIWebNavigation + * object. + * + * @param nsIWebNavigation aWebNav + * @param string aCharset + * @returns string or null + * Returns the posted string if it was possible to read from + * aWebNav, otherwise null. + */ + readPostTextFromPageViaWebNav: function NH_readPostTextFromPageViaWebNav(aWebNav, aCharset) { + if (aWebNav instanceof Ci.nsIWebPageDescriptor) { + var descriptor = aWebNav.currentDescriptor; + + if (descriptor instanceof Ci.nsISHEntry && descriptor.postData && descriptor instanceof Ci.nsISeekableStream) { + descriptor.seek(NS_SEEK_SET, 0); + + return this.readAndConvertFromStream(descriptor, aCharset); + } + } + return null; + }, + + /** + * Gets the web appId that is associated with aRequest. + * + * @param nsIHttpChannel aRequest + * @returns number|null + * The appId for the given request, if available. + */ + getAppIdForRequest: function NH_getAppIdForRequest(aRequest) { + try { + return this.getRequestLoadContext(aRequest).appId; + } catch (ex) { + // request loadContent is not always available. + } + return null; + }, + + /** + * Gets the topFrameElement that is associated with aRequest. This + * works in single-process and multiprocess contexts. It may cross + * the content/chrome boundary. + * + * @param nsIHttpChannel aRequest + * @returns nsIDOMElement|null + * The top frame element for the given request. + */ + getTopFrameForRequest: function NH_getTopFrameForRequest(aRequest) { + try { + return this.getRequestLoadContext(aRequest).topFrameElement; + } catch (ex) { + // request loadContent is not always available. + } + return null; + }, + + /** + * Gets the nsIDOMWindow that is associated with aRequest. + * + * @param nsIHttpChannel aRequest + * @returns nsIDOMWindow or null + */ + getWindowForRequest: function NH_getWindowForRequest(aRequest) { + try { + return this.getRequestLoadContext(aRequest).associatedWindow; + } catch (ex) { + // TODO: bug 802246 - getWindowForRequest() throws on b2g: there is no + // associatedWindow property. + } + return null; + }, + + /** + * Gets the nsILoadContext that is associated with aRequest. + * + * @param nsIHttpChannel aRequest + * @returns nsILoadContext or null + */ + getRequestLoadContext: function NH_getRequestLoadContext(aRequest) { + try { + return aRequest.notificationCallbacks.getInterface(Ci.nsILoadContext); + } catch (ex) {} + + try { + return aRequest.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext); + } catch (ex) {} + + return null; + }, + + /** + * Determines whether the request has been made for the top level document. + * + * @param nsIHttpChannel aRequest + * @returns Boolean True if the request represents the top level document. + */ + isTopLevelLoad: function (aRequest) { + if (aRequest instanceof Ci.nsIChannel) { + var loadInfo = aRequest.loadInfo; + if (loadInfo && loadInfo.parentOuterWindowID == loadInfo.outerWindowID) { + return aRequest.loadFlags & Ci.nsIChannel.LOAD_DOCUMENT_URI; + } + } + + return false; + }, + + /** + * Loads the content of aUrl from the cache. + * + * @param string aUrl + * URL to load the cached content for. + * @param string aCharset + * Assumed charset of the cached content. Used if there is no charset + * on the channel directly. + * @param function aCallback + * Callback that is called with the loaded cached content if available + * or null if something failed while getting the cached content. + */ + loadFromCache: function NH_loadFromCache(aUrl, aCharset, aCallback) { + var channel = NetUtil.newChannel({ uri: aUrl, loadUsingSystemPrincipal: true }); + + // Ensure that we only read from the cache and not the server. + channel.loadFlags = Ci.nsIRequest.LOAD_FROM_CACHE | Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE | Ci.nsICachingChannel.LOAD_BYPASS_LOCAL_CACHE_IF_BUSY; + + NetUtil.asyncFetch(channel, (aInputStream, aStatusCode, aRequest) => { + if (!components.isSuccessCode(aStatusCode)) { + aCallback(null); + return; + } + + // Try to get the encoding from the channel. If there is none, then use + // the passed assumed aCharset. + var aChannel = aRequest.QueryInterface(Ci.nsIChannel); + var contentCharset = aChannel.contentCharset || aCharset; + + // Read the content of the stream using contentCharset as encoding. + aCallback(this.readAndConvertFromStream(aInputStream, contentCharset)); + }); + }, + + /** + * Parse a raw Cookie header value. + * + * @param string aHeader + * The raw Cookie header value. + * @return array + * Array holding an object for each cookie. Each object holds the + * following properties: name and value. + */ + parseCookieHeader: function NH_parseCookieHeader(aHeader) { + var cookies = aHeader.split(";"); + var result = []; + + cookies.forEach(function (aCookie) { + var equal = aCookie.indexOf("="); + var name = aCookie.substr(0, equal); + var value = aCookie.substr(equal + 1); + result.push({ name: unescape(name.trim()), + value: unescape(value.trim()) }); + }); + + return result; + }, + + /** + * Parse a raw Set-Cookie header value. + * + * @param string aHeader + * The raw Set-Cookie header value. + * @return array + * Array holding an object for each cookie. Each object holds the + * following properties: name, value, secure (boolean), httpOnly + * (boolean), path, domain and expires (ISO date string). + */ + parseSetCookieHeader: function NH_parseSetCookieHeader(aHeader) { + var rawCookies = aHeader.split(/\r\n|\n|\r/); + var cookies = []; + + rawCookies.forEach(function (aCookie) { + var equal = aCookie.indexOf("="); + var name = unescape(aCookie.substr(0, equal).trim()); + var parts = aCookie.substr(equal + 1).split(";"); + var value = unescape(parts.shift().trim()); + + var cookie = { name: name, value: value }; + + parts.forEach(function (aPart) { + var part = aPart.trim(); + if (part.toLowerCase() == "secure") { + cookie.secure = true; + } else if (part.toLowerCase() == "httponly") { + cookie.httpOnly = true; + } else if (part.indexOf("=") > -1) { + var pair = part.split("="); + pair[0] = pair[0].toLowerCase(); + if (pair[0] == "path" || pair[0] == "domain") { + cookie[pair[0]] = pair[1]; + } else if (pair[0] == "expires") { + try { + pair[1] = pair[1].replace(/-/g, ' '); + cookie.expires = new Date(pair[1]).toISOString(); + } catch (ex) {} + } + } + }); + + cookies.push(cookie); + }); + + return cookies; + }, + + // This is a list of all the mime category maps jviereck could find in the + // firebug code base. + mimeCategoryMap: { + "text/plain": "txt", + "text/html": "html", + "text/xml": "xml", + "text/xsl": "txt", + "text/xul": "txt", + "text/css": "css", + "text/sgml": "txt", + "text/rtf": "txt", + "text/x-setext": "txt", + "text/richtext": "txt", + "text/javascript": "js", + "text/jscript": "txt", + "text/tab-separated-values": "txt", + "text/rdf": "txt", + "text/xif": "txt", + "text/ecmascript": "js", + "text/vnd.curl": "txt", + "text/x-json": "json", + "text/x-js": "txt", + "text/js": "txt", + "text/vbscript": "txt", + "view-source": "txt", + "view-fragment": "txt", + "application/xml": "xml", + "application/xhtml+xml": "xml", + "application/atom+xml": "xml", + "application/rss+xml": "xml", + "application/vnd.mozilla.maybe.feed": "xml", + "application/vnd.mozilla.xul+xml": "xml", + "application/javascript": "js", + "application/x-javascript": "js", + "application/x-httpd-php": "txt", + "application/rdf+xml": "xml", + "application/ecmascript": "js", + "application/http-index-format": "txt", + "application/json": "json", + "application/x-js": "txt", + "multipart/mixed": "txt", + "multipart/x-mixed-replace": "txt", + "image/svg+xml": "svg", + "application/octet-stream": "bin", + "image/jpeg": "image", + "image/jpg": "image", + "image/gif": "image", + "image/png": "image", + "image/bmp": "image", + "application/x-shockwave-flash": "flash", + "video/x-flv": "flash", + "audio/mpeg3": "media", + "audio/x-mpeg-3": "media", + "video/mpeg": "media", + "video/x-mpeg": "media", + "audio/ogg": "media", + "application/ogg": "media", + "application/x-ogg": "media", + "application/x-midi": "media", + "audio/midi": "media", + "audio/x-mid": "media", + "audio/x-midi": "media", + "music/crescendo": "media", + "audio/wav": "media", + "audio/x-wav": "media", + "text/json": "json", + "application/x-json": "json", + "application/json-rpc": "json", + "application/x-web-app-manifest+json": "json", + "application/manifest+json": "json" + }, + + /** + * Check if the given MIME type is a text-only MIME type. + * + * @param string aMimeType + * @return boolean + */ + isTextMimeType: function NH_isTextMimeType(aMimeType) { + if (aMimeType.indexOf("text/") == 0) { + return true; + } + + // XML and JSON often come with custom MIME types, so in addition to the + // standard "application/xml" and "application/json", we also look for + // variants like "application/x-bigcorp+xml". For JSON we allow "+json" and + // "-json" as suffixes. + if (/^application\/\w+(?:[\.-]\w+)*(?:\+xml|[-+]json)$/.test(aMimeType)) { + return true; + } + + var category = this.mimeCategoryMap[aMimeType] || null; + switch (category) { + case "txt": + case "js": + case "json": + case "css": + case "html": + case "svg": + case "xml": + return true; + + default: + return false; + } + }, + + /** + * Takes a securityInfo object of nsIRequest, the nsIRequest itself and + * extracts security information from them. + * + * @param object securityInfo + * The securityInfo object of a request. If null channel is assumed + * to be insecure. + * @param object httpActivity + * The httpActivity object for the request with at least members + * { private, hostname }. + * + * @return object + * Returns an object containing following members: + * - state: The security of the connection used to fetch this + * request. Has one of following string values: + * * "insecure": the connection was not secure (only http) + * * "weak": the connection has minor security issues + * * "broken": secure connection failed (e.g. expired cert) + * * "secure": the connection was properly secured. + * If state == broken: + * - errorMessage: full error message from nsITransportSecurityInfo. + * If state == secure: + * - protocolVersion: one of TLSv1, TLSv1.1, TLSv1.2. + * - cipherSuite: the cipher suite used in this connection. + * - cert: information about certificate used in this connection. + * See parseCertificateInfo for the contents. + * - hsts: true if host uses Strict Transport Security, false otherwise + * - hpkp: true if host uses Public Key Pinning, false otherwise + * If state == weak: Same as state == secure and + * - weaknessReasons: list of reasons that cause the request to be + * considered weak. See getReasonsForWeakness. + */ + parseSecurityInfo: function NH_parseSecurityInfo(securityInfo, httpActivity) { + var info = { + state: "insecure" + }; + + // The request did not contain any security info. + if (!securityInfo) { + return info; + } + + /** + * Different scenarios to consider here and how they are handled: + * - request is HTTP, the connection is not secure + * => securityInfo is null + * => state === "insecure" + * + * - request is HTTPS, the connection is secure + * => .securityState has STATE_IS_SECURE flag + * => state === "secure" + * + * - request is HTTPS, the connection has security issues + * => .securityState has STATE_IS_INSECURE flag + * => .errorCode is an NSS error code. + * => state === "broken" + * + * - request is HTTPS, the connection was terminated before the security + * could be validated + * => .securityState has STATE_IS_INSECURE flag + * => .errorCode is NOT an NSS error code. + * => .errorMessage is not available. + * => state === "insecure" + * + * - request is HTTPS but it uses a weak cipher or old protocol, see + * http://hg.mozilla.org/mozilla-central/annotate/def6ed9d1c1a/ + * security/manager/ssl/nsNSSCallbacks.cpp#l1233 + * - request is mixed content (which makes no sense whatsoever) + * => .securityState has STATE_IS_BROKEN flag + * => .errorCode is NOT an NSS error code + * => .errorMessage is not available + * => state === "weak" + */ + + securityInfo.QueryInterface(Ci.nsITransportSecurityInfo); + securityInfo.QueryInterface(Ci.nsISSLStatusProvider); + + var wpl = Ci.nsIWebProgressListener; + var NSSErrorsService = Cc['@mozilla.org/nss_errors_service;1'].getService(Ci.nsINSSErrorsService); + var SSLStatus = securityInfo.SSLStatus; + if (!NSSErrorsService.isNSSErrorCode(securityInfo.errorCode)) { + var state = securityInfo.securityState; + + var uri = null; + if (httpActivity.channel && httpActivity.channel.URI) { + uri = httpActivity.channel.URI; + } + if (uri && !uri.schemeIs("https") && !uri.schemeIs("wss")) { + // it is not enough to look at the transport security info - schemes other than + // https and wss are subject to downgrade/etc at the scheme level and should + // always be considered insecure + info.state = "insecure"; + } else if (state & wpl.STATE_IS_SECURE) { + // The connection is secure if the scheme is sufficient + info.state = "secure"; + } else if (state & wpl.STATE_IS_BROKEN) { + // The connection is not secure, there was no error but there's some + // minor security issues. + info.state = "weak"; + info.weaknessReasons = this.getReasonsForWeakness(state); + } else if (state & wpl.STATE_IS_INSECURE) { + // This was most likely an https request that was aborted before + // validation. Return info as info.state = insecure. + return info; + } else { + DevToolsUtils.reportException("NetworkHelper.parseSecurityInfo", "Security state " + state + " has no known STATE_IS_* flags."); + return info; + } + + // Cipher suite. + info.cipherSuite = SSLStatus.cipherName; + + // Protocol version. + info.protocolVersion = this.formatSecurityProtocol(SSLStatus.protocolVersion); + + // Certificate. + info.cert = this.parseCertificateInfo(SSLStatus.serverCert); + + // HSTS and HPKP if available. + if (httpActivity.hostname) { + var sss = Cc("@mozilla.org/ssservice;1").getService(Ci.nsISiteSecurityService); + + // SiteSecurityService uses different storage if the channel is + // private. Thus we must give isSecureHost correct flags or we + // might get incorrect results. + var flags = httpActivity.private ? Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0; + + var host = httpActivity.hostname; + + info.hsts = sss.isSecureHost(sss.HEADER_HSTS, host, flags); + info.hpkp = sss.isSecureHost(sss.HEADER_HPKP, host, flags); + } else { + DevToolsUtils.reportException("NetworkHelper.parseSecurityInfo", "Could not get HSTS/HPKP status as hostname is not available."); + info.hsts = false; + info.hpkp = false; + } + } else { + // The connection failed. + info.state = "broken"; + info.errorMessage = securityInfo.errorMessage; + } + + return info; + }, + + /** + * Takes an nsIX509Cert and returns an object with certificate information. + * + * @param nsIX509Cert cert + * The certificate to extract the information from. + * @return object + * An object with following format: + * { + * subject: { commonName, organization, organizationalUnit }, + * issuer: { commonName, organization, organizationUnit }, + * validity: { start, end }, + * fingerprint: { sha1, sha256 } + * } + */ + parseCertificateInfo: function NH_parseCertifificateInfo(cert) { + var info = {}; + if (cert) { + info.subject = { + commonName: cert.commonName, + organization: cert.organization, + organizationalUnit: cert.organizationalUnit + }; + + info.issuer = { + commonName: cert.issuerCommonName, + organization: cert.issuerOrganization, + organizationUnit: cert.issuerOrganizationUnit + }; + + info.validity = { + start: cert.validity.notBeforeLocalDay, + end: cert.validity.notAfterLocalDay + }; + + info.fingerprint = { + sha1: cert.sha1Fingerprint, + sha256: cert.sha256Fingerprint + }; + } else { + DevToolsUtils.reportException("NetworkHelper.parseCertificateInfo", "Secure connection established without certificate."); + } + + return info; + }, + + /** + * Takes protocolVersion of SSLStatus object and returns human readable + * description. + * + * @param Number version + * One of nsISSLStatus version constants. + * @return string + * One of TLSv1, TLSv1.1, TLSv1.2 if @param version is valid, + * Unknown otherwise. + */ + formatSecurityProtocol: function NH_formatSecurityProtocol(version) { + switch (version) { + case Ci.nsISSLStatus.TLS_VERSION_1: + return "TLSv1"; + case Ci.nsISSLStatus.TLS_VERSION_1_1: + return "TLSv1.1"; + case Ci.nsISSLStatus.TLS_VERSION_1_2: + return "TLSv1.2"; + default: + DevToolsUtils.reportException("NetworkHelper.formatSecurityProtocol", "protocolVersion " + version + " is unknown."); + return "Unknown"; + } + }, + + /** + * Takes the securityState bitfield and returns reasons for weak connection + * as an array of strings. + * + * @param Number state + * nsITransportSecurityInfo.securityState. + * + * @return Array[String] + * List of weakness reasons. A subset of { cipher } where + * * cipher: The cipher suite is consireded to be weak (RC4). + */ + getReasonsForWeakness: function NH_getReasonsForWeakness(state) { + var wpl = Ci.nsIWebProgressListener; + + // If there's non-fatal security issues the request has STATE_IS_BROKEN + // flag set. See http://hg.mozilla.org/mozilla-central/file/44344099d119 + // /security/manager/ssl/nsNSSCallbacks.cpp#l1233 + var reasons = []; + + if (state & wpl.STATE_IS_BROKEN) { + var isCipher = state & wpl.STATE_USES_WEAK_CRYPTO; + + if (isCipher) { + reasons.push("cipher"); + } + + if (!isCipher) { + DevToolsUtils.reportException("NetworkHelper.getReasonsForWeakness", "STATE_IS_BROKEN without a known reason. Full state was: " + state); + } + } + + return reasons; + }, + + /** + * Parse a url's query string into its components + * + * @param string aQueryString + * The query part of a url + * @return array + * Array of query params {name, value} + */ + parseQueryString: function (aQueryString) { + // Make sure there's at least one param available. + // Be careful here, params don't necessarily need to have values, so + // no need to verify the existence of a "=". + if (!aQueryString) { + return; + } + + // Turn the params string into an array containing { name: value } tuples. + var paramsArray = aQueryString.replace(/^[?&]/, "").split("&").map(e => { + var param = e.split("="); + return { + name: param[0] ? NetworkHelper.convertToUnicode(unescape(param[0])) : "", + value: param[1] ? NetworkHelper.convertToUnicode(unescape(param[1])) : "" + }; + }); + + return paramsArray; + }, + + /** + * Helper for getting an nsIURL instance out of a string. + */ + nsIURL: function (aUrl) { + var aStore = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : gNSURLStore; + + if (aStore.has(aUrl)) { + return aStore.get(aUrl); + } + + var uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL); + aStore.set(aUrl, uri); + return uri; + } + }; + + for (var prop of Object.getOwnPropertyNames(NetworkHelper)) { + exports[prop] = NetworkHelper[prop]; + } + +/***/ }, +/* 74 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var _require = __webpack_require__(61); + + var Ci = _require.Ci; + var Cc = _require.Cc; + var Cr = _require.Cr; + var CC = _require.CC; + + var _require2 = __webpack_require__(30); + + var Services = _require2.Services; + + var _require3 = __webpack_require__(68); + + var dumpv = _require3.dumpv; + + var EventEmitter = __webpack_require__(60); + var promise = __webpack_require__(66); + + var IOUtil = Cc("@mozilla.org/io-util;1").getService(Ci.nsIIOUtil); + + var ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1", "nsIScriptableInputStream", "init"); + + var BUFFER_SIZE = 0x8000; + + /** + * This helper function (and its companion object) are used by bulk senders and + * receivers to read and write data in and out of other streams. Functions that + * make use of this tool are passed to callers when it is time to read or write + * bulk data. It is highly recommended to use these copier functions instead of + * the stream directly because the copier enforces the agreed upon length. + * Since bulk mode reuses an existing stream, the sender and receiver must write + * and read exactly the agreed upon amount of data, or else the entire transport + * will be left in a invalid state. Additionally, other methods of stream + * copying (such as NetUtil.asyncCopy) close the streams involved, which would + * terminate the debugging transport, and so it is avoided here. + * + * Overall, this *works*, but clearly the optimal solution would be able to just + * use the streams directly. If it were possible to fully implement + * nsIInputStream / nsIOutputStream in JS, wrapper streams could be created to + * enforce the length and avoid closing, and consumers could use familiar stream + * utilities like NetUtil.asyncCopy. + * + * The function takes two async streams and copies a precise number of bytes + * from one to the other. Copying begins immediately, but may complete at some + * future time depending on data size. Use the returned promise to know when + * it's complete. + * + * @param input nsIAsyncInputStream + * The stream to copy from. + * @param output nsIAsyncOutputStream + * The stream to copy to. + * @param length Integer + * The amount of data that needs to be copied. + * @return Promise + * The promise is resolved when copying completes or rejected if any + * (unexpected) errors occur. + */ + function copyStream(input, output, length) { + var copier = new StreamCopier(input, output, length); + return copier.copy(); + } + + function StreamCopier(input, output, length) { + EventEmitter.decorate(this); + this._id = StreamCopier._nextId++; + this.input = input; + // Save off the base output stream, since we know it's async as we've required + this.baseAsyncOutput = output; + if (IOUtil.outputStreamIsBuffered(output)) { + this.output = output; + } else { + this.output = Cc("@mozilla.org/network/buffered-output-stream;1").createInstance(Ci.nsIBufferedOutputStream); + this.output.init(output, BUFFER_SIZE); + } + this._length = length; + this._amountLeft = length; + this._deferred = promise.defer(); + + this._copy = this._copy.bind(this); + this._flush = this._flush.bind(this); + this._destroy = this._destroy.bind(this); + + // Copy promise's then method up to this object. + // Allows the copier to offer a promise interface for the simple succeed or + // fail scenarios, but also emit events (due to the EventEmitter) for other + // states, like progress. + this.then = this._deferred.promise.then.bind(this._deferred.promise); + this.then(this._destroy, this._destroy); + + // Stream ready callback starts as |_copy|, but may switch to |_flush| at end + // if flushing would block the output stream. + this._streamReadyCallback = this._copy; + } + StreamCopier._nextId = 0; + + StreamCopier.prototype = { + + copy: function () { + // Dispatch to the next tick so that it's possible to attach a progress + // event listener, even for extremely fast copies (like when testing). + Services.tm.currentThread.dispatch(() => { + try { + this._copy(); + } catch (e) { + this._deferred.reject(e); + } + }, 0); + return this; + }, + + _copy: function () { + var bytesAvailable = this.input.available(); + var amountToCopy = Math.min(bytesAvailable, this._amountLeft); + this._debug("Trying to copy: " + amountToCopy); + + var bytesCopied = void 0; + try { + bytesCopied = this.output.writeFrom(this.input, amountToCopy); + } catch (e) { + if (e.result == Cr.NS_BASE_STREAM_WOULD_BLOCK) { + this._debug("Base stream would block, will retry"); + this._debug("Waiting for output stream"); + this.baseAsyncOutput.asyncWait(this, 0, 0, Services.tm.currentThread); + return; + } else { + throw e; + } + } + + this._amountLeft -= bytesCopied; + this._debug("Copied: " + bytesCopied + ", Left: " + this._amountLeft); + this._emitProgress(); + + if (this._amountLeft === 0) { + this._debug("Copy done!"); + this._flush(); + return; + } + + this._debug("Waiting for input stream"); + this.input.asyncWait(this, 0, 0, Services.tm.currentThread); + }, + + _emitProgress: function () { + this.emit("progress", { + bytesSent: this._length - this._amountLeft, + totalBytes: this._length + }); + }, + + _flush: function () { + try { + this.output.flush(); + } catch (e) { + if (e.result == Cr.NS_BASE_STREAM_WOULD_BLOCK || e.result == Cr.NS_ERROR_FAILURE) { + this._debug("Flush would block, will retry"); + this._streamReadyCallback = this._flush; + this._debug("Waiting for output stream"); + this.baseAsyncOutput.asyncWait(this, 0, 0, Services.tm.currentThread); + return; + } else { + throw e; + } + } + this._deferred.resolve(); + }, + + _destroy: function () { + this._destroy = null; + this._copy = null; + this._flush = null; + this.input = null; + this.output = null; + }, + + // nsIInputStreamCallback + onInputStreamReady: function () { + this._streamReadyCallback(); + }, + + // nsIOutputStreamCallback + onOutputStreamReady: function () { + this._streamReadyCallback(); + }, + + _debug: function (msg) { + // Prefix logs with the copier ID, which makes logs much easier to + // understand when several copiers are running simultaneously + dumpv("Copier: " + this._id + " " + msg); + } + + }; + + /** + * Read from a stream, one byte at a time, up to the next |delimiter| + * character, but stopping if we've read |count| without finding it. Reading + * also terminates early if there are less than |count| bytes available on the + * stream. In that case, we only read as many bytes as the stream currently has + * to offer. + * TODO: This implementation could be removed if bug 984651 is fixed, which + * provides a native version of the same idea. + * @param stream nsIInputStream + * The input stream to read from. + * @param delimiter string + * The character we're trying to find. + * @param count integer + * The max number of characters to read while searching. + * @return string + * The data collected. If the delimiter was found, this string will + * end with it. + */ + function delimitedRead(stream, delimiter, count) { + dumpv("Starting delimited read for " + delimiter + " up to " + count + " bytes"); + + var scriptableStream = void 0; + if (stream.readBytes) { + scriptableStream = stream; + } else { + scriptableStream = new ScriptableInputStream(stream); + } + + var data = ""; + + // Don't exceed what's available on the stream + count = Math.min(count, stream.available()); + + if (count <= 0) { + return data; + } + + var char = void 0; + while (char !== delimiter && count > 0) { + char = scriptableStream.readBytes(1); + count--; + data += char; + } + + return data; + } + + module.exports = { + copyStream: copyStream, + delimitedRead: delimitedRead + }; + +/***/ }, +/* 75 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + /** + * Packets contain read / write functionality for the different packet types + * supported by the debugging protocol, so that a transport can focus on + * delivery and queue management without worrying too much about the specific + * packet types. + * + * They are intended to be "one use only", so a new packet should be + * instantiated for each incoming or outgoing packet. + * + * A complete Packet type should expose at least the following: + * * read(stream, scriptableStream) + * Called when the input stream has data to read + * * write(stream) + * Called when the output stream is ready to write + * * get done() + * Returns true once the packet is done being read / written + * * destroy() + * Called to clean up at the end of use + */ + + var _require = __webpack_require__(61); + + var Cc = _require.Cc; + var Ci = _require.Ci; + var Cu = _require.Cu; + + var DevToolsUtils = __webpack_require__(68); + var dumpn = DevToolsUtils.dumpn; + var dumpv = DevToolsUtils.dumpv; + + var StreamUtils = __webpack_require__(74); + var promise = __webpack_require__(66); + + /*DevToolsUtils.defineLazyGetter(this, "unicodeConverter", () => { + const unicodeConverter = Cc("@mozilla.org/intl/scriptableunicodeconverter") + .createInstance(Ci.nsIScriptableUnicodeConverter); + unicodeConverter.charset = "UTF-8"; + return unicodeConverter; + });*/ + var utf8 = __webpack_require__(76); + + // The transport's previous check ensured the header length did not exceed 20 + // characters. Here, we opt for the somewhat smaller, but still large limit of + // 1 TiB. + var PACKET_LENGTH_MAX = Math.pow(2, 40); + + /** + * A generic Packet processing object (extended by two subtypes below). + */ + function Packet(transport) { + this._transport = transport; + this._length = 0; + } + + /** + * Attempt to initialize a new Packet based on the incoming packet header we've + * received so far. We try each of the types in succession, trying JSON packets + * first since they are much more common. + * @param header string + * The packet header string to attempt parsing. + * @param transport DebuggerTransport + * The transport instance that will own the packet. + * @return Packet + * The parsed packet of the matching type, or null if no types matched. + */ + Packet.fromHeader = function (header, transport) { + return JSONPacket.fromHeader(header, transport) || BulkPacket.fromHeader(header, transport); + }; + + Packet.prototype = { + + get length() { + return this._length; + }, + + set length(length) { + if (length > PACKET_LENGTH_MAX) { + throw Error("Packet length " + length + " exceeds the max length of " + PACKET_LENGTH_MAX); + } + this._length = length; + }, + + destroy: function () { + this._transport = null; + } + + }; + + exports.Packet = Packet; + + /** + * With a JSON packet (the typical packet type sent via the transport), data is + * transferred as a JSON packet serialized into a string, with the string length + * prepended to the packet, followed by a colon ([length]:[packet]). The + * contents of the JSON packet are specified in the Remote Debugging Protocol + * specification. + * @param transport DebuggerTransport + * The transport instance that will own the packet. + */ + function JSONPacket(transport) { + Packet.call(this, transport); + this._data = ""; + this._done = false; + } + + /** + * Attempt to initialize a new JSONPacket based on the incoming packet header + * we've received so far. + * @param header string + * The packet header string to attempt parsing. + * @param transport DebuggerTransport + * The transport instance that will own the packet. + * @return JSONPacket + * The parsed packet, or null if it's not a match. + */ + JSONPacket.fromHeader = function (header, transport) { + var match = this.HEADER_PATTERN.exec(header); + + if (!match) { + return null; + } + + dumpv("Header matches JSON packet"); + var packet = new JSONPacket(transport); + packet.length = +match[1]; + return packet; + }; + + JSONPacket.HEADER_PATTERN = /^(\d+):$/; + + JSONPacket.prototype = Object.create(Packet.prototype); + + Object.defineProperty(JSONPacket.prototype, "object", { + /** + * Gets the object (not the serialized string) being read or written. + */ + get: function () { + return this._object; + }, + + /** + * Sets the object to be sent when write() is called. + */ + set: function (object) { + this._object = object; + var data = JSON.stringify(object); + this._data = data; + this.length = this._data.length; + } + }); + + JSONPacket.prototype.read = function (stream, scriptableStream) { + dumpv("Reading JSON packet"); + + // Read in more packet data. + this._readData(stream, scriptableStream); + + if (!this.done) { + // Don't have a complete packet yet. + return; + } + + var json = this._data; + try { + json = utf8.decode(json); + this._object = JSON.parse(json); + } catch (e) { + var msg = "Error parsing incoming packet: " + json + " (" + e + " - " + e.stack + ")"; + if (console.error) { + console.error(msg); + } + dumpn(msg); + return; + } + + this._transport._onJSONObjectReady(this._object); + }; + + JSONPacket.prototype._readData = function (stream, scriptableStream) { + if (!scriptableStream) { + scriptableStream = stream; + } + if (dumpv.wantVerbose) { + dumpv("Reading JSON data: _l: " + this.length + " dL: " + this._data.length + " sA: " + stream.available()); + } + var bytesToRead = Math.min(this.length - this._data.length, stream.available()); + this._data += scriptableStream.readBytes(bytesToRead); + this._done = this._data.length === this.length; + }; + + JSONPacket.prototype.write = function (stream) { + dumpv("Writing JSON packet"); + + if (this._outgoing === undefined) { + // Format the serialized packet to a buffer + this._outgoing = this.length + ":" + this._data; + } + + var written = stream.write(this._outgoing, this._outgoing.length); + this._outgoing = this._outgoing.slice(written); + this._done = !this._outgoing.length; + }; + + Object.defineProperty(JSONPacket.prototype, "done", { + get: function () { + return this._done; + } + }); + + JSONPacket.prototype.toString = function () { + return JSON.stringify(this._object, null, 2); + }; + + exports.JSONPacket = JSONPacket; + + /** + * With a bulk packet, data is transferred by temporarily handing over the + * transport's input or output stream to the application layer for writing data + * directly. This can be much faster for large data sets, and avoids various + * stages of copies and data duplication inherent in the JSON packet type. The + * bulk packet looks like: + * + * bulk [actor] [type] [length]:[data] + * + * The interpretation of the data portion depends on the kind of actor and the + * packet's type. See the Remote Debugging Protocol Stream Transport spec for + * more details. + * @param transport DebuggerTransport + * The transport instance that will own the packet. + */ + function BulkPacket(transport) { + Packet.call(this, transport); + this._done = false; + this._readyForWriting = promise.defer(); + } + + /** + * Attempt to initialize a new BulkPacket based on the incoming packet header + * we've received so far. + * @param header string + * The packet header string to attempt parsing. + * @param transport DebuggerTransport + * The transport instance that will own the packet. + * @return BulkPacket + * The parsed packet, or null if it's not a match. + */ + BulkPacket.fromHeader = function (header, transport) { + var match = this.HEADER_PATTERN.exec(header); + + if (!match) { + return null; + } + + dumpv("Header matches bulk packet"); + var packet = new BulkPacket(transport); + packet.header = { + actor: match[1], + type: match[2], + length: +match[3] + }; + return packet; + }; + + BulkPacket.HEADER_PATTERN = /^bulk ([^: ]+) ([^: ]+) (\d+):$/; + + BulkPacket.prototype = Object.create(Packet.prototype); + + BulkPacket.prototype.read = function (stream) { + dumpv("Reading bulk packet, handing off input stream"); + + // Temporarily pause monitoring of the input stream + this._transport.pauseIncoming(); + + var deferred = promise.defer(); + + this._transport._onBulkReadReady({ + actor: this.actor, + type: this.type, + length: this.length, + copyTo: output => { + dumpv("CT length: " + this.length); + var copying = StreamUtils.copyStream(stream, output, this.length); + deferred.resolve(copying); + return copying; + }, + stream: stream, + done: deferred + }); + + // Await the result of reading from the stream + deferred.promise.then(() => { + dumpv("onReadDone called, ending bulk mode"); + this._done = true; + this._transport.resumeIncoming(); + }, this._transport.close); + + // Ensure this is only done once + this.read = () => { + throw new Error("Tried to read() a BulkPacket's stream multiple times."); + }; + }; + + BulkPacket.prototype.write = function (stream) { + dumpv("Writing bulk packet"); + + if (this._outgoingHeader === undefined) { + dumpv("Serializing bulk packet header"); + // Format the serialized packet header to a buffer + this._outgoingHeader = "bulk " + this.actor + " " + this.type + " " + this.length + ":"; + } + + // Write the header, or whatever's left of it to write. + if (this._outgoingHeader.length) { + dumpv("Writing bulk packet header"); + var written = stream.write(this._outgoingHeader, this._outgoingHeader.length); + this._outgoingHeader = this._outgoingHeader.slice(written); + return; + } + + dumpv("Handing off output stream"); + + // Temporarily pause the monitoring of the output stream + this._transport.pauseOutgoing(); + + var deferred = promise.defer(); + + this._readyForWriting.resolve({ + copyFrom: input => { + dumpv("CF length: " + this.length); + var copying = StreamUtils.copyStream(input, stream, this.length); + deferred.resolve(copying); + return copying; + }, + stream: stream, + done: deferred + }); + + // Await the result of writing to the stream + deferred.promise.then(() => { + dumpv("onWriteDone called, ending bulk mode"); + this._done = true; + this._transport.resumeOutgoing(); + }, this._transport.close); + + // Ensure this is only done once + this.write = () => { + throw new Error("Tried to write() a BulkPacket's stream multiple times."); + }; + }; + + Object.defineProperty(BulkPacket.prototype, "streamReadyForWriting", { + get: function () { + return this._readyForWriting.promise; + } + }); + + Object.defineProperty(BulkPacket.prototype, "header", { + get: function () { + return { + actor: this.actor, + type: this.type, + length: this.length + }; + }, + + set: function (header) { + this.actor = header.actor; + this.type = header.type; + this.length = header.length; + } + }); + + Object.defineProperty(BulkPacket.prototype, "done", { + get: function () { + return this._done; + } + }); + + BulkPacket.prototype.toString = function () { + return "Bulk: " + JSON.stringify(this.header, null, 2); + }; + + exports.BulkPacket = BulkPacket; + + /** + * RawPacket is used to test the transport's error handling of malformed + * packets, by writing data directly onto the stream. + * @param transport DebuggerTransport + * The transport instance that will own the packet. + * @param data string + * The raw string to send out onto the stream. + */ + function RawPacket(transport, data) { + Packet.call(this, transport); + this._data = data; + this.length = data.length; + this._done = false; + } + + RawPacket.prototype = Object.create(Packet.prototype); + + RawPacket.prototype.read = function (stream) { + // This hasn't yet been needed for testing. + throw Error("Not implmented."); + }; + + RawPacket.prototype.write = function (stream) { + var written = stream.write(this._data, this._data.length); + this._data = this._data.slice(written); + this._done = !this._data.length; + }; + + Object.defineProperty(RawPacket.prototype, "done", { + get: function () { + return this._done; + } + }); + + exports.RawPacket = RawPacket; + +/***/ }, +/* 76 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/utf8js v2.0.0 by @mathias */ + ;(function (root) { + + // Detect free variables `exports` + var freeExports = typeof exports == 'object' && exports; + + // Detect free variable `module` + var freeModule = typeof module == 'object' && module && module.exports == freeExports && module; + + // Detect free variable `global`, from Node.js or Browserified code, + // and use it as `root` + var freeGlobal = typeof global == 'object' && global; + if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { + root = freeGlobal; + } + + /*--------------------------------------------------------------------------*/ + + var stringFromCharCode = String.fromCharCode; + + // Taken from https://mths.be/punycode + function ucs2decode(string) { + var output = []; + var counter = 0; + var length = string.length; + var value; + var extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { + // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + // Taken from https://mths.be/punycode + function ucs2encode(array) { + var length = array.length; + var index = -1; + var value; + var output = ''; + while (++index < length) { + value = array[index]; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + } + return output; + } + + function checkScalarValue(codePoint) { + if (codePoint >= 0xD800 && codePoint <= 0xDFFF) { + throw Error('Lone surrogate U+' + codePoint.toString(16).toUpperCase() + ' is not a scalar value'); + } + } + /*--------------------------------------------------------------------------*/ + + function createByte(codePoint, shift) { + return stringFromCharCode(codePoint >> shift & 0x3F | 0x80); + } + + function encodeCodePoint(codePoint) { + if ((codePoint & 0xFFFFFF80) == 0) { + // 1-byte sequence + return stringFromCharCode(codePoint); + } + var symbol = ''; + if ((codePoint & 0xFFFFF800) == 0) { + // 2-byte sequence + symbol = stringFromCharCode(codePoint >> 6 & 0x1F | 0xC0); + } else if ((codePoint & 0xFFFF0000) == 0) { + // 3-byte sequence + checkScalarValue(codePoint); + symbol = stringFromCharCode(codePoint >> 12 & 0x0F | 0xE0); + symbol += createByte(codePoint, 6); + } else if ((codePoint & 0xFFE00000) == 0) { + // 4-byte sequence + symbol = stringFromCharCode(codePoint >> 18 & 0x07 | 0xF0); + symbol += createByte(codePoint, 12); + symbol += createByte(codePoint, 6); + } + symbol += stringFromCharCode(codePoint & 0x3F | 0x80); + return symbol; + } + + function utf8encode(string) { + var codePoints = ucs2decode(string); + var length = codePoints.length; + var index = -1; + var codePoint; + var byteString = ''; + while (++index < length) { + codePoint = codePoints[index]; + byteString += encodeCodePoint(codePoint); + } + return byteString; + } + + /*--------------------------------------------------------------------------*/ + + function readContinuationByte() { + if (byteIndex >= byteCount) { + throw Error('Invalid byte index'); + } + + var continuationByte = byteArray[byteIndex] & 0xFF; + byteIndex++; + + if ((continuationByte & 0xC0) == 0x80) { + return continuationByte & 0x3F; + } + + // If we end up here, it’s not a continuation byte + throw Error('Invalid continuation byte'); + } + + function decodeSymbol() { + var byte1; + var byte2; + var byte3; + var byte4; + var codePoint; + + if (byteIndex > byteCount) { + throw Error('Invalid byte index'); + } + + if (byteIndex == byteCount) { + return false; + } + + // Read first byte + byte1 = byteArray[byteIndex] & 0xFF; + byteIndex++; + + // 1-byte sequence (no continuation bytes) + if ((byte1 & 0x80) == 0) { + return byte1; + } + + // 2-byte sequence + if ((byte1 & 0xE0) == 0xC0) { + var byte2 = readContinuationByte(); + codePoint = (byte1 & 0x1F) << 6 | byte2; + if (codePoint >= 0x80) { + return codePoint; + } else { + throw Error('Invalid continuation byte'); + } + } + + // 3-byte sequence (may include unpaired surrogates) + if ((byte1 & 0xF0) == 0xE0) { + byte2 = readContinuationByte(); + byte3 = readContinuationByte(); + codePoint = (byte1 & 0x0F) << 12 | byte2 << 6 | byte3; + if (codePoint >= 0x0800) { + checkScalarValue(codePoint); + return codePoint; + } else { + throw Error('Invalid continuation byte'); + } + } + + // 4-byte sequence + if ((byte1 & 0xF8) == 0xF0) { + byte2 = readContinuationByte(); + byte3 = readContinuationByte(); + byte4 = readContinuationByte(); + codePoint = (byte1 & 0x0F) << 0x12 | byte2 << 0x0C | byte3 << 0x06 | byte4; + if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) { + return codePoint; + } + } + + throw Error('Invalid UTF-8 detected'); + } + + var byteArray; + var byteCount; + var byteIndex; + function utf8decode(byteString) { + byteArray = ucs2decode(byteString); + byteCount = byteArray.length; + byteIndex = 0; + var codePoints = []; + var tmp; + while ((tmp = decodeSymbol()) !== false) { + codePoints.push(tmp); + } + return ucs2encode(codePoints); + } + + /*--------------------------------------------------------------------------*/ + + var utf8 = { + 'version': '2.0.0', + 'encode': utf8encode, + 'decode': utf8decode + }; + + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if (true) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = function () { + return utf8; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (freeExports && !freeExports.nodeType) { + if (freeModule) { + // in Node.js or RingoJS v0.8.0+ + freeModule.exports = utf8; + } else { + // in Narwhal or RingoJS v0.7.0- + var object = {}; + var hasOwnProperty = object.hasOwnProperty; + for (var key in utf8) { + hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]); + } + } + } else { + // in Rhino or a web browser + root.utf8 = utf8; + } + })(this); + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(77)(module), (function() { return this; }()))) + +/***/ }, +/* 77 */ +/***/ function(module, exports) { + + module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + module.children = []; + module.webpackPolyfill = 1; + } + return module; + } + + +/***/ }, +/* 78 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/utf8js v2.0.0 by @mathias */ + ;(function (root) { + + // Detect free variables `exports` + var freeExports = typeof exports == 'object' && exports; + + // Detect free variable `module` + var freeModule = typeof module == 'object' && module && module.exports == freeExports && module; + + // Detect free variable `global`, from Node.js or Browserified code, + // and use it as `root` + var freeGlobal = typeof global == 'object' && global; + if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { + root = freeGlobal; + } + + /*--------------------------------------------------------------------------*/ + + var stringFromCharCode = String.fromCharCode; + + // Taken from https://mths.be/punycode + function ucs2decode(string) { + var output = []; + var counter = 0; + var length = string.length; + var value; + var extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { + // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + // Taken from https://mths.be/punycode + function ucs2encode(array) { + var length = array.length; + var index = -1; + var value; + var output = ''; + while (++index < length) { + value = array[index]; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + } + return output; + } + + function checkScalarValue(codePoint) { + if (codePoint >= 0xD800 && codePoint <= 0xDFFF) { + throw Error('Lone surrogate U+' + codePoint.toString(16).toUpperCase() + ' is not a scalar value'); + } + } + /*--------------------------------------------------------------------------*/ + + function createByte(codePoint, shift) { + return stringFromCharCode(codePoint >> shift & 0x3F | 0x80); + } + + function encodeCodePoint(codePoint) { + if ((codePoint & 0xFFFFFF80) == 0) { + // 1-byte sequence + return stringFromCharCode(codePoint); + } + var symbol = ''; + if ((codePoint & 0xFFFFF800) == 0) { + // 2-byte sequence + symbol = stringFromCharCode(codePoint >> 6 & 0x1F | 0xC0); + } else if ((codePoint & 0xFFFF0000) == 0) { + // 3-byte sequence + checkScalarValue(codePoint); + symbol = stringFromCharCode(codePoint >> 12 & 0x0F | 0xE0); + symbol += createByte(codePoint, 6); + } else if ((codePoint & 0xFFE00000) == 0) { + // 4-byte sequence + symbol = stringFromCharCode(codePoint >> 18 & 0x07 | 0xF0); + symbol += createByte(codePoint, 12); + symbol += createByte(codePoint, 6); + } + symbol += stringFromCharCode(codePoint & 0x3F | 0x80); + return symbol; + } + + function utf8encode(string) { + var codePoints = ucs2decode(string); + var length = codePoints.length; + var index = -1; + var codePoint; + var byteString = ''; + while (++index < length) { + codePoint = codePoints[index]; + byteString += encodeCodePoint(codePoint); + } + return byteString; + } + + /*--------------------------------------------------------------------------*/ + + function readContinuationByte() { + if (byteIndex >= byteCount) { + throw Error('Invalid byte index'); + } + + var continuationByte = byteArray[byteIndex] & 0xFF; + byteIndex++; + + if ((continuationByte & 0xC0) == 0x80) { + return continuationByte & 0x3F; + } + + // If we end up here, it’s not a continuation byte + throw Error('Invalid continuation byte'); + } + + function decodeSymbol() { + var byte1; + var byte2; + var byte3; + var byte4; + var codePoint; + + if (byteIndex > byteCount) { + throw Error('Invalid byte index'); + } + + if (byteIndex == byteCount) { + return false; + } + + // Read first byte + byte1 = byteArray[byteIndex] & 0xFF; + byteIndex++; + + // 1-byte sequence (no continuation bytes) + if ((byte1 & 0x80) == 0) { + return byte1; + } + + // 2-byte sequence + if ((byte1 & 0xE0) == 0xC0) { + var byte2 = readContinuationByte(); + codePoint = (byte1 & 0x1F) << 6 | byte2; + if (codePoint >= 0x80) { + return codePoint; + } else { + throw Error('Invalid continuation byte'); + } + } + + // 3-byte sequence (may include unpaired surrogates) + if ((byte1 & 0xF0) == 0xE0) { + byte2 = readContinuationByte(); + byte3 = readContinuationByte(); + codePoint = (byte1 & 0x0F) << 12 | byte2 << 6 | byte3; + if (codePoint >= 0x0800) { + checkScalarValue(codePoint); + return codePoint; + } else { + throw Error('Invalid continuation byte'); + } + } + + // 4-byte sequence + if ((byte1 & 0xF8) == 0xF0) { + byte2 = readContinuationByte(); + byte3 = readContinuationByte(); + byte4 = readContinuationByte(); + codePoint = (byte1 & 0x0F) << 0x12 | byte2 << 0x0C | byte3 << 0x06 | byte4; + if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) { + return codePoint; + } + } + + throw Error('Invalid UTF-8 detected'); + } + + var byteArray; + var byteCount; + var byteIndex; + function utf8decode(byteString) { + byteArray = ucs2decode(byteString); + byteCount = byteArray.length; + byteIndex = 0; + var codePoints = []; + var tmp; + while ((tmp = decodeSymbol()) !== false) { + codePoints.push(tmp); + } + return ucs2encode(codePoints); + } + + /*--------------------------------------------------------------------------*/ + + var utf8 = { + 'version': '2.0.0', + 'encode': utf8encode, + 'decode': utf8decode + }; + + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if (true) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = function () { + return utf8; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (freeExports && !freeExports.nodeType) { + if (freeModule) { + // in Node.js or RingoJS v0.8.0+ + freeModule.exports = utf8; + } else { + // in Narwhal or RingoJS v0.7.0- + var object = {}; + var hasOwnProperty = object.hasOwnProperty; + for (var key in utf8) { + hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]); + } + } + } else { + // in Rhino or a web browser + root.utf8 = utf8; + } + })(this); + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(77)(module), (function() { return this; }()))) + +/***/ }, +/* 79 */ +/***/ function(module, exports, __webpack_require__) { + + function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + + /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var _require = __webpack_require__(61); + + var Ci = _require.Ci; + var Cu = _require.Cu; + var components = _require.components; + + var _require2 = __webpack_require__(30); + + var Services = _require2.Services; + + var DevToolsUtils = __webpack_require__(68); + + // WARNING I swapped the sync one for the async one here + // const promise = require("resource://devtools/shared/deprecated-sync-thenables.js", {}).Promise; + var promise = __webpack_require__(66); + + var events = __webpack_require__(80); + + var _require3 = __webpack_require__(82); + + var WebConsoleClient = _require3.WebConsoleClient; + /* const { DebuggerSocket } = require("../shared/security/socket");*/ + /* const Authentication = require("../shared/security/auth");*/ + + var noop = () => {}; + + /** + * TODO: Get rid of this API in favor of EventTarget (bug 1042642) + * + * Add simple event notification to a prototype object. Any object that has + * some use for event notifications or the observer pattern in general can be + * augmented with the necessary facilities by passing its prototype to this + * function. + * + * @param aProto object + * The prototype object that will be modified. + */ + function eventSource(aProto) { + /** + * Add a listener to the event source for a given event. + * + * @param aName string + * The event to listen for. + * @param aListener function + * Called when the event is fired. If the same listener + * is added more than once, it will be called once per + * addListener call. + */ + aProto.addListener = function (aName, aListener) { + if (typeof aListener != "function") { + throw TypeError("Listeners must be functions."); + } + + if (!this._listeners) { + this._listeners = {}; + } + + this._getListeners(aName).push(aListener); + }; + + /** + * Add a listener to the event source for a given event. The + * listener will be removed after it is called for the first time. + * + * @param aName string + * The event to listen for. + * @param aListener function + * Called when the event is fired. + */ + aProto.addOneTimeListener = function (aName, aListener) { + var _this = this; + + var l = function () { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + _this.removeListener(aName, l); + aListener.apply(null, args); + }; + this.addListener(aName, l); + }; + + /** + * Remove a listener from the event source previously added with + * addListener(). + * + * @param aName string + * The event name used during addListener to add the listener. + * @param aListener function + * The callback to remove. If addListener was called multiple + * times, all instances will be removed. + */ + aProto.removeListener = function (aName, aListener) { + if (!this._listeners || aListener && !this._listeners[aName]) { + return; + } + + if (!aListener) { + this._listeners[aName] = []; + } else { + this._listeners[aName] = this._listeners[aName].filter(function (l) { + return l != aListener; + }); + } + }; + + /** + * Returns the listeners for the specified event name. If none are defined it + * initializes an empty list and returns that. + * + * @param aName string + * The event name. + */ + aProto._getListeners = function (aName) { + if (aName in this._listeners) { + return this._listeners[aName]; + } + this._listeners[aName] = []; + return this._listeners[aName]; + }; + + /** + * Notify listeners of an event. + * + * @param aName string + * The event to fire. + * @param arguments + * All arguments will be passed along to the listeners, + * including the name argument. + */ + aProto.emit = function () { + if (!this._listeners) { + return; + } + + var name = arguments[0]; + var listeners = this._getListeners(name).slice(0); + + for (var listener of listeners) { + try { + listener.apply(null, arguments); + } catch (e) { + // Prevent a bad listener from interfering with the others. + DevToolsUtils.reportException("notify event '" + name + "'", e); + } + } + }; + } + + /** + * Set of protocol messages that affect thread state, and the + * state the actor is in after each message. + */ + var ThreadStateTypes = { + "paused": "paused", + "resumed": "attached", + "detached": "detached" + }; + + /** + * Set of protocol messages that are sent by the server without a prior request + * by the client. + */ + var UnsolicitedNotifications = { + "consoleAPICall": "consoleAPICall", + "eventNotification": "eventNotification", + "fileActivity": "fileActivity", + "lastPrivateContextExited": "lastPrivateContextExited", + "logMessage": "logMessage", + "networkEvent": "networkEvent", + "networkEventUpdate": "networkEventUpdate", + "newGlobal": "newGlobal", + "newScript": "newScript", + "tabDetached": "tabDetached", + "tabListChanged": "tabListChanged", + "reflowActivity": "reflowActivity", + "addonListChanged": "addonListChanged", + "workerListChanged": "workerListChanged", + "serviceWorkerRegistrationListChanged": "serviceWorkerRegistrationList", + "tabNavigated": "tabNavigated", + "frameUpdate": "frameUpdate", + "pageError": "pageError", + "documentLoad": "documentLoad", + "enteredFrame": "enteredFrame", + "exitedFrame": "exitedFrame", + "appOpen": "appOpen", + "appClose": "appClose", + "appInstall": "appInstall", + "appUninstall": "appUninstall", + "evaluationResult": "evaluationResult", + "newSource": "newSource", + "updatedSource": "updatedSource" + }; + + /** + * Set of pause types that are sent by the server and not as an immediate + * response to a client request. + */ + var UnsolicitedPauses = { + "resumeLimit": "resumeLimit", + "debuggerStatement": "debuggerStatement", + "breakpoint": "breakpoint", + "DOMEvent": "DOMEvent", + "watchpoint": "watchpoint", + "exception": "exception" + }; + + /** + * Creates a client for the remote debugging protocol server. This client + * provides the means to communicate with the server and exchange the messages + * required by the protocol in a traditional JavaScript API. + */ + var DebuggerClient = exports.DebuggerClient = function (aTransport) { + this._transport = aTransport; + this._transport.hooks = this; + + // Map actor ID to client instance for each actor type. + this._clients = new Map(); + + this._pendingRequests = new Map(); + this._activeRequests = new Map(); + this._eventsEnabled = true; + + this.traits = {}; + + this.request = this.request.bind(this); + this.localTransport = this._transport.onOutputStreamReady === undefined; + + /* + * As the first thing on the connection, expect a greeting packet from + * the connection's root actor. + */ + this.mainRoot = null; + this.expectReply("root", aPacket => { + this.mainRoot = new RootClient(this, aPacket); + this.emit("connected", aPacket.applicationType, aPacket.traits); + }); + }; + + /** + * A declarative helper for defining methods that send requests to the server. + * + * @param aPacketSkeleton + * The form of the packet to send. Can specify fields to be filled from + * the parameters by using the |args| function. + * @param telemetry + * The unique suffix of the telemetry histogram id. + * @param before + * The function to call before sending the packet. Is passed the packet, + * and the return value is used as the new packet. The |this| context is + * the instance of the client object we are defining a method for. + * @param after + * The function to call after the response is received. It is passed the + * response, and the return value is considered the new response that + * will be passed to the callback. The |this| context is the instance of + * the client object we are defining a method for. + * @return Request + * The `Request` object that is a Promise object and resolves once + * we receive the response. (See request method for more details) + */ + DebuggerClient.requester = function (aPacketSkeleton) { + var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var telemetry = config.telemetry; + var before = config.before; + var after = config.after; + + return DevToolsUtils.makeInfallible(function () { + for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + var histogram = void 0, + startTime = void 0; + if (telemetry) { + var transportType = this._transport.onOutputStreamReady === undefined ? "LOCAL_" : "REMOTE_"; + var histogramId = "DEVTOOLS_DEBUGGER_RDP_" + transportType + telemetry + "_MS"; + histogram = Services.telemetry.getHistogramById(histogramId); + startTime = +new Date(); + } + var outgoingPacket = { + to: aPacketSkeleton.to || this.actor + }; + + var maxPosition = -1; + for (var k of Object.keys(aPacketSkeleton)) { + if (aPacketSkeleton[k] instanceof DebuggerClient.Argument) { + var position = aPacketSkeleton[k].position; + + outgoingPacket[k] = aPacketSkeleton[k].getArgument(args); + maxPosition = Math.max(position, maxPosition); + } else { + outgoingPacket[k] = aPacketSkeleton[k]; + } + } + + if (before) { + outgoingPacket = before.call(this, outgoingPacket); + } + + return this.request(outgoingPacket, DevToolsUtils.makeInfallible(aResponse => { + if (after) { + var _aResponse = aResponse; + var from = _aResponse.from; + + aResponse = after.call(this, aResponse); + if (!aResponse.from) { + aResponse.from = from; + } + } + + // The callback is always the last parameter. + var thisCallback = args[maxPosition + 1]; + if (thisCallback) { + thisCallback(aResponse); + } + + if (histogram) { + histogram.add(+new Date() - startTime); + } + }, "DebuggerClient.requester request callback")); + }, "DebuggerClient.requester"); + }; + + function args(aPos) { + return new DebuggerClient.Argument(aPos); + } + + DebuggerClient.Argument = function (aPosition) { + this.position = aPosition; + }; + + DebuggerClient.Argument.prototype.getArgument = function (aParams) { + if (!(this.position in aParams)) { + throw new Error("Bad index into params: " + this.position); + } + return aParams[this.position]; + }; + + // Expose these to save callers the trouble of importing DebuggerSocket + DebuggerClient.socketConnect = function (options) { + // Defined here instead of just copying the function to allow lazy-load + return DebuggerSocket.connect(options); + }; + DevToolsUtils.defineLazyGetter(DebuggerClient, "Authenticators", () => { + return Authentication.Authenticators; + }); + DevToolsUtils.defineLazyGetter(DebuggerClient, "AuthenticationResult", () => { + return Authentication.AuthenticationResult; + }); + + DebuggerClient.prototype = { + /** + * Connect to the server and start exchanging protocol messages. + * + * @param aOnConnected function + * If specified, will be called when the greeting packet is + * received from the debugging server. + * + * @return Promise + * Resolves once connected with an array whose first element + * is the application type, by default "browser", and the second + * element is the traits object (help figure out the features + * and behaviors of the server we connect to. See RootActor). + */ + connect: function (aOnConnected) { + return Promise.race([new Promise((resolve, reject) => { + this.emit("connect"); + + // Also emit the event on the |DebuggerClient| object (not on the instance), + // so it's possible to track all instances. + events.emit(DebuggerClient, "connect", this); + + this.addOneTimeListener("connected", (aName, aApplicationType, aTraits) => { + this.traits = aTraits; + if (aOnConnected) { + aOnConnected(aApplicationType, aTraits); + } + resolve([aApplicationType, aTraits]); + }); + + this._transport.ready(); + }), new Promise((resolve, reject) => { + setTimeout(() => reject(new Error("Connect timeout error")), 6000); + })]); + }, + + /** + * Shut down communication with the debugging server. + * + * @param aOnClosed function + * If specified, will be called when the debugging connection + * has been closed. + */ + close: function (aOnClosed) { + // Disable detach event notifications, because event handlers will be in a + // cleared scope by the time they run. + this._eventsEnabled = false; + + var cleanup = () => { + this._transport.close(); + this._transport = null; + }; + + // If the connection is already closed, + // there is no need to detach client + // as we won't be able to send any message. + if (this._closed) { + cleanup(); + if (aOnClosed) { + aOnClosed(); + } + return; + } + + if (aOnClosed) { + this.addOneTimeListener("closed", function (aEvent) { + aOnClosed(); + }); + } + + // Call each client's `detach` method by calling + // lastly registered ones first to give a chance + // to detach child clients first. + var clients = [].concat(_toConsumableArray(this._clients.values())); + this._clients.clear(); + var detachClients = () => { + var client = clients.pop(); + if (!client) { + // All clients detached. + cleanup(); + return; + } + if (client.detach) { + client.detach(detachClients); + return; + } + detachClients(); + }; + detachClients(); + }, + + /* + * This function exists only to preserve DebuggerClient's interface; + * new code should say 'client.mainRoot.listTabs()'. + */ + listTabs: function (aOnResponse) { + return this.mainRoot.listTabs(aOnResponse); + }, + + /* + * This function exists only to preserve DebuggerClient's interface; + * new code should say 'client.mainRoot.listAddons()'. + */ + listAddons: function (aOnResponse) { + return this.mainRoot.listAddons(aOnResponse); + }, + + getTab: function (aFilter) { + return this.mainRoot.getTab(aFilter); + }, + + /** + * Attach to a tab actor. + * + * @param string aTabActor + * The actor ID for the tab to attach. + * @param function aOnResponse + * Called with the response packet and a TabClient + * (which will be undefined on error). + */ + attachTab: function (aTabActor) { + var _this2 = this; + + var aOnResponse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; + + if (this._clients.has(aTabActor)) { + var _ret = function () { + var cachedTab = _this2._clients.get(aTabActor); + var cachedResponse = { + cacheDisabled: cachedTab.cacheDisabled, + javascriptEnabled: cachedTab.javascriptEnabled, + traits: cachedTab.traits + }; + DevToolsUtils.executeSoon(() => aOnResponse(cachedResponse, cachedTab)); + return { + v: promise.resolve([cachedResponse, cachedTab]) + }; + }(); + + if (typeof _ret === "object") return _ret.v; + } + + var packet = { + to: aTabActor, + type: "attach" + }; + return this.request(packet).then(aResponse => { + var tabClient = void 0; + if (!aResponse.error) { + tabClient = new TabClient(this, aResponse); + this.registerClient(tabClient); + } + aOnResponse(aResponse, tabClient); + return [aResponse, tabClient]; + }); + }, + + attachWorker: function DC_attachWorker(aWorkerActor) { + var aOnResponse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; + + var workerClient = this._clients.get(aWorkerActor); + if (workerClient !== undefined) { + var _ret2 = function () { + var response = { + from: workerClient.actor, + type: "attached", + url: workerClient.url + }; + DevToolsUtils.executeSoon(() => aOnResponse(response, workerClient)); + return { + v: promise.resolve([response, workerClient]) + }; + }(); + + if (typeof _ret2 === "object") return _ret2.v; + } + + return this.request({ to: aWorkerActor, type: "attach" }).then(aResponse => { + if (aResponse.error) { + aOnResponse(aResponse, null); + return [aResponse, null]; + } + + var workerClient = new WorkerClient(this, aResponse); + this.registerClient(workerClient); + aOnResponse(aResponse, workerClient); + return [aResponse, workerClient]; + }); + }, + + /** + * Attach to an addon actor. + * + * @param string aAddonActor + * The actor ID for the addon to attach. + * @param function aOnResponse + * Called with the response packet and a AddonClient + * (which will be undefined on error). + */ + attachAddon: function DC_attachAddon(aAddonActor) { + var aOnResponse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; + + var packet = { + to: aAddonActor, + type: "attach" + }; + return this.request(packet).then(aResponse => { + var addonClient = void 0; + if (!aResponse.error) { + addonClient = new AddonClient(this, aAddonActor); + this.registerClient(addonClient); + this.activeAddon = addonClient; + } + aOnResponse(aResponse, addonClient); + return [aResponse, addonClient]; + }); + }, + + /** + * Attach to a Web Console actor. + * + * @param string aConsoleActor + * The ID for the console actor to attach to. + * @param array aListeners + * The console listeners you want to start. + * @param function aOnResponse + * Called with the response packet and a WebConsoleClient + * instance (which will be undefined on error). + */ + attachConsole: function (aConsoleActor, aListeners) { + var aOnResponse = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : noop; + + var packet = { + to: aConsoleActor, + type: "startListeners", + listeners: aListeners + }; + + return this.request(packet).then(aResponse => { + var consoleClient = void 0; + if (!aResponse.error) { + if (this._clients.has(aConsoleActor)) { + consoleClient = this._clients.get(aConsoleActor); + } else { + consoleClient = new WebConsoleClient(this, aResponse); + this.registerClient(consoleClient); + } + } + aOnResponse(aResponse, consoleClient); + return [aResponse, consoleClient]; + }); + }, + + /** + * Attach to a global-scoped thread actor for chrome debugging. + * + * @param string aThreadActor + * The actor ID for the thread to attach. + * @param function aOnResponse + * Called with the response packet and a ThreadClient + * (which will be undefined on error). + * @param object aOptions + * Configuration options. + * - useSourceMaps: whether to use source maps or not. + */ + attachThread: function (aThreadActor) { + var _this3 = this; + + var aOnResponse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; + var aOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + if (this._clients.has(aThreadActor)) { + var _ret3 = function () { + var client = _this3._clients.get(aThreadActor); + DevToolsUtils.executeSoon(() => aOnResponse({}, client)); + return { + v: promise.resolve([{}, client]) + }; + }(); + + if (typeof _ret3 === "object") return _ret3.v; + } + + var packet = { + to: aThreadActor, + type: "attach", + options: aOptions + }; + return this.request(packet).then(aResponse => { + if (!aResponse.error) { + var threadClient = new ThreadClient(this, aThreadActor); + this.registerClient(threadClient); + } + aOnResponse(aResponse, threadClient); + return [aResponse, threadClient]; + }); + }, + + /** + * Attach to a trace actor. + * + * @param string aTraceActor + * The actor ID for the tracer to attach. + * @param function aOnResponse + * Called with the response packet and a TraceClient + * (which will be undefined on error). + */ + attachTracer: function (aTraceActor) { + var _this4 = this; + + var aOnResponse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; + + if (this._clients.has(aTraceActor)) { + var _ret4 = function () { + var client = _this4._clients.get(aTraceActor); + DevToolsUtils.executeSoon(() => aOnResponse({}, client)); + return { + v: promise.resolve([{}, client]) + }; + }(); + + if (typeof _ret4 === "object") return _ret4.v; + } + + var packet = { + to: aTraceActor, + type: "attach" + }; + return this.request(packet).then(aResponse => { + if (!aResponse.error) { + var traceClient = new TraceClient(this, aTraceActor); + this.registerClient(traceClient); + } + aOnResponse(aResponse, traceClient); + return [aResponse, traceClient]; + }); + }, + + /** + * Fetch the ChromeActor for the main process or ChildProcessActor for a + * a given child process ID. + * + * @param number aId + * The ID for the process to attach (returned by `listProcesses`). + * Connected to the main process if omitted, or is 0. + */ + getProcess: function (aId) { + var packet = { + to: "root", + type: "getProcess" + }; + if (typeof aId == "number") { + packet.id = aId; + } + return this.request(packet); + }, + + /** + * Release an object actor. + * + * @param string aActor + * The actor ID to send the request to. + * @param aOnResponse function + * If specified, will be called with the response packet when + * debugging server responds. + */ + release: DebuggerClient.requester({ + to: args(0), + type: "release" + }, { + telemetry: "RELEASE" + }), + + /** + * Send a request to the debugging server. + * + * @param aRequest object + * A JSON packet to send to the debugging server. + * @param aOnResponse function + * If specified, will be called with the JSON response packet when + * debugging server responds. + * @return Request + * This object emits a number of events to allow you to respond to + * different parts of the request lifecycle. + * It is also a Promise object, with a `then` method, that is resolved + * whenever a JSON or a Bulk response is received; and is rejected + * if the response is an error. + * Note: This return value can be ignored if you are using JSON alone, + * because the callback provided in |aOnResponse| will be bound to the + * "json-reply" event automatically. + * + * Events emitted: + * * json-reply: The server replied with a JSON packet, which is + * passed as event data. + * * bulk-reply: The server replied with bulk data, which you can read + * using the event data object containing: + * * actor: Name of actor that received the packet + * * type: Name of actor's method that was called on receipt + * * length: Size of the data to be read + * * stream: This input stream should only be used directly if you + * can ensure that you will read exactly |length| bytes + * and will not close the stream when reading is complete + * * done: If you use the stream directly (instead of |copyTo| + * below), you must signal completion by resolving / + * rejecting this deferred. If it's rejected, the + * transport will be closed. If an Error is supplied as a + * rejection value, it will be logged via |dumpn|. If you + * do use |copyTo|, resolving is taken care of for you + * when copying completes. + * * copyTo: A helper function for getting your data out of the + * stream that meets the stream handling requirements + * above, and has the following signature: + * @param output nsIAsyncOutputStream + * The stream to copy to. + * @return Promise + * The promise is resolved when copying completes or + * rejected if any (unexpected) errors occur. + * This object also emits "progress" events for each chunk + * that is copied. See stream-utils.js. + */ + request: function (aRequest, aOnResponse) { + if (!this.mainRoot) { + throw Error("Have not yet received a hello packet from the server."); + } + var type = aRequest.type || ""; + if (!aRequest.to) { + throw Error("'" + type + "' request packet has no destination."); + } + if (this._closed) { + var msg = "'" + type + "' request packet to " + "'" + aRequest.to + "' " + "can't be sent as the connection is closed."; + var resp = { error: "connectionClosed", message: msg }; + if (aOnResponse) { + aOnResponse(resp); + } + return promise.reject(resp); + } + + var request = new Request(aRequest); + request.format = "json"; + request.stack = components.stack; + if (aOnResponse) { + request.on("json-reply", aOnResponse); + } + + this._sendOrQueueRequest(request); + + // Implement a Promise like API on the returned object + // that resolves/rejects on request response + var deferred = promise.defer(); + function listenerJson(resp) { + request.off("json-reply", listenerJson); + request.off("bulk-reply", listenerBulk); + if (resp.error) { + deferred.reject(resp); + } else { + deferred.resolve(resp); + } + } + function listenerBulk(resp) { + request.off("json-reply", listenerJson); + request.off("bulk-reply", listenerBulk); + deferred.resolve(resp); + } + request.on("json-reply", listenerJson); + request.on("bulk-reply", listenerBulk); + request.then = deferred.promise.then.bind(deferred.promise); + + return request; + }, + + /** + * Transmit streaming data via a bulk request. + * + * This method initiates the bulk send process by queuing up the header data. + * The caller receives eventual access to a stream for writing. + * + * Since this opens up more options for how the server might respond (it could + * send back either JSON or bulk data), and the returned Request object emits + * events for different stages of the request process that you may want to + * react to. + * + * @param request Object + * This is modeled after the format of JSON packets above, but does not + * actually contain the data, but is instead just a routing header: + * * actor: Name of actor that will receive the packet + * * type: Name of actor's method that should be called on receipt + * * length: Size of the data to be sent + * @return Request + * This object emits a number of events to allow you to respond to + * different parts of the request lifecycle. + * + * Events emitted: + * * bulk-send-ready: Ready to send bulk data to the server, using the + * event data object containing: + * * stream: This output stream should only be used directly if + * you can ensure that you will write exactly |length| + * bytes and will not close the stream when writing is + * complete + * * done: If you use the stream directly (instead of |copyFrom| + * below), you must signal completion by resolving / + * rejecting this deferred. If it's rejected, the + * transport will be closed. If an Error is supplied as + * a rejection value, it will be logged via |dumpn|. If + * you do use |copyFrom|, resolving is taken care of for + * you when copying completes. + * * copyFrom: A helper function for getting your data onto the + * stream that meets the stream handling requirements + * above, and has the following signature: + * @param input nsIAsyncInputStream + * The stream to copy from. + * @return Promise + * The promise is resolved when copying completes or + * rejected if any (unexpected) errors occur. + * This object also emits "progress" events for each chunk + * that is copied. See stream-utils.js. + * * json-reply: The server replied with a JSON packet, which is + * passed as event data. + * * bulk-reply: The server replied with bulk data, which you can read + * using the event data object containing: + * * actor: Name of actor that received the packet + * * type: Name of actor's method that was called on receipt + * * length: Size of the data to be read + * * stream: This input stream should only be used directly if you + * can ensure that you will read exactly |length| bytes + * and will not close the stream when reading is complete + * * done: If you use the stream directly (instead of |copyTo| + * below), you must signal completion by resolving / + * rejecting this deferred. If it's rejected, the + * transport will be closed. If an Error is supplied as a + * rejection value, it will be logged via |dumpn|. If you + * do use |copyTo|, resolving is taken care of for you + * when copying completes. + * * copyTo: A helper function for getting your data out of the + * stream that meets the stream handling requirements + * above, and has the following signature: + * @param output nsIAsyncOutputStream + * The stream to copy to. + * @return Promise + * The promise is resolved when copying completes or + * rejected if any (unexpected) errors occur. + * This object also emits "progress" events for each chunk + * that is copied. See stream-utils.js. + */ + startBulkRequest: function (request) { + if (!this.traits.bulk) { + throw Error("Server doesn't support bulk transfers"); + } + if (!this.mainRoot) { + throw Error("Have not yet received a hello packet from the server."); + } + if (!request.type) { + throw Error("Bulk packet is missing the required 'type' field."); + } + if (!request.actor) { + throw Error("'" + request.type + "' bulk packet has no destination."); + } + if (!request.length) { + throw Error("'" + request.type + "' bulk packet has no length."); + } + + request = new Request(request); + request.format = "bulk"; + + this._sendOrQueueRequest(request); + + return request; + }, + + /** + * If a new request can be sent immediately, do so. Otherwise, queue it. + */ + _sendOrQueueRequest(request) { + var actor = request.actor; + if (!this._activeRequests.has(actor)) { + this._sendRequest(request); + } else { + this._queueRequest(request); + } + }, + + /** + * Send a request. + * @throws Error if there is already an active request in flight for the same + * actor. + */ + _sendRequest(request) { + var actor = request.actor; + this.expectReply(actor, request); + + if (request.format === "json") { + this._transport.send(request.request); + return false; + } + + this._transport.startBulkSend(request.request).then(function () { + for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + args[_key3] = arguments[_key3]; + } + + request.emit.apply(request, ["bulk-send-ready"].concat(args)); + }); + }, + + /** + * Queue a request to be sent later. Queues are only drained when an in + * flight request to a given actor completes. + */ + _queueRequest(request) { + var actor = request.actor; + var queue = this._pendingRequests.get(actor) || []; + queue.push(request); + this._pendingRequests.set(actor, queue); + }, + + /** + * Attempt the next request to a given actor (if any). + */ + _attemptNextRequest(actor) { + if (this._activeRequests.has(actor)) { + return; + } + var queue = this._pendingRequests.get(actor); + if (!queue) { + return; + } + var request = queue.shift(); + if (queue.length === 0) { + this._pendingRequests.delete(actor); + } + this._sendRequest(request); + }, + + /** + * Arrange to hand the next reply from |aActor| to the handler bound to + * |aRequest|. + * + * DebuggerClient.prototype.request / startBulkRequest usually takes care of + * establishing the handler for a given request, but in rare cases (well, + * greetings from new root actors, is the only case at the moment) we must be + * prepared for a "reply" that doesn't correspond to any request we sent. + */ + expectReply: function (aActor, aRequest) { + if (this._activeRequests.has(aActor)) { + throw Error("clashing handlers for next reply from " + uneval(aActor)); + } + + // If a handler is passed directly (as it is with the handler for the root + // actor greeting), create a dummy request to bind this to. + if (typeof aRequest === "function") { + var handler = aRequest; + aRequest = new Request(); + aRequest.on("json-reply", handler); + } + + this._activeRequests.set(aActor, aRequest); + }, + + // Transport hooks. + + /** + * Called by DebuggerTransport to dispatch incoming packets as appropriate. + * + * @param aPacket object + * The incoming packet. + */ + onPacket: function (aPacket) { + if (!aPacket.from) { + DevToolsUtils.reportException("onPacket", new Error("Server did not specify an actor, dropping packet: " + JSON.stringify(aPacket))); + return; + } + + // If we have a registered Front for this actor, let it handle the packet + // and skip all the rest of this unpleasantness. + var front = this.getActor(aPacket.from); + if (front) { + front.onPacket(aPacket); + return; + } + + if (this._clients.has(aPacket.from) && aPacket.type) { + var client = this._clients.get(aPacket.from); + var type = aPacket.type; + if (client.events.indexOf(type) != -1) { + client.emit(type, aPacket); + // we ignore the rest, as the client is expected to handle this packet. + return; + } + } + + var activeRequest = void 0; + // See if we have a handler function waiting for a reply from this + // actor. (Don't count unsolicited notifications or pauses as + // replies.) + if (this._activeRequests.has(aPacket.from) && !(aPacket.type in UnsolicitedNotifications) && !(aPacket.type == ThreadStateTypes.paused && aPacket.why.type in UnsolicitedPauses)) { + activeRequest = this._activeRequests.get(aPacket.from); + this._activeRequests.delete(aPacket.from); + } + + // If there is a subsequent request for the same actor, hand it off to the + // transport. Delivery of packets on the other end is always async, even + // in the local transport case. + this._attemptNextRequest(aPacket.from); + + // Packets that indicate thread state changes get special treatment. + if (aPacket.type in ThreadStateTypes && this._clients.has(aPacket.from) && typeof this._clients.get(aPacket.from)._onThreadState == "function") { + this._clients.get(aPacket.from)._onThreadState(aPacket); + } + + // TODO: Bug 1151156 - Remove once Gecko 40 is on b2g-stable. + if (!this.traits.noNeedToFakeResumptionOnNavigation) { + // On navigation the server resumes, so the client must resume as well. + // We achieve that by generating a fake resumption packet that triggers + // the client's thread state change listeners. + if (aPacket.type == UnsolicitedNotifications.tabNavigated && this._clients.has(aPacket.from) && this._clients.get(aPacket.from).thread) { + var thread = this._clients.get(aPacket.from).thread; + var resumption = { from: thread._actor, type: "resumed" }; + thread._onThreadState(resumption); + } + } + + // Only try to notify listeners on events, not responses to requests + // that lack a packet type. + if (aPacket.type) { + this.emit(aPacket.type, aPacket); + } + + if (activeRequest) { + var emitReply = () => activeRequest.emit("json-reply", aPacket); + if (activeRequest.stack) { + Cu.callFunctionWithAsyncStack(emitReply, activeRequest.stack, "DevTools RDP"); + } else { + emitReply(); + } + } + }, + + /** + * Called by the DebuggerTransport to dispatch incoming bulk packets as + * appropriate. + * + * @param packet object + * The incoming packet, which contains: + * * actor: Name of actor that will receive the packet + * * type: Name of actor's method that should be called on receipt + * * length: Size of the data to be read + * * stream: This input stream should only be used directly if you can + * ensure that you will read exactly |length| bytes and will + * not close the stream when reading is complete + * * done: If you use the stream directly (instead of |copyTo| + * below), you must signal completion by resolving / + * rejecting this deferred. If it's rejected, the transport + * will be closed. If an Error is supplied as a rejection + * value, it will be logged via |dumpn|. If you do use + * |copyTo|, resolving is taken care of for you when copying + * completes. + * * copyTo: A helper function for getting your data out of the stream + * that meets the stream handling requirements above, and has + * the following signature: + * @param output nsIAsyncOutputStream + * The stream to copy to. + * @return Promise + * The promise is resolved when copying completes or rejected + * if any (unexpected) errors occur. + * This object also emits "progress" events for each chunk + * that is copied. See stream-utils.js. + */ + onBulkPacket: function (packet) { + var actor = packet.actor; + var type = packet.type; + var length = packet.length; + + + if (!actor) { + DevToolsUtils.reportException("onBulkPacket", new Error("Server did not specify an actor, dropping bulk packet: " + JSON.stringify(packet))); + return; + } + + // See if we have a handler function waiting for a reply from this + // actor. + if (!this._activeRequests.has(actor)) { + return; + } + + var activeRequest = this._activeRequests.get(actor); + this._activeRequests.delete(actor); + + // If there is a subsequent request for the same actor, hand it off to the + // transport. Delivery of packets on the other end is always async, even + // in the local transport case. + this._attemptNextRequest(actor); + + activeRequest.emit("bulk-reply", packet); + }, + + /** + * Called by DebuggerTransport when the underlying stream is closed. + * + * @param aStatus nsresult + * The status code that corresponds to the reason for closing + * the stream. + */ + onClosed: function (aStatus) { + this._closed = true; + this.emit("closed"); + + // Reject all pending and active requests + var reject = function (type, request, actor) { + // Server can send packets on its own and client only pass a callback + // to expectReply, so that there is no request object. + var msg = void 0; + if (request.request) { + msg = "'" + request.request.type + "' " + type + " request packet" + " to '" + actor + "' " + "can't be sent as the connection just closed."; + } else { + msg = "server side packet from '" + actor + "' can't be received " + "as the connection just closed."; + } + var packet = { error: "connectionClosed", message: msg }; + request.emit("json-reply", packet); + }; + + var pendingRequests = new Map(this._pendingRequests); + this._pendingRequests.clear(); + pendingRequests.forEach((list, actor) => { + list.forEach(request => reject("pending", request, actor)); + }); + var activeRequests = new Map(this._activeRequests); + this._activeRequests.clear(); + activeRequests.forEach(reject.bind(null, "active")); + + // The |_pools| array on the client-side currently is used only by + // protocol.js to store active fronts, mirroring the actor pools found in + // the server. So, read all usages of "pool" as "protocol.js front". + // + // In the normal case where we shutdown cleanly, the toolbox tells each tool + // to close, and they each call |destroy| on any fronts they were using. + // When |destroy| or |cleanup| is called on a protocol.js front, it also + // removes itself from the |_pools| array. Once the toolbox has shutdown, + // the connection is closed, and we reach here. All fronts (should have + // been) |destroy|ed, so |_pools| should empty. + // + // If the connection instead aborts unexpectedly, we may end up here with + // all fronts used during the life of the connection. So, we call |cleanup| + // on them clear their state, reject pending requests, and remove themselves + // from |_pools|. This saves the toolbox from hanging indefinitely, in case + // it waits for some server response before shutdown that will now never + // arrive. + for (var pool of this._pools) { + pool.cleanup(); + } + }, + + registerClient: function (client) { + var actorID = client.actor; + if (!actorID) { + throw new Error("DebuggerServer.registerClient expects " + "a client instance with an `actor` attribute."); + } + if (!Array.isArray(client.events)) { + throw new Error("DebuggerServer.registerClient expects " + "a client instance with an `events` attribute " + "that is an array."); + } + if (client.events.length > 0 && typeof client.emit != "function") { + throw new Error("DebuggerServer.registerClient expects " + "a client instance with non-empty `events` array to" + "have an `emit` function."); + } + if (this._clients.has(actorID)) { + throw new Error("DebuggerServer.registerClient already registered " + "a client for this actor."); + } + this._clients.set(actorID, client); + }, + + unregisterClient: function (client) { + var actorID = client.actor; + if (!actorID) { + throw new Error("DebuggerServer.unregisterClient expects " + "a Client instance with a `actor` attribute."); + } + this._clients.delete(actorID); + }, + + /** + * Actor lifetime management, echos the server's actor pools. + */ + __pools: null, + get _pools() { + if (this.__pools) { + return this.__pools; + } + this.__pools = new Set(); + return this.__pools; + }, + + addActorPool: function (pool) { + this._pools.add(pool); + }, + removeActorPool: function (pool) { + this._pools.delete(pool); + }, + getActor: function (actorID) { + var pool = this.poolFor(actorID); + return pool ? pool.get(actorID) : null; + }, + + poolFor: function (actorID) { + for (var pool of this._pools) { + if (pool.has(actorID)) return pool; + } + return null; + }, + + /** + * Currently attached addon. + */ + activeAddon: null + }; + + eventSource(DebuggerClient.prototype); + + function Request(request) { + this.request = request; + } + + Request.prototype = { + + on: function (type, listener) { + events.on(this, type, listener); + }, + + off: function (type, listener) { + events.off(this, type, listener); + }, + + once: function (type, listener) { + events.once(this, type, listener); + }, + + emit: function (type) { + for (var _len4 = arguments.length, args = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { + args[_key4 - 1] = arguments[_key4]; + } + + events.emit.apply(events, [this, type].concat(args)); + }, + + get actor() { + return this.request.to || this.request.actor; + } + + }; + + /** + * Creates a tab client for the remote debugging protocol server. This client + * is a front to the tab actor created in the server side, hiding the protocol + * details in a traditional JavaScript API. + * + * @param aClient DebuggerClient + * The debugger client parent. + * @param aForm object + * The protocol form for this tab. + */ + function TabClient(aClient, aForm) { + this.client = aClient; + this._actor = aForm.from; + this._threadActor = aForm.threadActor; + this.javascriptEnabled = aForm.javascriptEnabled; + this.cacheDisabled = aForm.cacheDisabled; + this.thread = null; + this.request = this.client.request; + this.traits = aForm.traits || {}; + this.events = ["workerListChanged"]; + } + + TabClient.prototype = { + get actor() { + return this._actor; + }, + get _transport() { + return this.client._transport; + }, + + /** + * Attach to a thread actor. + * + * @param object aOptions + * Configuration options. + * - useSourceMaps: whether to use source maps or not. + * @param function aOnResponse + * Called with the response packet and a ThreadClient + * (which will be undefined on error). + */ + attachThread: function () { + var aOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var aOnResponse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; + + if (this.thread) { + DevToolsUtils.executeSoon(() => aOnResponse({}, this.thread)); + return promise.resolve([{}, this.thread]); + } + + var packet = { + to: this._threadActor, + type: "attach", + options: aOptions + }; + return this.request(packet).then(aResponse => { + if (!aResponse.error) { + this.thread = new ThreadClient(this, this._threadActor); + this.client.registerClient(this.thread); + } + aOnResponse(aResponse, this.thread); + return [aResponse, this.thread]; + }); + }, + + /** + * Detach the client from the tab actor. + * + * @param function aOnResponse + * Called with the response packet. + */ + detach: DebuggerClient.requester({ + type: "detach" + }, { + before: function (aPacket) { + if (this.thread) { + this.thread.detach(); + } + return aPacket; + }, + after: function (aResponse) { + this.client.unregisterClient(this); + return aResponse; + }, + telemetry: "TABDETACH" + }), + + /** + * Bring the window to the front. + */ + focus: DebuggerClient.requester({ + type: "focus" + }, {}), + + /** + * Reload the page in this tab. + * + * @param [optional] object options + * An object with a `force` property indicating whether or not + * this reload should skip the cache + */ + reload: function () { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { force: false }; + + return this._reload(options); + }, + _reload: DebuggerClient.requester({ + type: "reload", + options: args(0) + }, { + telemetry: "RELOAD" + }), + + /** + * Navigate to another URL. + * + * @param string url + * The URL to navigate to. + */ + navigateTo: DebuggerClient.requester({ + type: "navigateTo", + url: args(0) + }, { + telemetry: "NAVIGATETO" + }), + + /** + * Reconfigure the tab actor. + * + * @param object aOptions + * A dictionary object of the new options to use in the tab actor. + * @param function aOnResponse + * Called with the response packet. + */ + reconfigure: DebuggerClient.requester({ + type: "reconfigure", + options: args(0) + }, { + telemetry: "RECONFIGURETAB" + }), + + listWorkers: DebuggerClient.requester({ + type: "listWorkers" + }, { + telemetry: "LISTWORKERS" + }), + + attachWorker: function (aWorkerActor, aOnResponse) { + this.client.attachWorker(aWorkerActor, aOnResponse); + }, + + /** + * Resolve a location ({ url, line, column }) to its current + * source mapping location. + * + * @param {String} arg[0].url + * @param {Number} arg[0].line + * @param {Number?} arg[0].column + */ + resolveLocation: DebuggerClient.requester({ + type: "resolveLocation", + location: args(0) + }) + }; + + eventSource(TabClient.prototype); + + function WorkerClient(aClient, aForm) { + this.client = aClient; + this._actor = aForm.from; + this._isClosed = false; + this._url = aForm.url; + + this._onClose = this._onClose.bind(this); + + this.addListener("close", this._onClose); + + this.traits = {}; + } + + WorkerClient.prototype = { + get _transport() { + return this.client._transport; + }, + + get request() { + return this.client.request; + }, + + get actor() { + return this._actor; + }, + + get url() { + return this._url; + }, + + get isClosed() { + return this._isClosed; + }, + + detach: DebuggerClient.requester({ type: "detach" }, { + after: function (aResponse) { + if (this.thread) { + this.client.unregisterClient(this.thread); + } + this.client.unregisterClient(this); + return aResponse; + }, + + telemetry: "WORKERDETACH" + }), + + attachThread: function () { + var _this5 = this; + + var aOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var aOnResponse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; + + if (this.thread) { + var _ret5 = function () { + var response = [{ + type: "connected", + threadActor: _this5.thread._actor, + consoleActor: _this5.consoleActor + }, _this5.thread]; + DevToolsUtils.executeSoon(() => aOnResponse(response)); + return { + v: response + }; + }(); + + if (typeof _ret5 === "object") return _ret5.v; + } + + // The connect call on server doesn't attach the thread as of version 44. + return this.request({ + to: this._actor, + type: "connect", + options: aOptions + }).then(connectReponse => { + if (connectReponse.error) { + aOnResponse(connectReponse, null); + return [connectResponse, null]; + } + + return this.request({ + to: connectReponse.threadActor, + type: "attach", + options: aOptions + }).then(attachResponse => { + if (attachResponse.error) { + aOnResponse(attachResponse, null); + } + + this.thread = new ThreadClient(this, connectReponse.threadActor); + this.consoleActor = connectReponse.consoleActor; + this.client.registerClient(this.thread); + + aOnResponse(connectReponse, this.thread); + return [connectResponse, this.thread]; + }); + }); + }, + + _onClose: function () { + this.removeListener("close", this._onClose); + + if (this.thread) { + this.client.unregisterClient(this.thread); + } + this.client.unregisterClient(this); + this._isClosed = true; + }, + + reconfigure: function () { + return Promise.resolve(); + }, + + events: ["close"] + }; + + eventSource(WorkerClient.prototype); + + function AddonClient(aClient, aActor) { + this._client = aClient; + this._actor = aActor; + this.request = this._client.request; + this.events = []; + } + + AddonClient.prototype = { + get actor() { + return this._actor; + }, + get _transport() { + return this._client._transport; + }, + + /** + * Detach the client from the addon actor. + * + * @param function aOnResponse + * Called with the response packet. + */ + detach: DebuggerClient.requester({ + type: "detach" + }, { + after: function (aResponse) { + if (this._client.activeAddon === this) { + this._client.activeAddon = null; + } + this._client.unregisterClient(this); + return aResponse; + }, + telemetry: "ADDONDETACH" + }) + }; + + /** + * A RootClient object represents a root actor on the server. Each + * DebuggerClient keeps a RootClient instance representing the root actor + * for the initial connection; DebuggerClient's 'listTabs' and + * 'listChildProcesses' methods forward to that root actor. + * + * @param aClient object + * The client connection to which this actor belongs. + * @param aGreeting string + * The greeting packet from the root actor we're to represent. + * + * Properties of a RootClient instance: + * + * @property actor string + * The name of this child's root actor. + * @property applicationType string + * The application type, as given in the root actor's greeting packet. + * @property traits object + * The traits object, as given in the root actor's greeting packet. + */ + function RootClient(aClient, aGreeting) { + this._client = aClient; + this.actor = aGreeting.from; + this.applicationType = aGreeting.applicationType; + this.traits = aGreeting.traits; + } + exports.RootClient = RootClient; + + RootClient.prototype = { + constructor: RootClient, + + /** + * List the open tabs. + * + * @param function aOnResponse + * Called with the response packet. + */ + listTabs: DebuggerClient.requester({ type: "listTabs" }, { telemetry: "LISTTABS" }), + + /** + * List the installed addons. + * + * @param function aOnResponse + * Called with the response packet. + */ + listAddons: DebuggerClient.requester({ type: "listAddons" }, { telemetry: "LISTADDONS" }), + + /** + * List the registered workers. + * + * @param function aOnResponse + * Called with the response packet. + */ + listWorkers: DebuggerClient.requester({ type: "listWorkers" }, { telemetry: "LISTWORKERS" }), + + /** + * List the registered service workers. + * + * @param function aOnResponse + * Called with the response packet. + */ + listServiceWorkerRegistrations: DebuggerClient.requester({ type: "listServiceWorkerRegistrations" }, { telemetry: "LISTSERVICEWORKERREGISTRATIONS" }), + + /** + * List the running processes. + * + * @param function aOnResponse + * Called with the response packet. + */ + listProcesses: DebuggerClient.requester({ type: "listProcesses" }, { telemetry: "LISTPROCESSES" }), + + /** + * Fetch the TabActor for the currently selected tab, or for a specific + * tab given as first parameter. + * + * @param [optional] object aFilter + * A dictionary object with following optional attributes: + * - outerWindowID: used to match tabs in parent process + * - tabId: used to match tabs in child processes + * - tab: a reference to xul:tab element + * If nothing is specified, returns the actor for the currently + * selected tab. + */ + getTab: function (aFilter) { + var packet = { + to: this.actor, + type: "getTab" + }; + + if (aFilter) { + if (typeof aFilter.outerWindowID == "number") { + packet.outerWindowID = aFilter.outerWindowID; + } else if (typeof aFilter.tabId == "number") { + packet.tabId = aFilter.tabId; + } else if ("tab" in aFilter) { + var browser = aFilter.tab.linkedBrowser; + if (browser.frameLoader.tabParent) { + // Tabs in child process + packet.tabId = browser.frameLoader.tabParent.tabId; + } else { + // Tabs in parent process + var windowUtils = browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); + packet.outerWindowID = windowUtils.outerWindowID; + } + } else { + // Throw if a filter object have been passed but without + // any clearly idenfified filter. + throw new Error("Unsupported argument given to getTab request"); + } + } + + return this.request(packet); + }, + + /** + * Description of protocol's actors and methods. + * + * @param function aOnResponse + * Called with the response packet. + */ + protocolDescription: DebuggerClient.requester({ type: "protocolDescription" }, { telemetry: "PROTOCOLDESCRIPTION" }), + + /* + * Methods constructed by DebuggerClient.requester require these forwards + * on their 'this'. + */ + get _transport() { + return this._client._transport; + }, + get request() { + return this._client.request; + } + }; + + /** + * Creates a thread client for the remote debugging protocol server. This client + * is a front to the thread actor created in the server side, hiding the + * protocol details in a traditional JavaScript API. + * + * @param aClient DebuggerClient|TabClient + * The parent of the thread (tab for tab-scoped debuggers, DebuggerClient + * for chrome debuggers). + * @param aActor string + * The actor ID for this thread. + */ + function ThreadClient(aClient, aActor) { + this._parent = aClient; + this.client = aClient instanceof DebuggerClient ? aClient : aClient.client; + this._actor = aActor; + this._frameCache = []; + this._scriptCache = {}; + this._pauseGrips = {}; + this._threadGrips = {}; + this.request = this.client.request; + } + + ThreadClient.prototype = { + _state: "paused", + get state() { + return this._state; + }, + get paused() { + return this._state === "paused"; + }, + + _pauseOnExceptions: false, + _ignoreCaughtExceptions: false, + _pauseOnDOMEvents: null, + + _actor: null, + get actor() { + return this._actor; + }, + + get _transport() { + return this.client._transport; + }, + + _assertPaused: function (aCommand) { + if (!this.paused) { + throw Error(aCommand + " command sent while not paused. Currently " + this._state); + } + }, + + /** + * Resume a paused thread. If the optional aLimit parameter is present, then + * the thread will also pause when that limit is reached. + * + * @param [optional] object aLimit + * An object with a type property set to the appropriate limit (next, + * step, or finish) per the remote debugging protocol specification. + * Use null to specify no limit. + * @param function aOnResponse + * Called with the response packet. + */ + _doResume: DebuggerClient.requester({ + type: "resume", + resumeLimit: args(0) + }, { + before: function (aPacket) { + this._assertPaused("resume"); + + // Put the client in a tentative "resuming" state so we can prevent + // further requests that should only be sent in the paused state. + this._state = "resuming"; + + if (this._pauseOnExceptions) { + aPacket.pauseOnExceptions = this._pauseOnExceptions; + } + if (this._ignoreCaughtExceptions) { + aPacket.ignoreCaughtExceptions = this._ignoreCaughtExceptions; + } + if (this._pauseOnDOMEvents) { + aPacket.pauseOnDOMEvents = this._pauseOnDOMEvents; + } + return aPacket; + }, + after: function (aResponse) { + if (aResponse.error) { + // There was an error resuming, back to paused state. + this._state = "paused"; + } + return aResponse; + }, + telemetry: "RESUME" + }), + + /** + * Reconfigure the thread actor. + * + * @param object aOptions + * A dictionary object of the new options to use in the thread actor. + * @param function aOnResponse + * Called with the response packet. + */ + reconfigure: DebuggerClient.requester({ + type: "reconfigure", + options: args(0) + }, { + telemetry: "RECONFIGURETHREAD" + }), + + /** + * Resume a paused thread. + */ + resume: function (aOnResponse) { + return this._doResume(null, aOnResponse); + }, + + /** + * Resume then pause without stepping. + * + * @param function aOnResponse + * Called with the response packet. + */ + resumeThenPause: function (aOnResponse) { + return this._doResume({ type: "break" }, aOnResponse); + }, + + /** + * Step over a function call. + * + * @param function aOnResponse + * Called with the response packet. + */ + stepOver: function (aOnResponse) { + return this._doResume({ type: "next" }, aOnResponse); + }, + + /** + * Step into a function call. + * + * @param function aOnResponse + * Called with the response packet. + */ + stepIn: function (aOnResponse) { + return this._doResume({ type: "step" }, aOnResponse); + }, + + /** + * Step out of a function call. + * + * @param function aOnResponse + * Called with the response packet. + */ + stepOut: function (aOnResponse) { + return this._doResume({ type: "finish" }, aOnResponse); + }, + + /** + * Immediately interrupt a running thread. + * + * @param function aOnResponse + * Called with the response packet. + */ + interrupt: function (aOnResponse) { + return this._doInterrupt(null, aOnResponse); + }, + + /** + * Pause execution right before the next JavaScript bytecode is executed. + * + * @param function aOnResponse + * Called with the response packet. + */ + breakOnNext: function (aOnResponse) { + return this._doInterrupt("onNext", aOnResponse); + }, + + /** + * Interrupt a running thread. + * + * @param function aOnResponse + * Called with the response packet. + */ + _doInterrupt: DebuggerClient.requester({ + type: "interrupt", + when: args(0) + }, { + telemetry: "INTERRUPT" + }), + + /** + * Enable or disable pausing when an exception is thrown. + * + * @param boolean aFlag + * Enables pausing if true, disables otherwise. + * @param function aOnResponse + * Called with the response packet. + */ + pauseOnExceptions: function (aPauseOnExceptions, aIgnoreCaughtExceptions) { + var aOnResponse = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : noop; + + this._pauseOnExceptions = aPauseOnExceptions; + this._ignoreCaughtExceptions = aIgnoreCaughtExceptions; + + // Otherwise send the flag using a standard resume request. + if (!this.paused) { + return this.interrupt(aResponse => { + if (aResponse.error) { + // Can't continue if pausing failed. + aOnResponse(aResponse); + return aResponse; + } + return this.resume(aOnResponse); + }); + } + + aOnResponse(); + return promise.resolve(); + }, + + /** + * Enable pausing when the specified DOM events are triggered. Disabling + * pausing on an event can be realized by calling this method with the updated + * array of events that doesn't contain it. + * + * @param array|string events + * An array of strings, representing the DOM event types to pause on, + * or "*" to pause on all DOM events. Pass an empty array to + * completely disable pausing on DOM events. + * @param function onResponse + * Called with the response packet in a future turn of the event loop. + */ + pauseOnDOMEvents: function (events) { + var onResponse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; + + this._pauseOnDOMEvents = events; + // If the debuggee is paused, the value of the array will be communicated in + // the next resumption. Otherwise we have to force a pause in order to send + // the array. + if (this.paused) { + DevToolsUtils.executeSoon(() => onResponse({})); + return {}; + } + return this.interrupt(response => { + // Can't continue if pausing failed. + if (response.error) { + onResponse(response); + return response; + } + return this.resume(onResponse); + }); + }, + + /** + * Send a clientEvaluate packet to the debuggee. Response + * will be a resume packet. + * + * @param string aFrame + * The actor ID of the frame where the evaluation should take place. + * @param string aExpression + * The expression that will be evaluated in the scope of the frame + * above. + * @param function aOnResponse + * Called with the response packet. + */ + eval: DebuggerClient.requester({ + type: "clientEvaluate", + frame: args(0), + expression: args(1) + }, { + before: function (aPacket) { + this._assertPaused("eval"); + // Put the client in a tentative "resuming" state so we can prevent + // further requests that should only be sent in the paused state. + this._state = "resuming"; + return aPacket; + }, + after: function (aResponse) { + if (aResponse.error) { + // There was an error resuming, back to paused state. + this._state = "paused"; + } + return aResponse; + }, + telemetry: "CLIENTEVALUATE" + }), + + /** + * Detach from the thread actor. + * + * @param function aOnResponse + * Called with the response packet. + */ + detach: DebuggerClient.requester({ + type: "detach" + }, { + after: function (aResponse) { + this.client.unregisterClient(this); + this._parent.thread = null; + return aResponse; + }, + telemetry: "THREADDETACH" + }), + + /** + * Release multiple thread-lifetime object actors. If any pause-lifetime + * actors are included in the request, a |notReleasable| error will return, + * but all the thread-lifetime ones will have been released. + * + * @param array actors + * An array with actor IDs to release. + */ + releaseMany: DebuggerClient.requester({ + type: "releaseMany", + actors: args(0) + }, { + telemetry: "RELEASEMANY" + }), + + /** + * Promote multiple pause-lifetime object actors to thread-lifetime ones. + * + * @param array actors + * An array with actor IDs to promote. + */ + threadGrips: DebuggerClient.requester({ + type: "threadGrips", + actors: args(0) + }, { + telemetry: "THREADGRIPS" + }), + + /** + * Return the event listeners defined on the page. + * + * @param aOnResponse Function + * Called with the thread's response. + */ + eventListeners: DebuggerClient.requester({ + type: "eventListeners" + }, { + telemetry: "EVENTLISTENERS" + }), + + /** + * Request the loaded sources for the current thread. + * + * @param aOnResponse Function + * Called with the thread's response. + */ + getSources: DebuggerClient.requester({ + type: "sources" + }, { + telemetry: "SOURCES" + }), + + /** + * Clear the thread's source script cache. A scriptscleared event + * will be sent. + */ + _clearScripts: function () { + if (Object.keys(this._scriptCache).length > 0) { + this._scriptCache = {}; + this.emit("scriptscleared"); + } + }, + + /** + * Request frames from the callstack for the current thread. + * + * @param aStart integer + * The number of the youngest stack frame to return (the youngest + * frame is 0). + * @param aCount integer + * The maximum number of frames to return, or null to return all + * frames. + * @param aOnResponse function + * Called with the thread's response. + */ + getFrames: DebuggerClient.requester({ + type: "frames", + start: args(0), + count: args(1) + }, { + telemetry: "FRAMES" + }), + + /** + * An array of cached frames. Clients can observe the framesadded and + * framescleared event to keep up to date on changes to this cache, + * and can fill it using the fillFrames method. + */ + get cachedFrames() { + return this._frameCache; + }, + + /** + * true if there are more stack frames available on the server. + */ + get moreFrames() { + return this.paused && (!this._frameCache || this._frameCache.length == 0 || !this._frameCache[this._frameCache.length - 1].oldest); + }, + + /** + * Ensure that at least aTotal stack frames have been loaded in the + * ThreadClient's stack frame cache. A framesadded event will be + * sent when the stack frame cache is updated. + * + * @param aTotal number + * The minimum number of stack frames to be included. + * @param aCallback function + * Optional callback function called when frames have been loaded + * @returns true if a framesadded notification should be expected. + */ + fillFrames: function (aTotal) { + var aCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; + + this._assertPaused("fillFrames"); + if (this._frameCache.length >= aTotal) { + return false; + } + + var numFrames = this._frameCache.length; + + this.getFrames(numFrames, aTotal - numFrames, aResponse => { + if (aResponse.error) { + aCallback(aResponse); + return; + } + + var threadGrips = DevToolsUtils.values(this._threadGrips); + + for (var i in aResponse.frames) { + var frame = aResponse.frames[i]; + if (!frame.where.source) { + // Older servers use urls instead, so we need to resolve + // them to source actors + for (var grip of threadGrips) { + if (grip instanceof SourceClient && grip.url === frame.url) { + frame.where.source = grip._form; + } + } + } + + this._frameCache[frame.depth] = frame; + } + + // If we got as many frames as we asked for, there might be more + // frames available. + this.emit("framesadded"); + + aCallback(aResponse); + }); + + return true; + }, + + /** + * Clear the thread's stack frame cache. A framescleared event + * will be sent. + */ + _clearFrames: function () { + if (this._frameCache.length > 0) { + this._frameCache = []; + this.emit("framescleared"); + } + }, + + /** + * Return a ObjectClient object for the given object grip. + * + * @param aGrip object + * A pause-lifetime object grip returned by the protocol. + */ + pauseGrip: function (aGrip) { + if (aGrip.actor in this._pauseGrips) { + return this._pauseGrips[aGrip.actor]; + } + + var client = new ObjectClient(this.client, aGrip); + this._pauseGrips[aGrip.actor] = client; + return client; + }, + + /** + * Get or create a long string client, checking the grip client cache if it + * already exists. + * + * @param aGrip Object + * The long string grip returned by the protocol. + * @param aGripCacheName String + * The property name of the grip client cache to check for existing + * clients in. + */ + _longString: function (aGrip, aGripCacheName) { + if (aGrip.actor in this[aGripCacheName]) { + return this[aGripCacheName][aGrip.actor]; + } + + var client = new LongStringClient(this.client, aGrip); + this[aGripCacheName][aGrip.actor] = client; + return client; + }, + + /** + * Return an instance of LongStringClient for the given long string grip that + * is scoped to the current pause. + * + * @param aGrip Object + * The long string grip returned by the protocol. + */ + pauseLongString: function (aGrip) { + return this._longString(aGrip, "_pauseGrips"); + }, + + /** + * Return an instance of LongStringClient for the given long string grip that + * is scoped to the thread lifetime. + * + * @param aGrip Object + * The long string grip returned by the protocol. + */ + threadLongString: function (aGrip) { + return this._longString(aGrip, "_threadGrips"); + }, + + /** + * Clear and invalidate all the grip clients from the given cache. + * + * @param aGripCacheName + * The property name of the grip cache we want to clear. + */ + _clearObjectClients: function (aGripCacheName) { + for (var id in this[aGripCacheName]) { + this[aGripCacheName][id].valid = false; + } + this[aGripCacheName] = {}; + }, + + /** + * Invalidate pause-lifetime grip clients and clear the list of current grip + * clients. + */ + _clearPauseGrips: function () { + this._clearObjectClients("_pauseGrips"); + }, + + /** + * Invalidate thread-lifetime grip clients and clear the list of current grip + * clients. + */ + _clearThreadGrips: function () { + this._clearObjectClients("_threadGrips"); + }, + + /** + * Handle thread state change by doing necessary cleanup and notifying all + * registered listeners. + */ + _onThreadState: function (aPacket) { + this._state = ThreadStateTypes[aPacket.type]; + // The debugger UI may not be initialized yet so we want to keep + // the packet around so it knows what to pause state to display + // when it's initialized + this._lastPausePacket = aPacket.type === "resumed" ? null : aPacket; + this._clearFrames(); + this._clearPauseGrips(); + aPacket.type === ThreadStateTypes.detached && this._clearThreadGrips(); + this.client._eventsEnabled && this.emit(aPacket.type, aPacket); + }, + + getLastPausePacket: function () { + return this._lastPausePacket; + }, + + /** + * Return an EnvironmentClient instance for the given environment actor form. + */ + environment: function (aForm) { + return new EnvironmentClient(this.client, aForm); + }, + + /** + * Return an instance of SourceClient for the given source actor form. + */ + source: function (aForm) { + if (aForm.actor in this._threadGrips) { + return this._threadGrips[aForm.actor]; + } + + return this._threadGrips[aForm.actor] = new SourceClient(this, aForm); + }, + + /** + * Request the prototype and own properties of mutlipleObjects. + * + * @param aOnResponse function + * Called with the request's response. + * @param actors [string] + * List of actor ID of the queried objects. + */ + getPrototypesAndProperties: DebuggerClient.requester({ + type: "prototypesAndProperties", + actors: args(0) + }, { + telemetry: "PROTOTYPESANDPROPERTIES" + }), + + events: ["newSource"] + }; + + eventSource(ThreadClient.prototype); + + /** + * Creates a tracing profiler client for the remote debugging protocol + * server. This client is a front to the trace actor created on the + * server side, hiding the protocol details in a traditional + * JavaScript API. + * + * @param aClient DebuggerClient + * The debugger client parent. + * @param aActor string + * The actor ID for this thread. + */ + function TraceClient(aClient, aActor) { + this._client = aClient; + this._actor = aActor; + this._activeTraces = new Set(); + this._waitingPackets = new Map(); + this._expectedPacket = 0; + this.request = this._client.request; + this.events = []; + } + + TraceClient.prototype = { + get actor() { + return this._actor; + }, + get tracing() { + return this._activeTraces.size > 0; + }, + + get _transport() { + return this._client._transport; + }, + + /** + * Detach from the trace actor. + */ + detach: DebuggerClient.requester({ + type: "detach" + }, { + after: function (aResponse) { + this._client.unregisterClient(this); + return aResponse; + }, + telemetry: "TRACERDETACH" + }), + + /** + * Start a new trace. + * + * @param aTrace [string] + * An array of trace types to be recorded by the new trace. + * + * @param aName string + * The name of the new trace. + * + * @param aOnResponse function + * Called with the request's response. + */ + startTrace: DebuggerClient.requester({ + type: "startTrace", + name: args(1), + trace: args(0) + }, { + after: function (aResponse) { + if (aResponse.error) { + return aResponse; + } + + if (!this.tracing) { + this._waitingPackets.clear(); + this._expectedPacket = 0; + } + this._activeTraces.add(aResponse.name); + + return aResponse; + }, + telemetry: "STARTTRACE" + }), + + /** + * End a trace. If a name is provided, stop the named + * trace. Otherwise, stop the most recently started trace. + * + * @param aName string + * The name of the trace to stop. + * + * @param aOnResponse function + * Called with the request's response. + */ + stopTrace: DebuggerClient.requester({ + type: "stopTrace", + name: args(0) + }, { + after: function (aResponse) { + if (aResponse.error) { + return aResponse; + } + + this._activeTraces.delete(aResponse.name); + + return aResponse; + }, + telemetry: "STOPTRACE" + }) + }; + + /** + * Grip clients are used to retrieve information about the relevant object. + * + * @param aClient DebuggerClient + * The debugger client parent. + * @param aGrip object + * A pause-lifetime object grip returned by the protocol. + */ + function ObjectClient(aClient, aGrip) { + this._grip = aGrip; + this._client = aClient; + this.request = this._client.request; + } + exports.ObjectClient = ObjectClient; + + ObjectClient.prototype = { + get actor() { + return this._grip.actor; + }, + get _transport() { + return this._client._transport; + }, + + valid: true, + + get isFrozen() { + return this._grip.frozen; + }, + get isSealed() { + return this._grip.sealed; + }, + get isExtensible() { + return this._grip.extensible; + }, + + getDefinitionSite: DebuggerClient.requester({ + type: "definitionSite" + }, { + before: function (aPacket) { + if (this._grip.class != "Function") { + throw new Error("getDefinitionSite is only valid for function grips."); + } + return aPacket; + } + }), + + /** + * Request the names of a function's formal parameters. + * + * @param aOnResponse function + * Called with an object of the form: + * { parameterNames:[<parameterName>, ...] } + * where each <parameterName> is the name of a parameter. + */ + getParameterNames: DebuggerClient.requester({ + type: "parameterNames" + }, { + before: function (aPacket) { + if (this._grip.class !== "Function") { + throw new Error("getParameterNames is only valid for function grips."); + } + return aPacket; + }, + telemetry: "PARAMETERNAMES" + }), + + /** + * Request the names of the properties defined on the object and not its + * prototype. + * + * @param aOnResponse function Called with the request's response. + */ + getOwnPropertyNames: DebuggerClient.requester({ + type: "ownPropertyNames" + }, { + telemetry: "OWNPROPERTYNAMES" + }), + + /** + * Request the prototype and own properties of the object. + * + * @param aOnResponse function Called with the request's response. + */ + getPrototypeAndProperties: DebuggerClient.requester({ + type: "prototypeAndProperties" + }, { + telemetry: "PROTOTYPEANDPROPERTIES" + }), + + /** + * Request a PropertyIteratorClient instance to ease listing + * properties for this object. + * + * @param options Object + * A dictionary object with various boolean attributes: + * - ignoreSafeGetters Boolean + * If true, do not iterate over safe getters. + * - ignoreIndexedProperties Boolean + * If true, filters out Array items. + * e.g. properties names between `0` and `object.length`. + * - ignoreNonIndexedProperties Boolean + * If true, filters out items that aren't array items + * e.g. properties names that are not a number between `0` + * and `object.length`. + * - sort Boolean + * If true, the iterator will sort the properties by name + * before dispatching them. + * @param aOnResponse function Called with the client instance. + */ + enumProperties: DebuggerClient.requester({ + type: "enumProperties", + options: args(0) + }, { + after: function (aResponse) { + if (aResponse.iterator) { + return { iterator: new PropertyIteratorClient(this._client, aResponse.iterator) }; + } + return aResponse; + }, + telemetry: "ENUMPROPERTIES" + }), + + /** + * Request a PropertyIteratorClient instance to enumerate entries in a + * Map/Set-like object. + * + * @param aOnResponse function Called with the request's response. + */ + enumEntries: DebuggerClient.requester({ + type: "enumEntries" + }, { + before: function (packet) { + if (!["Map", "WeakMap", "Set", "WeakSet"].includes(this._grip.class)) { + throw new Error("enumEntries is only valid for Map/Set-like grips."); + } + return packet; + }, + after: function (response) { + if (response.iterator) { + return { + iterator: new PropertyIteratorClient(this._client, response.iterator) + }; + } + return response; + } + }), + + /** + * Request the property descriptor of the object's specified property. + * + * @param aName string The name of the requested property. + * @param aOnResponse function Called with the request's response. + */ + getProperty: DebuggerClient.requester({ + type: "property", + name: args(0) + }, { + telemetry: "PROPERTY" + }), + + /** + * Request the prototype of the object. + * + * @param aOnResponse function Called with the request's response. + */ + getPrototype: DebuggerClient.requester({ + type: "prototype" + }, { + telemetry: "PROTOTYPE" + }), + + /** + * Request the display string of the object. + * + * @param aOnResponse function Called with the request's response. + */ + getDisplayString: DebuggerClient.requester({ + type: "displayString" + }, { + telemetry: "DISPLAYSTRING" + }), + + /** + * Request the scope of the object. + * + * @param aOnResponse function Called with the request's response. + */ + getScope: DebuggerClient.requester({ + type: "scope" + }, { + before: function (aPacket) { + if (this._grip.class !== "Function") { + throw new Error("scope is only valid for function grips."); + } + return aPacket; + }, + telemetry: "SCOPE" + }), + + /** + * Request the promises directly depending on the current promise. + */ + getDependentPromises: DebuggerClient.requester({ + type: "dependentPromises" + }, { + before: function (aPacket) { + if (this._grip.class !== "Promise") { + throw new Error("getDependentPromises is only valid for promise " + "grips."); + } + return aPacket; + } + }), + + /** + * Request the stack to the promise's allocation point. + */ + getPromiseAllocationStack: DebuggerClient.requester({ + type: "allocationStack" + }, { + before: function (aPacket) { + if (this._grip.class !== "Promise") { + throw new Error("getAllocationStack is only valid for promise grips."); + } + return aPacket; + } + }), + + /** + * Request the stack to the promise's fulfillment point. + */ + getPromiseFulfillmentStack: DebuggerClient.requester({ + type: "fulfillmentStack" + }, { + before: function (packet) { + if (this._grip.class !== "Promise") { + throw new Error("getPromiseFulfillmentStack is only valid for " + "promise grips."); + } + return packet; + } + }), + + /** + * Request the stack to the promise's rejection point. + */ + getPromiseRejectionStack: DebuggerClient.requester({ + type: "rejectionStack" + }, { + before: function (packet) { + if (this._grip.class !== "Promise") { + throw new Error("getPromiseRejectionStack is only valid for " + "promise grips."); + } + return packet; + } + }) + }; + + /** + * A PropertyIteratorClient provides a way to access to property names and + * values of an object efficiently, slice by slice. + * Note that the properties can be sorted in the backend, + * this is controled while creating the PropertyIteratorClient + * from ObjectClient.enumProperties. + * + * @param aClient DebuggerClient + * The debugger client parent. + * @param aGrip Object + * A PropertyIteratorActor grip returned by the protocol via + * TabActor.enumProperties request. + */ + function PropertyIteratorClient(aClient, aGrip) { + this._grip = aGrip; + this._client = aClient; + this.request = this._client.request; + } + + PropertyIteratorClient.prototype = { + get actor() { + return this._grip.actor; + }, + + /** + * Get the total number of properties available in the iterator. + */ + get count() { + return this._grip.count; + }, + + /** + * Get one or more property names that correspond to the positions in the + * indexes parameter. + * + * @param indexes Array + * An array of property indexes. + * @param aCallback Function + * The function called when we receive the property names. + */ + names: DebuggerClient.requester({ + type: "names", + indexes: args(0) + }, {}), + + /** + * Get a set of following property value(s). + * + * @param start Number + * The index of the first property to fetch. + * @param count Number + * The number of properties to fetch. + * @param aCallback Function + * The function called when we receive the property values. + */ + slice: DebuggerClient.requester({ + type: "slice", + start: args(0), + count: args(1) + }, {}), + + /** + * Get all the property values. + * + * @param aCallback Function + * The function called when we receive the property values. + */ + all: DebuggerClient.requester({ + type: "all" + }, {}) + }; + + /** + * A LongStringClient provides a way to access "very long" strings from the + * debugger server. + * + * @param aClient DebuggerClient + * The debugger client parent. + * @param aGrip Object + * A pause-lifetime long string grip returned by the protocol. + */ + function LongStringClient(aClient, aGrip) { + this._grip = aGrip; + this._client = aClient; + this.request = this._client.request; + } + exports.LongStringClient = LongStringClient; + + LongStringClient.prototype = { + get actor() { + return this._grip.actor; + }, + get length() { + return this._grip.length; + }, + get initial() { + return this._grip.initial; + }, + get _transport() { + return this._client._transport; + }, + + valid: true, + + /** + * Get the substring of this LongString from aStart to aEnd. + * + * @param aStart Number + * The starting index. + * @param aEnd Number + * The ending index. + * @param aCallback Function + * The function called when we receive the substring. + */ + substring: DebuggerClient.requester({ + type: "substring", + start: args(0), + end: args(1) + }, { + telemetry: "SUBSTRING" + }) + }; + + /** + * A SourceClient provides a way to access the source text of a script. + * + * @param aClient ThreadClient + * The thread client parent. + * @param aForm Object + * The form sent across the remote debugging protocol. + */ + function SourceClient(aClient, aForm) { + this._form = aForm; + this._isBlackBoxed = aForm.isBlackBoxed; + this._isPrettyPrinted = aForm.isPrettyPrinted; + this._activeThread = aClient; + this._client = aClient.client; + } + + SourceClient.prototype = { + get _transport() { + return this._client._transport; + }, + get isBlackBoxed() { + return this._isBlackBoxed; + }, + get isPrettyPrinted() { + return this._isPrettyPrinted; + }, + get actor() { + return this._form.actor; + }, + get request() { + return this._client.request; + }, + get url() { + return this._form.url; + }, + + /** + * Black box this SourceClient's source. + * + * @param aCallback Function + * The callback function called when we receive the response from the server. + */ + blackBox: DebuggerClient.requester({ + type: "blackbox" + }, { + telemetry: "BLACKBOX", + after: function (aResponse) { + if (!aResponse.error) { + this._isBlackBoxed = true; + if (this._activeThread) { + this._activeThread.emit("blackboxchange", this); + } + } + return aResponse; + } + }), + + /** + * Un-black box this SourceClient's source. + * + * @param aCallback Function + * The callback function called when we receive the response from the server. + */ + unblackBox: DebuggerClient.requester({ + type: "unblackbox" + }, { + telemetry: "UNBLACKBOX", + after: function (aResponse) { + if (!aResponse.error) { + this._isBlackBoxed = false; + if (this._activeThread) { + this._activeThread.emit("blackboxchange", this); + } + } + return aResponse; + } + }), + + /** + * Get Executable Lines from a source + * + * @param aCallback Function + * The callback function called when we receive the response from the server. + */ + getExecutableLines: function () { + var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : noop; + + var packet = { + to: this._form.actor, + type: "getExecutableLines" + }; + + return this._client.request(packet).then(res => { + cb(res.lines); + return res.lines; + }); + }, + + /** + * Get a long string grip for this SourceClient's source. + */ + source: function () { + var aCallback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : noop; + + var packet = { + to: this._form.actor, + type: "source" + }; + return this._client.request(packet).then(aResponse => { + return this._onSourceResponse(aResponse, aCallback); + }); + }, + + /** + * Pretty print this source's text. + */ + prettyPrint: function (aIndent) { + var aCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; + + var packet = { + to: this._form.actor, + type: "prettyPrint", + indent: aIndent + }; + return this._client.request(packet).then(aResponse => { + if (!aResponse.error) { + this._isPrettyPrinted = true; + this._activeThread._clearFrames(); + this._activeThread.emit("prettyprintchange", this); + } + return this._onSourceResponse(aResponse, aCallback); + }); + }, + + /** + * Stop pretty printing this source's text. + */ + disablePrettyPrint: function () { + var aCallback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : noop; + + var packet = { + to: this._form.actor, + type: "disablePrettyPrint" + }; + return this._client.request(packet).then(aResponse => { + if (!aResponse.error) { + this._isPrettyPrinted = false; + this._activeThread._clearFrames(); + this._activeThread.emit("prettyprintchange", this); + } + return this._onSourceResponse(aResponse, aCallback); + }); + }, + + _onSourceResponse: function (aResponse, aCallback) { + if (aResponse.error) { + aCallback(aResponse); + return aResponse; + } + + if (typeof aResponse.source === "string") { + aCallback(aResponse); + return aResponse; + } + + var contentType = aResponse.contentType; + var source = aResponse.source; + + var longString = this._activeThread.threadLongString(source); + return longString.substring(0, longString.length).then(function (aResponse) { + if (aResponse.error) { + aCallback(aResponse); + return aReponse; + } + + var response = { + source: aResponse.substring, + contentType: contentType + }; + aCallback(response); + return response; + }); + }, + + /** + * Request to set a breakpoint in the specified location. + * + * @param object aLocation + * The location and condition of the breakpoint in + * the form of { line[, column, condition] }. + * @param function aOnResponse + * Called with the thread's response. + */ + setBreakpoint: function (_ref) { + var line = _ref.line; + var column = _ref.column; + var condition = _ref.condition; + var noSliding = _ref.noSliding; + var aOnResponse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; + + // A helper function that sets the breakpoint. + var doSetBreakpoint = aCallback => { + var root = this._client.mainRoot; + var location = { + line: line, + column: column + }; + + var packet = { + to: this.actor, + type: "setBreakpoint", + location: location, + condition: condition, + noSliding: noSliding + }; + + // Backwards compatibility: send the breakpoint request to the + // thread if the server doesn't support Debugger.Source actors. + if (!root.traits.debuggerSourceActors) { + packet.to = this._activeThread.actor; + packet.location.url = this.url; + } + + return this._client.request(packet).then(aResponse => { + // Ignoring errors, since the user may be setting a breakpoint in a + // dead script that will reappear on a page reload. + var bpClient = void 0; + if (aResponse.actor) { + bpClient = new BreakpointClient(this._client, this, aResponse.actor, location, root.traits.conditionalBreakpoints ? condition : undefined); + } + aOnResponse(aResponse, bpClient); + if (aCallback) { + aCallback(); + } + return [aResponse, bpClient]; + }); + }; + + // If the debuggee is paused, just set the breakpoint. + if (this._activeThread.paused) { + return doSetBreakpoint(); + } + // Otherwise, force a pause in order to set the breakpoint. + return this._activeThread.interrupt().then(aResponse => { + if (aResponse.error) { + // Can't set the breakpoint if pausing failed. + aOnResponse(aResponse); + return aResponse; + } + + var type = aResponse.type; + var why = aResponse.why; + + var cleanUp = type == "paused" && why.type == "interrupted" ? () => this._activeThread.resume() : noop; + + return doSetBreakpoint(cleanUp); + }); + } + }; + + /** + * Breakpoint clients are used to remove breakpoints that are no longer used. + * + * @param aClient DebuggerClient + * The debugger client parent. + * @param aSourceClient SourceClient + * The source where this breakpoint exists + * @param aActor string + * The actor ID for this breakpoint. + * @param aLocation object + * The location of the breakpoint. This is an object with two properties: + * url and line. + * @param aCondition string + * The conditional expression of the breakpoint + */ + function BreakpointClient(aClient, aSourceClient, aActor, aLocation, aCondition) { + this._client = aClient; + this._actor = aActor; + this.location = aLocation; + this.location.actor = aSourceClient.actor; + this.location.url = aSourceClient.url; + this.source = aSourceClient; + this.request = this._client.request; + + // The condition property should only exist if it's a truthy value + if (aCondition) { + this.condition = aCondition; + } + } + + BreakpointClient.prototype = { + + _actor: null, + get actor() { + return this._actor; + }, + get _transport() { + return this._client._transport; + }, + + /** + * Remove the breakpoint from the server. + */ + remove: DebuggerClient.requester({ + type: "delete" + }, { + telemetry: "DELETE" + }), + + /** + * Determines if this breakpoint has a condition + */ + hasCondition: function () { + var root = this._client.mainRoot; + // XXX bug 990137: We will remove support for client-side handling of + // conditional breakpoints + if (root.traits.conditionalBreakpoints) { + return "condition" in this; + } else { + return "conditionalExpression" in this; + } + }, + + /** + * Get the condition of this breakpoint. Currently we have to + * support locally emulated conditional breakpoints until the + * debugger servers are updated (see bug 990137). We used a + * different property when moving it server-side to ensure that we + * are testing the right code. + */ + getCondition: function () { + var root = this._client.mainRoot; + if (root.traits.conditionalBreakpoints) { + return this.condition; + } else { + return this.conditionalExpression; + } + }, + + /** + * Set the condition of this breakpoint + */ + setCondition: function (gThreadClient, aCondition, noSliding) { + var _this6 = this; + + var root = this._client.mainRoot; + var deferred = promise.defer(); + + if (root.traits.conditionalBreakpoints) { + (function () { + var info = { + line: _this6.location.line, + column: _this6.location.column, + condition: aCondition, + noSliding + }; + + // Remove the current breakpoint and add a new one with the + // condition. + _this6.remove(aResponse => { + if (aResponse && aResponse.error) { + deferred.reject(aResponse); + return; + } + + _this6.source.setBreakpoint(info, (aResponse, aNewBreakpoint) => { + if (aResponse && aResponse.error) { + deferred.reject(aResponse); + } else { + deferred.resolve(aNewBreakpoint); + } + }); + }); + })(); + } else { + // The property shouldn't even exist if the condition is blank + if (aCondition === "") { + delete this.conditionalExpression; + } else { + this.conditionalExpression = aCondition; + } + deferred.resolve(this); + } + + return deferred.promise; + } + }; + + eventSource(BreakpointClient.prototype); + + /** + * Environment clients are used to manipulate the lexical environment actors. + * + * @param aClient DebuggerClient + * The debugger client parent. + * @param aForm Object + * The form sent across the remote debugging protocol. + */ + function EnvironmentClient(aClient, aForm) { + this._client = aClient; + this._form = aForm; + this.request = this._client.request; + } + exports.EnvironmentClient = EnvironmentClient; + + EnvironmentClient.prototype = { + + get actor() { + return this._form.actor; + }, + get _transport() { + return this._client._transport; + }, + + /** + * Fetches the bindings introduced by this lexical environment. + */ + getBindings: DebuggerClient.requester({ + type: "bindings" + }, { + telemetry: "BINDINGS" + }), + + /** + * Changes the value of the identifier whose name is name (a string) to that + * represented by value (a grip). + */ + assign: DebuggerClient.requester({ + type: "assign", + name: args(0), + value: args(1) + }, { + telemetry: "ASSIGN" + }) + }; + + eventSource(EnvironmentClient.prototype); + +/***/ }, +/* 80 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(module) {/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + module.metadata = { + "stability": "unstable" + }; + + var UNCAUGHT_ERROR = 'An error event was emitted for which there was no listener.'; + var BAD_LISTENER = 'The event listener must be a function.'; + + var _require = __webpack_require__(81); + + var ns = _require.ns; + + + var event = ns(); + + var EVENT_TYPE_PATTERN = /^on([A-Z]\w+$)/; + exports.EVENT_TYPE_PATTERN = EVENT_TYPE_PATTERN; + + // Utility function to access given event `target` object's event listeners for + // the specific event `type`. If listeners for this type does not exists they + // will be created. + var observers = function observers(target, type) { + if (!target) throw TypeError("Event target must be an object"); + var listeners = event(target); + return type in listeners ? listeners[type] : listeners[type] = []; + }; + + /** + * Registers an event `listener` that is called every time events of + * specified `type` is emitted on the given event `target`. + * @param {Object} target + * Event target object. + * @param {String} type + * The type of event. + * @param {Function} listener + * The listener function that processes the event. + */ + function on(target, type, listener) { + if (typeof listener !== 'function') throw new Error(BAD_LISTENER); + + var listeners = observers(target, type); + if (!~listeners.indexOf(listener)) listeners.push(listener); + } + exports.on = on; + + var onceWeakMap = new WeakMap(); + + /** + * Registers an event `listener` that is called only the next time an event + * of the specified `type` is emitted on the given event `target`. + * @param {Object} target + * Event target object. + * @param {String} type + * The type of the event. + * @param {Function} listener + * The listener function that processes the event. + */ + function once(target, type, listener) { + var replacement = function observer() { + off(target, type, observer); + onceWeakMap.delete(listener); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + listener.apply(target, args); + }; + onceWeakMap.set(listener, replacement); + on(target, type, replacement); + } + exports.once = once; + + /** + * Execute each of the listeners in order with the supplied arguments. + * All the exceptions that are thrown by listeners during the emit + * are caught and can be handled by listeners of 'error' event. Thrown + * exceptions are passed as an argument to an 'error' event listener. + * If no 'error' listener is registered exception will be logged into an + * error console. + * @param {Object} target + * Event target object. + * @param {String} type + * The type of event. + * @params {Object|Number|String|Boolean} args + * Arguments that will be passed to listeners. + */ + function emit(target, type) { + for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { + args[_key2 - 2] = arguments[_key2]; + } + + emitOnObject.apply(undefined, [target, type, target].concat(args)); + } + exports.emit = emit; + + /** + * A variant of emit that allows setting the this property for event listeners + */ + function emitOnObject(target, type, thisArg) { + var all = observers(target, '*').length; + var state = observers(target, type); + var listeners = state.slice(); + var count = listeners.length; + var index = 0; + + // If error event and there are no handlers (explicit or catch-all) + // then print error message to the console. + + for (var _len3 = arguments.length, args = Array(_len3 > 3 ? _len3 - 3 : 0), _key3 = 3; _key3 < _len3; _key3++) { + args[_key3 - 3] = arguments[_key3]; + } + + if (count === 0 && type === 'error' && all === 0) console.exception(args[0]); + while (index < count) { + try { + var listener = listeners[index]; + // Dispatch only if listener is still registered. + if (~state.indexOf(listener)) listener.apply(thisArg, args); + } catch (error) { + // If exception is not thrown by a error listener and error listener is + // registered emit `error` event. Otherwise dump exception to the console. + if (type !== 'error') emit(target, 'error', error);else console.exception(error); + } + index++; + } + // Also emit on `"*"` so that one could listen for all events. + if (type !== '*') emit.apply(undefined, [target, '*', type].concat(args)); + } + exports.emitOnObject = emitOnObject; + + /** + * Removes an event `listener` for the given event `type` on the given event + * `target`. If no `listener` is passed removes all listeners of the given + * `type`. If `type` is not passed removes all the listeners of the given + * event `target`. + * @param {Object} target + * The event target object. + * @param {String} type + * The type of event. + * @param {Function} listener + * The listener function that processes the event. + */ + function off(target, type, listener) { + var length = arguments.length; + if (length === 3) { + if (onceWeakMap.has(listener)) { + listener = onceWeakMap.get(listener); + onceWeakMap.delete(listener); + } + + var listeners = observers(target, type); + var index = listeners.indexOf(listener); + if (~index) listeners.splice(index, 1); + } else if (length === 2) { + observers(target, type).splice(0); + } else if (length === 1) { + (function () { + var listeners = event(target); + Object.keys(listeners).forEach(type => delete listeners[type]); + })(); + } + } + exports.off = off; + + /** + * Returns a number of event listeners registered for the given event `type` + * on the given event `target`. + */ + function count(target, type) { + return observers(target, type).length; + } + exports.count = count; + + /** + * Registers listeners on the given event `target` from the given `listeners` + * dictionary. Iterates over the listeners and if property name matches name + * pattern `onEventType` and property is a function, then registers it as + * an `eventType` listener on `target`. + * + * @param {Object} target + * The type of event. + * @param {Object} listeners + * Dictionary of listeners. + */ + function setListeners(target, listeners) { + Object.keys(listeners || {}).forEach(key => { + var match = EVENT_TYPE_PATTERN.exec(key); + var type = match && match[1].toLowerCase(); + if (!type) return; + + var listener = listeners[key]; + if (typeof listener === 'function') on(target, type, listener); + }); + } + exports.setListeners = setListeners; + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(77)(module))) + +/***/ }, +/* 81 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(module) {/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + module.metadata = { + "stability": "unstable" + }; + + var create = Object.create; + var prototypeOf = Object.getPrototypeOf; + + /** + * Returns a new namespace, function that may can be used to access an + * namespaced object of the argument argument. Namespaced object are associated + * with owner objects via weak references. Namespaced objects inherit from the + * owners ancestor namespaced object. If owner's ancestor is `null` then + * namespaced object inherits from given `prototype`. Namespaces can be used + * to define internal APIs that can be shared via enclosing `namespace` + * function. + * @examples + * const internals = ns(); + * internals(object).secret = secret; + */ + function ns() { + var map = new WeakMap(); + return function namespace(target) { + if (!target) // If `target` is not an object return `target` itself. + return target; + // If target has no namespaced object yet, create one that inherits from + // the target prototype's namespaced object. + if (!map.has(target)) map.set(target, create(namespace(prototypeOf(target) || null))); + + return map.get(target); + }; + }; + + // `Namespace` is a e4x function in the scope, so we export the function also as + // `ns` as alias to avoid clashing. + exports.ns = ns; + exports.Namespace = ns; + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(77)(module))) + +/***/ }, +/* 82 */ +/***/ function(module, exports, __webpack_require__) { + + /* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */ + /* vim: set ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + var _require = __webpack_require__(61); + + var Cc = _require.Cc; + var Ci = _require.Ci; + var Cu = _require.Cu; + + var DevToolsUtils = __webpack_require__(68); + var EventEmitter = __webpack_require__(60); + var promise = __webpack_require__(66); + + var _require2 = __webpack_require__(79); + + var LongStringClient = _require2.LongStringClient; + + /** + * A WebConsoleClient is used as a front end for the WebConsoleActor that is + * created on the server, hiding implementation details. + * + * @param object aDebuggerClient + * The DebuggerClient instance we live for. + * @param object aResponse + * The response packet received from the "startListeners" request sent to + * the WebConsoleActor. + */ + + function WebConsoleClient(aDebuggerClient, aResponse) { + this._actor = aResponse.from; + this._client = aDebuggerClient; + this._longStrings = {}; + this.traits = aResponse.traits || {}; + this.events = []; + this._networkRequests = new Map(); + + this.pendingEvaluationResults = new Map(); + this.onEvaluationResult = this.onEvaluationResult.bind(this); + this.onNetworkEvent = this._onNetworkEvent.bind(this); + this.onNetworkEventUpdate = this._onNetworkEventUpdate.bind(this); + + this._client.addListener("evaluationResult", this.onEvaluationResult); + this._client.addListener("networkEvent", this.onNetworkEvent); + this._client.addListener("networkEventUpdate", this.onNetworkEventUpdate); + EventEmitter.decorate(this); + } + + exports.WebConsoleClient = WebConsoleClient; + + WebConsoleClient.prototype = { + _longStrings: null, + traits: null, + + /** + * Holds the network requests currently displayed by the Web Console. Each key + * represents the connection ID and the value is network request information. + * @private + * @type object + */ + _networkRequests: null, + + getNetworkRequest(actorId) { + return this._networkRequests.get(actorId); + }, + + hasNetworkRequest(actorId) { + return this._networkRequests.has(actorId); + }, + + removeNetworkRequest(actorId) { + this._networkRequests.delete(actorId); + }, + + getNetworkEvents() { + return this._networkRequests.values(); + }, + + get actor() { + return this._actor; + }, + + /** + * The "networkEvent" message type handler. We redirect any message to + * the UI for displaying. + * + * @private + * @param string type + * Message type. + * @param object packet + * The message received from the server. + */ + _onNetworkEvent: function (type, packet) { + if (packet.from == this._actor) { + var actor = packet.eventActor; + var networkInfo = { + _type: "NetworkEvent", + timeStamp: actor.timeStamp, + node: null, + actor: actor.actor, + discardRequestBody: true, + discardResponseBody: true, + startedDateTime: actor.startedDateTime, + request: { + url: actor.url, + method: actor.method + }, + isXHR: actor.isXHR, + response: {}, + timings: {}, + updates: [], // track the list of network event updates + private: actor.private, + fromCache: actor.fromCache + }; + this._networkRequests.set(actor.actor, networkInfo); + + this.emit("networkEvent", networkInfo); + } + }, + + /** + * The "networkEventUpdate" message type handler. We redirect any message to + * the UI for displaying. + * + * @private + * @param string type + * Message type. + * @param object packet + * The message received from the server. + */ + _onNetworkEventUpdate: function (type, packet) { + var networkInfo = this.getNetworkRequest(packet.from); + if (!networkInfo) { + return; + } + + networkInfo.updates.push(packet.updateType); + + switch (packet.updateType) { + case "requestHeaders": + networkInfo.request.headersSize = packet.headersSize; + break; + case "requestPostData": + networkInfo.discardRequestBody = packet.discardRequestBody; + networkInfo.request.bodySize = packet.dataSize; + break; + case "responseStart": + networkInfo.response.httpVersion = packet.response.httpVersion; + networkInfo.response.status = packet.response.status; + networkInfo.response.statusText = packet.response.statusText; + networkInfo.response.headersSize = packet.response.headersSize; + networkInfo.response.remoteAddress = packet.response.remoteAddress; + networkInfo.response.remotePort = packet.response.remotePort; + networkInfo.discardResponseBody = packet.response.discardResponseBody; + break; + case "responseContent": + networkInfo.response.content = { + mimeType: packet.mimeType + }; + networkInfo.response.bodySize = packet.contentSize; + networkInfo.response.transferredSize = packet.transferredSize; + networkInfo.discardResponseBody = packet.discardResponseBody; + break; + case "eventTimings": + networkInfo.totalTime = packet.totalTime; + break; + case "securityInfo": + networkInfo.securityInfo = packet.state; + break; + } + + this.emit("networkEventUpdate", { + packet: packet, + networkInfo + }); + }, + + /** + * Retrieve the cached messages from the server. + * + * @see this.CACHED_MESSAGES + * @param array types + * The array of message types you want from the server. See + * this.CACHED_MESSAGES for known types. + * @param function aOnResponse + * The function invoked when the response is received. + */ + getCachedMessages: function WCC_getCachedMessages(types, aOnResponse) { + var packet = { + to: this._actor, + type: "getCachedMessages", + messageTypes: types + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Inspect the properties of an object. + * + * @param string aActor + * The WebConsoleObjectActor ID to send the request to. + * @param function aOnResponse + * The function invoked when the response is received. + */ + inspectObjectProperties: function WCC_inspectObjectProperties(aActor, aOnResponse) { + var packet = { + to: aActor, + type: "inspectProperties" + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Evaluate a JavaScript expression. + * + * @param string aString + * The code you want to evaluate. + * @param function aOnResponse + * The function invoked when the response is received. + * @param object [aOptions={}] + * Options for evaluation: + * + * - bindObjectActor: an ObjectActor ID. The OA holds a reference to + * a Debugger.Object that wraps a content object. This option allows + * you to bind |_self| to the D.O of the given OA, during string + * evaluation. + * + * See: Debugger.Object.executeInGlobalWithBindings() for information + * about bindings. + * + * Use case: the variable view needs to update objects and it does so + * by knowing the ObjectActor it inspects and binding |_self| to the + * D.O of the OA. As such, variable view sends strings like these for + * eval: + * _self["prop"] = value; + * + * - frameActor: a FrameActor ID. The FA holds a reference to + * a Debugger.Frame. This option allows you to evaluate the string in + * the frame of the given FA. + * + * - url: the url to evaluate the script as. Defaults to + * "debugger eval code". + * + * - selectedNodeActor: the NodeActor ID of the current selection in the + * Inspector, if such a selection exists. This is used by helper functions + * that can reference the currently selected node in the Inspector, like + * $0. + */ + evaluateJS: function WCC_evaluateJS(aString, aOnResponse) { + var aOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + var packet = { + to: this._actor, + type: "evaluateJS", + text: aString, + bindObjectActor: aOptions.bindObjectActor, + frameActor: aOptions.frameActor, + url: aOptions.url, + selectedNodeActor: aOptions.selectedNodeActor, + selectedObjectActor: aOptions.selectedObjectActor + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Evaluate a JavaScript expression asynchronously. + * See evaluateJS for parameter and response information. + */ + evaluateJSAsync: function (aString, aOnResponse) { + var aOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + // Pre-37 servers don't support async evaluation. + if (!this.traits.evaluateJSAsync) { + this.evaluateJS(aString, aOnResponse, aOptions); + return; + } + + var packet = { + to: this._actor, + type: "evaluateJSAsync", + text: aString, + bindObjectActor: aOptions.bindObjectActor, + frameActor: aOptions.frameActor, + url: aOptions.url, + selectedNodeActor: aOptions.selectedNodeActor, + selectedObjectActor: aOptions.selectedObjectActor + }; + + this._client.request(packet, response => { + // Null check this in case the client has been detached while waiting + // for a response. + if (this.pendingEvaluationResults) { + this.pendingEvaluationResults.set(response.resultID, aOnResponse); + } + }); + }, + + /** + * Handler for the actors's unsolicited evaluationResult packet. + */ + onEvaluationResult: function (aNotification, aPacket) { + // The client on the main thread can receive notification packets from + // multiple webconsole actors: the one on the main thread and the ones + // on worker threads. So make sure we should be handling this request. + if (aPacket.from !== this._actor) { + return; + } + + // Find the associated callback based on this ID, and fire it. + // In a sync evaluation, this would have already been called in + // direct response to the client.request function. + var onResponse = this.pendingEvaluationResults.get(aPacket.resultID); + if (onResponse) { + onResponse(aPacket); + this.pendingEvaluationResults.delete(aPacket.resultID); + } else { + DevToolsUtils.reportException("onEvaluationResult", "No response handler for an evaluateJSAsync result (resultID: " + aPacket.resultID + ")"); + } + }, + + /** + * Autocomplete a JavaScript expression. + * + * @param string aString + * The code you want to autocomplete. + * @param number aCursor + * Cursor location inside the string. Index starts from 0. + * @param function aOnResponse + * The function invoked when the response is received. + * @param string aFrameActor + * The id of the frame actor that made the call. + */ + autocomplete: function WCC_autocomplete(aString, aCursor, aOnResponse, aFrameActor) { + var packet = { + to: this._actor, + type: "autocomplete", + text: aString, + cursor: aCursor, + frameActor: aFrameActor + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Clear the cache of messages (page errors and console API calls). + */ + clearMessagesCache: function WCC_clearMessagesCache() { + var packet = { + to: this._actor, + type: "clearMessagesCache" + }; + this._client.request(packet); + }, + + /** + * Get Web Console-related preferences on the server. + * + * @param array aPreferences + * An array with the preferences you want to retrieve. + * @param function [aOnResponse] + * Optional function to invoke when the response is received. + */ + getPreferences: function WCC_getPreferences(aPreferences, aOnResponse) { + var packet = { + to: this._actor, + type: "getPreferences", + preferences: aPreferences + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Set Web Console-related preferences on the server. + * + * @param object aPreferences + * An object with the preferences you want to change. + * @param function [aOnResponse] + * Optional function to invoke when the response is received. + */ + setPreferences: function WCC_setPreferences(aPreferences, aOnResponse) { + var packet = { + to: this._actor, + type: "setPreferences", + preferences: aPreferences + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Retrieve the request headers from the given NetworkEventActor. + * + * @param string aActor + * The NetworkEventActor ID. + * @param function aOnResponse + * The function invoked when the response is received. + */ + getRequestHeaders: function WCC_getRequestHeaders(aActor, aOnResponse) { + var packet = { + to: aActor, + type: "getRequestHeaders" + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Retrieve the request cookies from the given NetworkEventActor. + * + * @param string aActor + * The NetworkEventActor ID. + * @param function aOnResponse + * The function invoked when the response is received. + */ + getRequestCookies: function WCC_getRequestCookies(aActor, aOnResponse) { + var packet = { + to: aActor, + type: "getRequestCookies" + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Retrieve the request post data from the given NetworkEventActor. + * + * @param string aActor + * The NetworkEventActor ID. + * @param function aOnResponse + * The function invoked when the response is received. + */ + getRequestPostData: function WCC_getRequestPostData(aActor, aOnResponse) { + var packet = { + to: aActor, + type: "getRequestPostData" + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Retrieve the response headers from the given NetworkEventActor. + * + * @param string aActor + * The NetworkEventActor ID. + * @param function aOnResponse + * The function invoked when the response is received. + */ + getResponseHeaders: function WCC_getResponseHeaders(aActor, aOnResponse) { + var packet = { + to: aActor, + type: "getResponseHeaders" + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Retrieve the response cookies from the given NetworkEventActor. + * + * @param string aActor + * The NetworkEventActor ID. + * @param function aOnResponse + * The function invoked when the response is received. + */ + getResponseCookies: function WCC_getResponseCookies(aActor, aOnResponse) { + var packet = { + to: aActor, + type: "getResponseCookies" + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Retrieve the response content from the given NetworkEventActor. + * + * @param string aActor + * The NetworkEventActor ID. + * @param function aOnResponse + * The function invoked when the response is received. + */ + getResponseContent: function WCC_getResponseContent(aActor, aOnResponse) { + var packet = { + to: aActor, + type: "getResponseContent" + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Retrieve the timing information for the given NetworkEventActor. + * + * @param string aActor + * The NetworkEventActor ID. + * @param function aOnResponse + * The function invoked when the response is received. + */ + getEventTimings: function WCC_getEventTimings(aActor, aOnResponse) { + var packet = { + to: aActor, + type: "getEventTimings" + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Retrieve the security information for the given NetworkEventActor. + * + * @param string aActor + * The NetworkEventActor ID. + * @param function aOnResponse + * The function invoked when the response is received. + */ + getSecurityInfo: function WCC_getSecurityInfo(aActor, aOnResponse) { + var packet = { + to: aActor, + type: "getSecurityInfo" + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Send a HTTP request with the given data. + * + * @param string aData + * The details of the HTTP request. + * @param function aOnResponse + * The function invoked when the response is received. + */ + sendHTTPRequest: function WCC_sendHTTPRequest(aData, aOnResponse) { + var packet = { + to: this._actor, + type: "sendHTTPRequest", + request: aData + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Start the given Web Console listeners. + * + * @see this.LISTENERS + * @param array aListeners + * Array of listeners you want to start. See this.LISTENERS for + * known listeners. + * @param function aOnResponse + * Function to invoke when the server response is received. + */ + startListeners: function WCC_startListeners(aListeners, aOnResponse) { + var packet = { + to: this._actor, + type: "startListeners", + listeners: aListeners + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Stop the given Web Console listeners. + * + * @see this.LISTENERS + * @param array aListeners + * Array of listeners you want to stop. See this.LISTENERS for + * known listeners. + * @param function aOnResponse + * Function to invoke when the server response is received. + */ + stopListeners: function WCC_stopListeners(aListeners, aOnResponse) { + var packet = { + to: this._actor, + type: "stopListeners", + listeners: aListeners + }; + this._client.request(packet, aOnResponse); + }, + + /** + * Return an instance of LongStringClient for the given long string grip. + * + * @param object aGrip + * The long string grip returned by the protocol. + * @return object + * The LongStringClient for the given long string grip. + */ + longString: function WCC_longString(aGrip) { + if (aGrip.actor in this._longStrings) { + return this._longStrings[aGrip.actor]; + } + + var client = new LongStringClient(this._client, aGrip); + this._longStrings[aGrip.actor] = client; + return client; + }, + + /** + * Close the WebConsoleClient. This stops all the listeners on the server and + * detaches from the console actor. + * + * @param function aOnResponse + * Function to invoke when the server response is received. + */ + detach: function WCC_detach(aOnResponse) { + this._client.removeListener("evaluationResult", this.onEvaluationResult); + this._client.removeListener("networkEvent", this.onNetworkEvent); + this._client.removeListener("networkEventUpdate", this.onNetworkEventUpdate); + this.stopListeners(null, aOnResponse); + this._longStrings = null; + this._client = null; + this.pendingEvaluationResults.clear(); + this.pendingEvaluationResults = null; + this.clearNetworkRequests(); + this._networkRequests = null; + }, + + clearNetworkRequests: function () { + this._networkRequests.clear(); + }, + + /** + * Fetches the full text of a LongString. + * + * @param object | string stringGrip + * The long string grip containing the corresponding actor. + * If you pass in a plain string (by accident or because you're lazy), + * then a promise of the same string is simply returned. + * @return object Promise + * A promise that is resolved when the full string contents + * are available, or rejected if something goes wrong. + */ + getString: function (stringGrip) { + // Make sure this is a long string. + if (typeof stringGrip != "object" || stringGrip.type != "longString") { + return promise.resolve(stringGrip); // Go home string, you're drunk. + } + + // Fetch the long string only once. + if (stringGrip._fullText) { + return stringGrip._fullText.promise; + } + + var deferred = stringGrip._fullText = promise.defer(); + var actor = stringGrip.actor; + var initial = stringGrip.initial; + var length = stringGrip.length; + + var longStringClient = this.longString(stringGrip); + + longStringClient.substring(initial.length, length, aResponse => { + if (aResponse.error) { + DevToolsUtils.reportException("getString", aResponse.error + ": " + aResponse.message); + + deferred.reject(aResponse); + return; + } + deferred.resolve(initial + aResponse.substring); + }); + + return deferred.promise; + } + }; + +/***/ }, +/* 83 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + const { Services } = __webpack_require__(30); + const EventEmitter = __webpack_require__(60); + + /** + * Shortcuts for lazily accessing and setting various preferences. + * Usage: + * let prefs = new Prefs("root.path.to.branch", { + * myIntPref: ["Int", "leaf.path.to.my-int-pref"], + * myCharPref: ["Char", "leaf.path.to.my-char-pref"], + * myJsonPref: ["Json", "leaf.path.to.my-json-pref"], + * myFloatPref: ["Float", "leaf.path.to.my-float-pref"] + * ... + * }); + * + * Get/set: + * prefs.myCharPref = "foo"; + * let aux = prefs.myCharPref; + * + * Observe: + * prefs.registerObserver(); + * prefs.on("pref-changed", (prefName, prefValue) => { + * ... + * }); + * + * @param string prefsRoot + * The root path to the required preferences branch. + * @param object prefsBlueprint + * An object containing { accessorName: [prefType, prefName] } keys. + */ + function PrefsHelper(prefsRoot = "", prefsBlueprint = {}) { + EventEmitter.decorate(this); + + let cache = new Map(); + + for (let accessorName in prefsBlueprint) { + let [prefType, prefName] = prefsBlueprint[accessorName]; + map(this, cache, accessorName, prefType, prefsRoot, prefName); + } + + let observer = makeObserver(this, cache, prefsRoot, prefsBlueprint); + this.registerObserver = () => observer.register(); + this.unregisterObserver = () => observer.unregister(); + } + + /** + * Helper method for getting a pref value. + * + * @param Map cache + * @param string prefType + * @param string prefsRoot + * @param string prefName + * @return any + */ + function get(cache, prefType, prefsRoot, prefName) { + let cachedPref = cache.get(prefName); + if (cachedPref !== undefined) { + return cachedPref; + } + let value = Services.prefs["get" + prefType + "Pref"]( + [prefsRoot, prefName].join(".") + ); + cache.set(prefName, value); + return value; + } + + /** + * Helper method for setting a pref value. + * + * @param Map cache + * @param string prefType + * @param string prefsRoot + * @param string prefName + * @param any value + */ + function set(cache, prefType, prefsRoot, prefName, value) { + Services.prefs["set" + prefType + "Pref"]( + [prefsRoot, prefName].join("."), + value + ); + cache.set(prefName, value); + } + + /** + * Maps a property name to a pref, defining lazy getters and setters. + * Supported types are "Bool", "Char", "Int", "Float" (sugar around "Char" + * type and casting), and "Json" (which is basically just sugar for "Char" + * using the standard JSON serializer). + * + * @param PrefsHelper self + * @param Map cache + * @param string accessorName + * @param string prefType + * @param string prefsRoot + * @param string prefName + * @param array serializer [optional] + */ + function map(self, cache, accessorName, prefType, prefsRoot, prefName, + serializer = { in: e => e, out: e => e }) { + if (prefName in self) { + throw new Error(`Can't use ${prefName} because it overrides a property` + + "on the instance."); + } + if (prefType == "Json") { + map(self, cache, accessorName, "Char", prefsRoot, prefName, { + in: JSON.parse, + out: JSON.stringify + }); + return; + } + if (prefType == "Float") { + map(self, cache, accessorName, "Char", prefsRoot, prefName, { + in: Number.parseFloat, + out: (n) => n + "" + }); + return; + } + + Object.defineProperty(self, accessorName, { + get: () => serializer.in(get(cache, prefType, prefsRoot, prefName)), + set: (e) => set(cache, prefType, prefsRoot, prefName, serializer.out(e)) + }); + } + + /** + * Finds the accessor for the provided pref, based on the blueprint object + * used in the constructor. + * + * @param PrefsHelper self + * @param object prefsBlueprint + * @return string + */ + function accessorNameForPref(somePrefName, prefsBlueprint) { + for (let accessorName in prefsBlueprint) { + let [, prefName] = prefsBlueprint[accessorName]; + if (somePrefName == prefName) { + return accessorName; + } + } + return ""; + } + + /** + * Creates a pref observer for `self`. + * + * @param PrefsHelper self + * @param Map cache + * @param string prefsRoot + * @param object prefsBlueprint + * @return object + */ + function makeObserver(self, cache, prefsRoot, prefsBlueprint) { + return { + register: function() { + this._branch = Services.prefs.getBranch(prefsRoot + "."); + this._branch.addObserver("", this, false); + }, + unregister: function() { + this._branch.removeObserver("", this); + }, + observe: function(subject, topic, prefName) { + // If this particular pref isn't handled by the blueprint object, + // even though it's in the specified branch, ignore it. + let accessorName = accessorNameForPref(prefName, prefsBlueprint); + if (!(accessorName in self)) { + return; + } + cache.delete(prefName); + self.emit("pref-changed", accessorName, self[accessorName]); + } + }; + } + + exports.PrefsHelper = PrefsHelper; + + +/***/ }, +/* 84 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var promise = __webpack_require__(66); + var EventEmitter = __webpack_require__(60); + + /* const { DebuggerServer } = require("../../server/main");*/ + + var _require = __webpack_require__(79); + + var DebuggerClient = _require.DebuggerClient; + + + var targets = new WeakMap(); + var promiseTargets = new WeakMap(); + + /** + * Functions for creating Targets + */ + exports.TargetFactory = { + /** + * Construct a Target + * @param {XULTab} tab + * The tab to use in creating a new target. + * + * @return A target object + */ + forTab: function (tab) { + var target = targets.get(tab); + if (target == null) { + target = new TabTarget(tab); + targets.set(tab, target); + } + return target; + }, + + /** + * Return a promise of a Target for a remote tab. + * @param {Object} options + * The options object has the following properties: + * { + * form: the remote protocol form of a tab, + * client: a DebuggerClient instance + * (caller owns this and is responsible for closing), + * chrome: true if the remote target is the whole process + * } + * + * @return A promise of a target object + */ + forRemoteTab: function (options) { + var targetPromise = promiseTargets.get(options); + if (targetPromise == null) { + (function () { + var target = new TabTarget(options); + targetPromise = target.makeRemote().then(() => target); + promiseTargets.set(options, targetPromise); + })(); + } + return targetPromise; + }, + + forWorker: function (workerClient) { + var target = targets.get(workerClient); + if (target == null) { + target = new WorkerTarget(workerClient); + targets.set(workerClient, target); + } + return target; + }, + + /** + * Creating a target for a tab that is being closed is a problem because it + * allows a leak as a result of coming after the close event which normally + * clears things up. This function allows us to ask if there is a known + * target for a tab without creating a target + * @return true/false + */ + isKnownTab: function (tab) { + return targets.has(tab); + } + }; + + /** + * A Target represents something that we can debug. Targets are generally + * read-only. Any changes that you wish to make to a target should be done via + * a Tool that attaches to the target. i.e. a Target is just a pointer saying + * "the thing to debug is over there". + * + * Providing a generalized abstraction of a web-page or web-browser (available + * either locally or remotely) is beyond the scope of this class (and maybe + * also beyond the scope of this universe) However Target does attempt to + * abstract some common events and read-only properties common to many Tools. + * + * Supported read-only properties: + * - name, isRemote, url + * + * Target extends EventEmitter and provides support for the following events: + * - close: The target window has been closed. All tools attached to this + * target should close. This event is not currently cancelable. + * - navigate: The target window has navigated to a different URL + * + * Optional events: + * - will-navigate: The target window will navigate to a different URL + * - hidden: The target is not visible anymore (for TargetTab, another tab is + * selected) + * - visible: The target is visible (for TargetTab, tab is selected) + * + * Comparing Targets: 2 instances of a Target object can point at the same + * thing, so t1 !== t2 and t1 != t2 even when they represent the same object. + * To compare to targets use 't1.equals(t2)'. + */ + + /** + * A TabTarget represents a page living in a browser tab. Generally these will + * be web pages served over http(s), but they don't have to be. + */ + function TabTarget(tab) { + EventEmitter.decorate(this); + this.destroy = this.destroy.bind(this); + this._handleThreadState = this._handleThreadState.bind(this); + this.on("thread-resumed", this._handleThreadState); + this.on("thread-paused", this._handleThreadState); + this.activeTab = this.activeConsole = null; + // Only real tabs need initialization here. Placeholder objects for remote + // targets will be initialized after a makeRemote method call. + if (tab && !["client", "form", "chrome"].every(tab.hasOwnProperty, tab)) { + this._tab = tab; + this._setupListeners(); + } else { + this._form = tab.form; + this._client = tab.client; + this._chrome = tab.chrome; + } + // Default isTabActor to true if not explicitly specified + if (typeof tab.isTabActor == "boolean") { + this._isTabActor = tab.isTabActor; + } else { + this._isTabActor = true; + } + } + + TabTarget.prototype = { + _webProgressListener: null, + + /** + * Returns a promise for the protocol description from the root actor. Used + * internally with `target.actorHasMethod`. Takes advantage of caching if + * definition was fetched previously with the corresponding actor information. + * Actors are lazily loaded, so not only must the tool using a specific actor + * be in use, the actors are only registered after invoking a method (for + * performance reasons, added in bug 988237), so to use these actor detection + * methods, one must already be communicating with a specific actor of that + * type. + * + * Must be a remote target. + * + * @return {Promise} + * { + * "category": "actor", + * "typeName": "longstractor", + * "methods": [{ + * "name": "substring", + * "request": { + * "type": "substring", + * "start": { + * "_arg": 0, + * "type": "primitive" + * }, + * "end": { + * "_arg": 1, + * "type": "primitive" + * } + * }, + * "response": { + * "substring": { + * "_retval": "primitive" + * } + * } + * }], + * "events": {} + * } + */ + getActorDescription: function (actorName) { + if (!this.client) { + throw new Error("TabTarget#getActorDescription() can only be called on " + "remote tabs."); + } + + var deferred = promise.defer(); + + if (this._protocolDescription && this._protocolDescription.types[actorName]) { + deferred.resolve(this._protocolDescription.types[actorName]); + } else { + this.client.mainRoot.protocolDescription(description => { + this._protocolDescription = description; + deferred.resolve(description.types[actorName]); + }); + } + + return deferred.promise; + }, + + /** + * Returns a boolean indicating whether or not the specific actor + * type exists. Must be a remote target. + * + * @param {String} actorName + * @return {Boolean} + */ + hasActor: function (actorName) { + if (!this.client) { + throw new Error("TabTarget#hasActor() can only be called on remote " + "tabs."); + } + if (this.form) { + return !!this.form[actorName + "Actor"]; + } + return false; + }, + + /** + * Queries the protocol description to see if an actor has + * an available method. The actor must already be lazily-loaded (read + * the restrictions in the `getActorDescription` comments), + * so this is for use inside of tool. Returns a promise that + * resolves to a boolean. Must be a remote target. + * + * @param {String} actorName + * @param {String} methodName + * @return {Promise} + */ + actorHasMethod: function (actorName, methodName) { + if (!this.client) { + throw new Error("TabTarget#actorHasMethod() can only be called on " + "remote tabs."); + } + return this.getActorDescription(actorName).then(desc => { + if (desc && desc.methods) { + return !!desc.methods.find(method => method.name === methodName); + } + return false; + }); + }, + + /** + * Returns a trait from the root actor. + * + * @param {String} traitName + * @return {Mixed} + */ + getTrait: function (traitName) { + if (!this.client) { + throw new Error("TabTarget#getTrait() can only be called on remote " + "tabs."); + } + + // If the targeted actor exposes traits and has a defined value for this + // traits, override the root actor traits + if (this.form.traits && traitName in this.form.traits) { + return this.form.traits[traitName]; + } + + return this.client.traits[traitName]; + }, + + get tab() { + return this._tab; + }, + + get form() { + return this._form; + }, + + // Get a promise of the root form returned by a listTabs request. This promise + // is cached. + get root() { + if (!this._root) { + this._root = this._getRoot(); + } + return this._root; + }, + + _getRoot: function () { + return new Promise((resolve, reject) => { + this.client.listTabs(response => { + if (response.error) { + reject(new Error(response.error + ": " + response.message)); + return; + } + + resolve(response); + }); + }); + }, + + get client() { + return this._client; + }, + + // Tells us if we are debugging content document + // or if we are debugging chrome stuff. + // Allows to controls which features are available against + // a chrome or a content document. + get chrome() { + return this._chrome; + }, + + // Tells us if the related actor implements TabActor interface + // and requires to call `attach` request before being used + // and `detach` during cleanup + get isTabActor() { + return this._isTabActor; + }, + + get window() { + // XXX - this is a footgun for e10s - there .contentWindow will be null, + // and even though .contentWindowAsCPOW *might* work, it will not work + // in all contexts. Consumers of .window need to be refactored to not + // rely on this. + // if (Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { + // console.error("The .window getter on devtools' |target| object isn't " + + // "e10s friendly!\n" + Error().stack); + // } + // Be extra careful here, since this may be called by HS_getHudByWindow + // during shutdown. + if (this._tab && this._tab.linkedBrowser) { + return this._tab.linkedBrowser.contentWindow; + } + return null; + }, + + get name() { + if (this._tab && this._tab.linkedBrowser.contentDocument) { + return this._tab.linkedBrowser.contentDocument.title; + } + if (this.isAddon) { + return this._form.name; + } + return this._form.title; + }, + + get url() { + return this._tab ? this._tab.linkedBrowser.currentURI.spec : this._form.url; + }, + + get isRemote() { + return !this.isLocalTab; + }, + + get isAddon() { + return !!(this._form && this._form.actor && this._form.actor.match(/conn\d+\.addon\d+/)); + }, + + get isLocalTab() { + return !!this._tab; + }, + + get isMultiProcess() { + return !this.window; + }, + + get isThreadPaused() { + return !!this._isThreadPaused; + }, + + /** + * Adds remote protocol capabilities to the target, so that it can be used + * for tools that support the Remote Debugging Protocol even for local + * connections. + */ + makeRemote: function () { + if (this._remote) { + return this._remote.promise; + } + + this._remote = promise.defer(); + + if (this.isLocalTab) { + // Since a remote protocol connection will be made, let's start the + // DebuggerServer here, once and for all tools. + if (!DebuggerServer.initialized) { + DebuggerServer.init(); + DebuggerServer.addBrowserActors(); + } + + this._client = new DebuggerClient(DebuggerServer.connectPipe()); + // A local TabTarget will never perform chrome debugging. + this._chrome = false; + } + + this._setupRemoteListeners(); + + var attachTab = () => { + this._client.attachTab(this._form.actor, (response, tabClient) => { + if (!tabClient) { + this._remote.reject("Unable to attach to the tab"); + return; + } + this.activeTab = tabClient; + this.threadActor = response.threadActor; + attachConsole(); + }); + }; + + var onConsoleAttached = (response, consoleClient) => { + if (!consoleClient) { + this._remote.reject("Unable to attach to the console"); + return; + } + this.activeConsole = consoleClient; + this._remote.resolve(null); + }; + + var attachConsole = () => { + this._client.attachConsole(this._form.consoleActor, ["NetworkActivity"], onConsoleAttached); + }; + + if (this.isLocalTab) { + this._client.connect(() => { + this._client.getTab({ tab: this.tab }).then(response => { + this._form = response.tab; + attachTab(); + }); + }); + } else if (this.isTabActor) { + // In the remote debugging case, the protocol connection will have been + // already initialized in the connection screen code. + attachTab(); + } else { + // AddonActor and chrome debugging on RootActor doesn't inherits from + // TabActor and doesn't need to be attached. + attachConsole(); + } + + return this._remote.promise; + }, + + /** + * Listen to the different events. + */ + _setupListeners: function () { + this._webProgressListener = new TabWebProgressListener(this); + this.tab.linkedBrowser.addProgressListener(this._webProgressListener); + this.tab.addEventListener("TabClose", this); + this.tab.parentNode.addEventListener("TabSelect", this); + this.tab.ownerDocument.defaultView.addEventListener("unload", this); + }, + + /** + * Teardown event listeners. + */ + _teardownListeners: function () { + if (this._webProgressListener) { + this._webProgressListener.destroy(); + } + + this._tab.ownerDocument.defaultView.removeEventListener("unload", this); + this._tab.removeEventListener("TabClose", this); + this._tab.parentNode.removeEventListener("TabSelect", this); + }, + + /** + * Setup listeners for remote debugging, updating existing ones as necessary. + */ + _setupRemoteListeners: function () { + this.client.addListener("closed", this.destroy); + + this._onTabDetached = (aType, aPacket) => { + // We have to filter message to ensure that this detach is for this tab + if (aPacket.from == this._form.actor) { + this.destroy(); + } + }; + this.client.addListener("tabDetached", this._onTabDetached); + + this._onTabNavigated = (aType, aPacket) => { + var event = Object.create(null); + event.url = aPacket.url; + event.title = aPacket.title; + event.nativeConsoleAPI = aPacket.nativeConsoleAPI; + event.isFrameSwitching = aPacket.isFrameSwitching; + // Send any stored event payload (DOMWindow or nsIRequest) for backwards + // compatibility with non-remotable tools. + if (aPacket.state == "start") { + event._navPayload = this._navRequest; + this.emit("will-navigate", event); + this._navRequest = null; + } else { + event._navPayload = this._navWindow; + this.emit("navigate", event); + this._navWindow = null; + } + }; + this.client.addListener("tabNavigated", this._onTabNavigated); + + this._onFrameUpdate = (aType, aPacket) => { + this.emit("frame-update", aPacket); + }; + this.client.addListener("frameUpdate", this._onFrameUpdate); + }, + + /** + * Teardown listeners for remote debugging. + */ + _teardownRemoteListeners: function () { + this.client.removeListener("closed", this.destroy); + this.client.removeListener("tabNavigated", this._onTabNavigated); + this.client.removeListener("tabDetached", this._onTabDetached); + this.client.removeListener("frameUpdate", this._onFrameUpdate); + }, + + /** + * Handle tabs events. + */ + handleEvent: function (event) { + switch (event.type) { + case "TabClose": + case "unload": + this.destroy(); + break; + case "TabSelect": + if (this.tab.selected) { + this.emit("visible", event); + } else { + this.emit("hidden", event); + } + break; + } + }, + + /** + * Handle script status. + */ + _handleThreadState: function (event) { + switch (event) { + case "thread-resumed": + this._isThreadPaused = false; + break; + case "thread-paused": + this._isThreadPaused = true; + break; + } + }, + + /** + * Target is not alive anymore. + */ + destroy: function () { + // If several things call destroy then we give them all the same + // destruction promise so we're sure to destroy only once + if (this._destroyer) { + return this._destroyer.promise; + } + + this._destroyer = promise.defer(); + + // Before taking any action, notify listeners that destruction is imminent. + this.emit("close"); + + // First of all, do cleanup tasks that pertain to both remoted and + // non-remoted targets. + this.off("thread-resumed", this._handleThreadState); + this.off("thread-paused", this._handleThreadState); + + if (this._tab) { + this._teardownListeners(); + } + + var cleanupAndResolve = () => { + this._cleanup(); + this._destroyer.resolve(null); + }; + // If this target was not remoted, the promise will be resolved before the + // function returns. + if (this._tab && !this._client) { + cleanupAndResolve(); + } else if (this._client) { + // If, on the other hand, this target was remoted, the promise will be + // resolved after the remote connection is closed. + this._teardownRemoteListeners(); + + if (this.isLocalTab) { + // We started with a local tab and created the client ourselves, so we + // should close it. + this._client.close(cleanupAndResolve); + } else if (this.activeTab) { + // The client was handed to us, so we are not responsible for closing + // it. We just need to detach from the tab, if already attached. + // |detach| may fail if the connection is already dead, so proceed with + // cleanup directly after this. + this.activeTab.detach(); + cleanupAndResolve(); + } else { + cleanupAndResolve(); + } + } + + return this._destroyer.promise; + }, + + /** + * Clean up references to what this target points to. + */ + _cleanup: function () { + if (this._tab) { + targets.delete(this._tab); + } else { + promiseTargets.delete(this._form); + } + this.activeTab = null; + this.activeConsole = null; + this._client = null; + this._tab = null; + this._form = null; + this._remote = null; + }, + + toString: function () { + var id = this._tab ? this._tab : this._form && this._form.actor; + return `TabTarget:${ id }`; + } + }; + + function WorkerTarget(workerClient) { + EventEmitter.decorate(this); + this._workerClient = workerClient; + } + + /** + * A WorkerTarget represents a worker. Unlike TabTarget, which can represent + * either a local or remote tab, WorkerTarget always represents a remote worker. + * Moreover, unlike TabTarget, which is constructed with a placeholder object + * for remote tabs (from which a TabClient can then be lazily obtained), + * WorkerTarget is constructed with a WorkerClient directly. + * + * WorkerClient is designed to mimic the interface of TabClient as closely as + * possible. This allows us to debug workers as if they were ordinary tabs, + * requiring only minimal changes to the rest of the frontend. + */ + WorkerTarget.prototype = { + destroy: function () {}, + + get isRemote() { + return true; + }, + + get isTabActor() { + return true; + }, + + get url() { + return this._workerClient.url; + }, + + get isWorkerTarget() { + return true; + }, + + get form() { + return { + consoleActor: this._workerClient.consoleActor + }; + }, + + get activeTab() { + return this._workerClient; + }, + + get client() { + return this._workerClient.client; + }, + + destroy: function () {}, + + hasActor: function (name) { + return false; + }, + + getTrait: function () { + return undefined; + }, + + makeRemote: function () { + return Promise.resolve(); + } + }; + +/***/ }, +/* 85 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + var EventEmitter = __webpack_require__(60); + + function WebSocketDebuggerTransport(socket) { + EventEmitter.decorate(this); + + this.active = false; + this.hooks = null; + this.socket = socket; + } + + WebSocketDebuggerTransport.prototype = { + ready() { + if (this.active) { + return; + } + + this.socket.addEventListener("message", this); + this.socket.addEventListener("close", this); + + this.active = true; + }, + + send(object) { + this.emit("send", object); + if (this.socket) { + this.socket.send(JSON.stringify(object)); + } + }, + + startBulkSend() { + throw new Error("Bulk send is not supported by WebSocket transport"); + }, + + close() { + this.emit("close"); + this.active = false; + + this.socket.removeEventListener("message", this); + this.socket.removeEventListener("close", this); + this.socket.close(); + this.socket = null; + + if (this.hooks) { + this.hooks.onClosed(); + this.hooks = null; + } + }, + + handleEvent(event) { + switch (event.type) { + case "message": + this.onMessage(event); + break; + case "close": + this.close(); + break; + } + }, + + onMessage(_ref) { + var data = _ref.data; + + if (typeof data !== "string") { + throw new Error("Binary messages are not supported by WebSocket transport"); + } + + var object = JSON.parse(data); + this.emit("packet", object); + if (this.hooks) { + this.hooks.onPacket(object); + } + } + }; + + module.exports = WebSocketDebuggerTransport; + +/***/ }, +/* 86 */ +/***/ function(module, exports, __webpack_require__) { + + /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + var EventEmitter = __webpack_require__(60); + + /** + * A partial implementation of the Menu API provided by electron: + * https://github.com/electron/electron/blob/master/docs/api/menu.md. + * + * Extra features: + * - Emits an 'open' and 'close' event when the menu is opened/closed + + * @param String id (non standard) + * Needed so tests can confirm the XUL implementation is working + */ + function Menu() { + var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + var _ref$id = _ref.id; + var id = _ref$id === undefined ? null : _ref$id; + + this.menuitems = []; + this.id = id; + + Object.defineProperty(this, "items", { + get() { + return this.menuitems; + } + }); + + EventEmitter.decorate(this); + } + + /** + * Add an item to the end of the Menu + * + * @param {MenuItem} menuItem + */ + Menu.prototype.append = function (menuItem) { + this.menuitems.push(menuItem); + }; + + /** + * Add an item to a specified position in the menu + * + * @param {int} pos + * @param {MenuItem} menuItem + */ + Menu.prototype.insert = function (pos, menuItem) { + throw Error("Not implemented"); + }; + + /** + * Show the Menu at a specified location on the screen + * + * Missing features: + * - browserWindow - BrowserWindow (optional) - Default is null. + * - positioningItem Number - (optional) OS X + * + * @param {int} screenX + * @param {int} screenY + * @param Toolbox toolbox (non standard) + * Needed so we in which window to inject XUL + */ + Menu.prototype.popup = function (screenX, screenY, toolbox) { + var doc = toolbox.doc; + var popupset = doc.querySelector("popupset"); + // See bug 1285229, on Windows, opening the same popup multiple times in a + // row ends up duplicating the popup. The newly inserted popup doesn't + // dismiss the old one. So remove any previously displayed popup before + // opening a new one. + var popup = popupset.querySelector("menupopup[menu-api=\"true\"]"); + if (popup) { + popup.hidePopup(); + } + + popup = this.createPopup(doc); + popup.setAttribute("menu-api", "true"); + + if (this.id) { + popup.id = this.id; + } + this._createMenuItems(popup); + + // Remove the menu from the DOM once it's hidden. + popup.addEventListener("popuphidden", e => { + if (e.target === popup) { + popup.remove(); + this.emit("close", popup); + } + }); + + popup.addEventListener("popupshown", e => { + if (e.target === popup) { + this.emit("open", popup); + } + }); + + popupset.appendChild(popup); + popup.openPopupAtScreen(screenX, screenY, true); + }; + + Menu.prototype.createPopup = function (doc) { + return doc.createElement("menupopup"); + }; + + Menu.prototype._createMenuItems = function (parent) { + var doc = parent.ownerDocument; + this.menuitems.forEach(item => { + if (!item.visible) { + return; + } + + if (item.submenu) { + var menupopup = doc.createElement("menupopup"); + item.submenu._createMenuItems(menupopup); + + var menu = doc.createElement("menu"); + menu.appendChild(menupopup); + menu.setAttribute("label", item.label); + if (item.disabled) { + menu.setAttribute("disabled", "true"); + } + if (item.accesskey) { + menu.setAttribute("accesskey", item.accesskey); + } + if (item.id) { + menu.id = item.id; + } + parent.appendChild(menu); + } else if (item.type === "separator") { + var menusep = doc.createElement("menuseparator"); + parent.appendChild(menusep); + } else { + var menuitem = doc.createElement("menuitem"); + menuitem.setAttribute("label", item.label); + menuitem.textContent = item.label; + menuitem.addEventListener("command", () => item.click()); + + if (item.type === "checkbox") { + menuitem.setAttribute("type", "checkbox"); + } + if (item.type === "radio") { + menuitem.setAttribute("type", "radio"); + } + if (item.disabled) { + menuitem.setAttribute("disabled", "true"); + } + if (item.checked) { + menuitem.setAttribute("checked", "true"); + } + if (item.accesskey) { + menuitem.setAttribute("accesskey", item.accesskey); + } + if (item.id) { + menuitem.id = item.id; + } + + parent.appendChild(menuitem); + } + }); + }; + + Menu.setApplicationMenu = () => { + throw Error("Not implemented"); + }; + + Menu.sendActionToFirstResponder = () => { + throw Error("Not implemented"); + }; + + Menu.buildFromTemplate = () => { + throw Error("Not implemented"); + }; + + module.exports = Menu; + +/***/ }, +/* 87 */ +/***/ function(module, exports) { + + /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + "use strict"; + + /** + * A partial implementation of the MenuItem API provided by electron: + * https://github.com/electron/electron/blob/master/docs/api/menu-item.md. + * + * Missing features: + * - id String - Unique within a single menu. If defined then it can be used + * as a reference to this item by the position attribute. + * - role String - Define the action of the menu item; when specified the + * click property will be ignored + * - sublabel String + * - accelerator Accelerator + * - icon NativeImage + * - position String - This field allows fine-grained definition of the + * specific location within a given menu. + * + * Implemented features: + * @param Object options + * Function click + * Will be called with click(menuItem, browserWindow) when the menu item + * is clicked + * String type + * Can be normal, separator, submenu, checkbox or radio + * String label + * Boolean enabled + * If false, the menu item will be greyed out and unclickable. + * Boolean checked + * Should only be specified for checkbox or radio type menu items. + * Menu submenu + * Should be specified for submenu type menu items. If submenu is specified, + * the type: 'submenu' can be omitted. If the value is not a Menu then it + * will be automatically converted to one using Menu.buildFromTemplate. + * Boolean visible + * If false, the menu item will be entirely hidden. + */ + + function MenuItem() { + var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + var _ref$accesskey = _ref.accesskey; + var accesskey = _ref$accesskey === undefined ? null : _ref$accesskey; + var _ref$checked = _ref.checked; + var checked = _ref$checked === undefined ? false : _ref$checked; + var _ref$click = _ref.click; + var click = _ref$click === undefined ? () => {} : _ref$click; + var _ref$disabled = _ref.disabled; + var disabled = _ref$disabled === undefined ? false : _ref$disabled; + var _ref$label = _ref.label; + var label = _ref$label === undefined ? "" : _ref$label; + var _ref$id = _ref.id; + var id = _ref$id === undefined ? null : _ref$id; + var _ref$submenu = _ref.submenu; + var submenu = _ref$submenu === undefined ? null : _ref$submenu; + var _ref$type = _ref.type; + var type = _ref$type === undefined ? "normal" : _ref$type; + var _ref$visible = _ref.visible; + var visible = _ref$visible === undefined ? true : _ref$visible; + + this.accesskey = accesskey; + this.checked = checked; + this.click = click; + this.disabled = disabled; + this.id = id; + this.label = label; + this.submenu = submenu; + this.type = type; + this.visible = visible; + } + + module.exports = MenuItem; + +/***/ }, +/* 88 */ +/***/ function(module, exports, __webpack_require__) { + + var _require = __webpack_require__(89); + + var isDevelopment = _require.isDevelopment; + var isTesting = _require.isTesting; + + + function debugGlobal(field, value) { + if (isDevelopment() || isTesting()) { + window[field] = value; + } + } + + function injectGlobals(_ref) { + var store = _ref.store; + + debugGlobal("store", store); + debugGlobal("injectDebuggee", __webpack_require__(140)); + debugGlobal("serializeStore", () => { + return JSON.parse(JSON.stringify(store.getState())); + }); + } + + module.exports = { + debugGlobal, + injectGlobals + }; + +/***/ }, +/* 89 */ +/***/ function(module, exports, __webpack_require__) { + + var feature = __webpack_require__(90); + + module.exports = feature; + +/***/ }, +/* 90 */ +/***/ function(module, exports, __webpack_require__) { + + var pick = __webpack_require__(91); + var config = void 0; + + var flag = __webpack_require__(139); + + /** + * Gets a config value for a given key + * e.g "chrome.webSocketPort" + */ + function getValue(key) { + return pick(config, key); + } + + function isEnabled(key) { + return config.features[key]; + } + + function isDevelopment() { + if (isFirefoxPanel()) { + // Default to production if compiling for the Firefox panel + return ("production") === "development"; + } + return ("production") !== "production"; + } + + function isTesting() { + return flag.testing; + } + + function isFirefoxPanel() { + return ("firefox-panel") == "firefox-panel"; + } + + function isFirefox() { + return (/firefox/i.test(navigator.userAgent) + ); + } + + function setConfig(value) { + config = value; + } + + function getConfig() { + return config; + } + + module.exports = { + isEnabled, + getValue, + isDevelopment, + isTesting, + isFirefoxPanel, + isFirefox, + getConfig, + setConfig + }; + +/***/ }, +/* 91 */ +/***/ function(module, exports, __webpack_require__) { + + var baseGet = __webpack_require__(92); + + /** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; + } + + module.exports = get; + + +/***/ }, +/* 92 */ +/***/ function(module, exports, __webpack_require__) { + + var castPath = __webpack_require__(93), + isKey = __webpack_require__(137), + toKey = __webpack_require__(138); + + /** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ + function baseGet(object, path) { + path = isKey(path, object) ? [path] : castPath(path); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; + } + + module.exports = baseGet; + + +/***/ }, +/* 93 */ +/***/ function(module, exports, __webpack_require__) { + + var isArray = __webpack_require__(94), + stringToPath = __webpack_require__(95); + + /** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array} Returns the cast property path array. + */ + function castPath(value) { + return isArray(value) ? value : stringToPath(value); + } + + module.exports = castPath; + + +/***/ }, +/* 94 */ +/***/ function(module, exports) { + + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; + + module.exports = isArray; + + +/***/ }, +/* 95 */ +/***/ function(module, exports, __webpack_require__) { + + var memoizeCapped = __webpack_require__(96), + toString = __webpack_require__(132); + + /** Used to match property names within property paths. */ + var reLeadingDot = /^\./, + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + + /** Used to match backslashes in property paths. */ + var reEscapeChar = /\\(\\)?/g; + + /** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ + var stringToPath = memoizeCapped(function(string) { + string = toString(string); + + var result = []; + if (reLeadingDot.test(string)) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; + }); + + module.exports = stringToPath; + + +/***/ }, +/* 96 */ +/***/ function(module, exports, __webpack_require__) { + + var memoize = __webpack_require__(97); + + /** Used as the maximum memoize cache size. */ + var MAX_MEMOIZE_SIZE = 500; + + /** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ + function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; + } + + module.exports = memoizeCapped; + + +/***/ }, +/* 97 */ +/***/ function(module, exports, __webpack_require__) { + + var MapCache = __webpack_require__(98); + + /** Error message constants. */ + var FUNC_ERROR_TEXT = 'Expected a function'; + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided, it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `delete`, `get`, `has`, and `set`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoized function. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; + * + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */ + function memoize(func, resolver) { + if (typeof func != 'function' || (resolver && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; + + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result) || cache; + return result; + }; + memoized.cache = new (memoize.Cache || MapCache); + return memoized; + } + + // Expose `MapCache`. + memoize.Cache = MapCache; + + module.exports = memoize; + + +/***/ }, +/* 98 */ +/***/ function(module, exports, __webpack_require__) { + + var mapCacheClear = __webpack_require__(99), + mapCacheDelete = __webpack_require__(126), + mapCacheGet = __webpack_require__(129), + mapCacheHas = __webpack_require__(130), + mapCacheSet = __webpack_require__(131); + + /** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function MapCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + // Add methods to `MapCache`. + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype['delete'] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; + + module.exports = MapCache; + + +/***/ }, +/* 99 */ +/***/ function(module, exports, __webpack_require__) { + + var Hash = __webpack_require__(100), + ListCache = __webpack_require__(117), + Map = __webpack_require__(125); + + /** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ + function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; + } + + module.exports = mapCacheClear; + + +/***/ }, +/* 100 */ +/***/ function(module, exports, __webpack_require__) { + + var hashClear = __webpack_require__(101), + hashDelete = __webpack_require__(113), + hashGet = __webpack_require__(114), + hashHas = __webpack_require__(115), + hashSet = __webpack_require__(116); + + /** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Hash(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + // Add methods to `Hash`. + Hash.prototype.clear = hashClear; + Hash.prototype['delete'] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; + + module.exports = Hash; + + +/***/ }, +/* 101 */ +/***/ function(module, exports, __webpack_require__) { + + var nativeCreate = __webpack_require__(102); + + /** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; + } + + module.exports = hashClear; + + +/***/ }, +/* 102 */ +/***/ function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(103); + + /* Built-in method references that are verified to be native. */ + var nativeCreate = getNative(Object, 'create'); + + module.exports = nativeCreate; + + +/***/ }, +/* 103 */ +/***/ function(module, exports, __webpack_require__) { + + var baseIsNative = __webpack_require__(104), + getValue = __webpack_require__(112); + + /** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; + } + + module.exports = getNative; + + +/***/ }, +/* 104 */ +/***/ function(module, exports, __webpack_require__) { + + var isFunction = __webpack_require__(105), + isMasked = __webpack_require__(107), + isObject = __webpack_require__(106), + toSource = __webpack_require__(111); + + /** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ + var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; + + /** Used to detect host constructors (Safari). */ + var reIsHostCtor = /^\[object .+?Constructor\]$/; + + /** Used for built-in method references. */ + var funcProto = Function.prototype, + objectProto = Object.prototype; + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to detect if a method is native. */ + var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + ); + + /** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } + + module.exports = baseIsNative; + + +/***/ }, +/* 105 */ +/***/ function(module, exports, __webpack_require__) { + + var isObject = __webpack_require__(106); + + /** `Object#toString` result references. */ + var funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + proxyTag = '[object Proxy]'; + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var objectToString = objectProto.toString; + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed array and other constructors. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag || tag == proxyTag; + } + + module.exports = isFunction; + + +/***/ }, +/* 106 */ +/***/ function(module, exports) { + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); + } + + module.exports = isObject; + + +/***/ }, +/* 107 */ +/***/ function(module, exports, __webpack_require__) { + + var coreJsData = __webpack_require__(108); + + /** Used to detect methods masquerading as native. */ + var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; + }()); + + /** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ + function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); + } + + module.exports = isMasked; + + +/***/ }, +/* 108 */ +/***/ function(module, exports, __webpack_require__) { + + var root = __webpack_require__(109); + + /** Used to detect overreaching core-js shims. */ + var coreJsData = root['__core-js_shared__']; + + module.exports = coreJsData; + + +/***/ }, +/* 109 */ +/***/ function(module, exports, __webpack_require__) { + + var freeGlobal = __webpack_require__(110); + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + + module.exports = root; + + +/***/ }, +/* 110 */ +/***/ function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + module.exports = freeGlobal; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 111 */ +/***/ function(module, exports) { + + /** Used for built-in method references. */ + var funcProto = Function.prototype; + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to process. + * @returns {string} Returns the source code. + */ + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; + } + + module.exports = toSource; + + +/***/ }, +/* 112 */ +/***/ function(module, exports) { + + /** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function getValue(object, key) { + return object == null ? undefined : object[key]; + } + + module.exports = getValue; + + +/***/ }, +/* 113 */ +/***/ function(module, exports) { + + /** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; + } + + module.exports = hashDelete; + + +/***/ }, +/* 114 */ +/***/ function(module, exports, __webpack_require__) { + + var nativeCreate = __webpack_require__(102); + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; + } + + module.exports = hashGet; + + +/***/ }, +/* 115 */ +/***/ function(module, exports, __webpack_require__) { + + var nativeCreate = __webpack_require__(102); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key); + } + + module.exports = hashHas; + + +/***/ }, +/* 116 */ +/***/ function(module, exports, __webpack_require__) { + + var nativeCreate = __webpack_require__(102); + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ + function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; + } + + module.exports = hashSet; + + +/***/ }, +/* 117 */ +/***/ function(module, exports, __webpack_require__) { + + var listCacheClear = __webpack_require__(118), + listCacheDelete = __webpack_require__(119), + listCacheGet = __webpack_require__(122), + listCacheHas = __webpack_require__(123), + listCacheSet = __webpack_require__(124); + + /** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function ListCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + // Add methods to `ListCache`. + ListCache.prototype.clear = listCacheClear; + ListCache.prototype['delete'] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; + + module.exports = ListCache; + + +/***/ }, +/* 118 */ +/***/ function(module, exports) { + + /** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ + function listCacheClear() { + this.__data__ = []; + this.size = 0; + } + + module.exports = listCacheClear; + + +/***/ }, +/* 119 */ +/***/ function(module, exports, __webpack_require__) { + + var assocIndexOf = __webpack_require__(120); + + /** Used for built-in method references. */ + var arrayProto = Array.prototype; + + /** Built-in value references. */ + var splice = arrayProto.splice; + + /** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; + } + + module.exports = listCacheDelete; + + +/***/ }, +/* 120 */ +/***/ function(module, exports, __webpack_require__) { + + var eq = __webpack_require__(121); + + /** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; + } + + module.exports = assocIndexOf; + + +/***/ }, +/* 121 */ +/***/ function(module, exports) { + + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } + + module.exports = eq; + + +/***/ }, +/* 122 */ +/***/ function(module, exports, __webpack_require__) { + + var assocIndexOf = __webpack_require__(120); + + /** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; + } + + module.exports = listCacheGet; + + +/***/ }, +/* 123 */ +/***/ function(module, exports, __webpack_require__) { + + var assocIndexOf = __webpack_require__(120); + + /** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } + + module.exports = listCacheHas; + + +/***/ }, +/* 124 */ +/***/ function(module, exports, __webpack_require__) { + + var assocIndexOf = __webpack_require__(120); + + /** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ + function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; + } + + module.exports = listCacheSet; + + +/***/ }, +/* 125 */ +/***/ function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(103), + root = __webpack_require__(109); + + /* Built-in method references that are verified to be native. */ + var Map = getNative(root, 'Map'); + + module.exports = Map; + + +/***/ }, +/* 126 */ +/***/ function(module, exports, __webpack_require__) { + + var getMapData = __webpack_require__(127); + + /** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; + } + + module.exports = mapCacheDelete; + + +/***/ }, +/* 127 */ +/***/ function(module, exports, __webpack_require__) { + + var isKeyable = __webpack_require__(128); + + /** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ + function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; + } + + module.exports = getMapData; + + +/***/ }, +/* 128 */ +/***/ function(module, exports) { + + /** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ + function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); + } + + module.exports = isKeyable; + + +/***/ }, +/* 129 */ +/***/ function(module, exports, __webpack_require__) { + + var getMapData = __webpack_require__(127); + + /** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function mapCacheGet(key) { + return getMapData(this, key).get(key); + } + + module.exports = mapCacheGet; + + +/***/ }, +/* 130 */ +/***/ function(module, exports, __webpack_require__) { + + var getMapData = __webpack_require__(127); + + /** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapCacheHas(key) { + return getMapData(this, key).has(key); + } + + module.exports = mapCacheHas; + + +/***/ }, +/* 131 */ +/***/ function(module, exports, __webpack_require__) { + + var getMapData = __webpack_require__(127); + + /** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ + function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; + } + + module.exports = mapCacheSet; + + +/***/ }, +/* 132 */ +/***/ function(module, exports, __webpack_require__) { + + var baseToString = __webpack_require__(133); + + /** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ + function toString(value) { + return value == null ? '' : baseToString(value); + } + + module.exports = toString; + + +/***/ }, +/* 133 */ +/***/ function(module, exports, __webpack_require__) { + + var Symbol = __webpack_require__(134), + arrayMap = __webpack_require__(135), + isArray = __webpack_require__(94), + isSymbol = __webpack_require__(136); + + /** Used as references for various `Number` constants. */ + var INFINITY = 1 / 0; + + /** Used to convert symbols to primitives and strings. */ + var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + + /** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ + function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + module.exports = baseToString; + + +/***/ }, +/* 134 */ +/***/ function(module, exports, __webpack_require__) { + + var root = __webpack_require__(109); + + /** Built-in value references. */ + var Symbol = root.Symbol; + + module.exports = Symbol; + + +/***/ }, +/* 135 */ +/***/ function(module, exports) { + + /** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function arrayMap(array, iteratee) { + var index = -1, + length = array ? array.length : 0, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + + module.exports = arrayMap; + + +/***/ }, +/* 136 */ +/***/ function(module, exports, __webpack_require__) { + + var isObjectLike = __webpack_require__(8); + + /** `Object#toString` result references. */ + var symbolTag = '[object Symbol]'; + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var objectToString = objectProto.toString; + + /** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ + function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); + } + + module.exports = isSymbol; + + +/***/ }, +/* 137 */ +/***/ function(module, exports, __webpack_require__) { + + var isArray = __webpack_require__(94), + isSymbol = __webpack_require__(136); + + /** Used to match property names within property paths. */ + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/; + + /** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ + function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); + } + + module.exports = isKey; + + +/***/ }, +/* 138 */ +/***/ function(module, exports, __webpack_require__) { + + var isSymbol = __webpack_require__(136); + + /** Used as references for various `Number` constants. */ + var INFINITY = 1 / 0; + + /** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ + function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + module.exports = toKey; + + +/***/ }, +/* 139 */ +/***/ function(module, exports) { + + module.exports = devtoolsRequire("devtools/shared/flags"); + +/***/ }, +/* 140 */ +/***/ function(module, exports) { + + function Debuggee() { + function $(selector) { + var element = document.querySelector(selector); + console.log("$", selector, element); + + if (!element) { + throw new Error("Element not found, try changing the selector"); + } + return element; + } + + function mouseEvent(eventType) { + return new MouseEvent(eventType, { + "view": window, + "bubbles": true, + "cancelable": true + }); + } + + var specialKeysMap = { + "{enter}": 13 + }; + + // Special character examples {enter}, {esc}, {leftarrow} .. + function isSpecialCharacter(text) { + return text.match(/^\{.*\}$/); + } + + function keyInfo(key, eventType) { + var charCodeAt = void 0; + + if (key.length > 1) { + charCodeAt = specialKeysMap[key]; + } else { + charCodeAt = key.toUpperCase().charCodeAt(0); + } + + return { + charCode: eventType == "keypress" ? 0 : charCodeAt, + keyCode: charCodeAt, + which: charCodeAt + }; + } + + function keyEvent(eventType, key) { + var event = new Event(eventType, { + bubbles: true, + cancelable: false, + view: window + }); + + var _keyInfo = keyInfo(key, eventType); + + var charCode = _keyInfo.charCode; + var keyCode = _keyInfo.keyCode; + var which = _keyInfo.which; + + + return Object.assign(event, { + charCode: charCode, + keyCode: keyCode, + which: which, + detail: 0, + layerX: 0, + layerY: 0, + pageX: 0, + pageY: 0 + }); + } + + function sendKey(element, key) { + element.dispatchEvent(keyEvent("keydown", key)); + element.dispatchEvent(keyEvent("keypress", key)); + if (key.length == 1) { + element.value += key; + } + element.dispatchEvent(keyEvent("keyup", key)); + } + + function click(selector) { + var element = $(selector); + console.log("click", selector); + element.dispatchEvent(mouseEvent("click")); + } + + function dblclick(selector) { + var element = $(selector); + console.log("dblclick", selector); + element.dispatchEvent(mouseEvent("dblclick")); + } + + function type(selector, text) { + var element = $(selector); + console.log("type", selector, text); + element.select(); + + if (isSpecialCharacter(text)) { + sendKey(element, text); + } else { + var chars = text.split(""); + chars.forEach(char => sendKey(element, char)); + } + } + + return { + click, + dblclick, + type + }; + } + + var debuggeeStatement = `window.dbg = (${ Debuggee })()`; + var injectedDebuggee = void 0; + + function injectDebuggee() { + if (injectedDebuggee) { + return Promise.resolve(injectedDebuggee); + } + + return window.client.debuggeeCommand(debuggeeStatement).then(result => { + injectedDebuggee = result; + }); + } + + module.exports = injectDebuggee; + +/***/ }, +/* 141 */ +/***/ function(module, exports, __webpack_require__) { + + var _require = __webpack_require__(142); + + var Task = _require.Task; + + var firefox = __webpack_require__(143); + var chrome = __webpack_require__(205); + + var _require2 = __webpack_require__(88); + + var debugGlobal = _require2.debugGlobal; + + + var clientType = void 0; + function getClient() { + if (clientType === "chrome") { + return chrome.clientCommands; + } + + return firefox.clientCommands; + } + + function startDebugging(connTarget, actions) { + if (connTarget.type === "node") { + return startDebuggingNode(connTarget.param, actions); + } + + var target = connTarget.type === "chrome" ? chrome : firefox; + return startDebuggingTab(target, connTarget.param, actions); + } + + function startDebuggingNode(url, actions) { + clientType = "chrome"; + return chrome.connectNode(`ws://${ url }`).then(() => { + chrome.initPage(actions); + }); + } + + function startDebuggingTab(targetEnv, tabId, actions) { + return Task.spawn(function* () { + var tabs = yield targetEnv.connectClient(); + var tab = tabs.find(t => t.id.indexOf(tabId) !== -1); + yield targetEnv.connectTab(tab.tab); + targetEnv.initPage(actions); + + clientType = targetEnv === firefox ? "firefox" : "chrome"; + debugGlobal("client", targetEnv.clientCommands); + + return tabs; + }); + } + + function connectClients(onConnect) { + firefox.connectClient().then(onConnect); + chrome.connectClient().then(onConnect); + } + + module.exports = { + getClient, + connectClients, + startDebugging, + firefox, + chrome + }; + +/***/ }, +/* 142 */ +/***/ function(module, exports) { + + /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + + /** + * This object provides the public module functions. + */ + var Task = { + // XXX: Not sure if this works in all cases... + async: function (task) { + return function () { + return Task.spawn(task, this, arguments); + }; + }, + + /** + * Creates and starts a new task. + * @param task A generator function + * @return A promise, resolved when the task terminates + */ + spawn: function (task, scope, args) { + return new Promise(function (resolve, reject) { + var iterator = task.apply(scope, args); + + var callNext = lastValue => { + var iteration = iterator.next(lastValue); + Promise.resolve(iteration.value).then(value => { + if (iteration.done) { + resolve(value); + } else { + callNext(value); + } + }).catch(error => { + reject(error); + iterator.throw(error); + }); + }; + + callNext(undefined); + }); + } + }; + + module.exports = { Task }; + +/***/ }, +/* 143 */ +/***/ function(module, exports, __webpack_require__) { + + var _require = __webpack_require__(28); + + var DebuggerClient = _require.DebuggerClient; + var DebuggerTransport = _require.DebuggerTransport; + var TargetFactory = _require.TargetFactory; + var WebsocketTransport = _require.WebsocketTransport; + + var defer = __webpack_require__(144); + + var _require2 = __webpack_require__(89); + + var getValue = _require2.getValue; + + var _require3 = __webpack_require__(145); + + var Tab = _require3.Tab; + + var _require4 = __webpack_require__(202); + + var setupCommands = _require4.setupCommands; + var clientCommands = _require4.clientCommands; + + var _require5 = __webpack_require__(203); + + var setupEvents = _require5.setupEvents; + var clientEvents = _require5.clientEvents; + + var _require6 = __webpack_require__(204); + + var createSource = _require6.createSource; + + + var debuggerClient = null; + var threadClient = null; + var tabTarget = null; + + function getThreadClient() { + return threadClient; + } + + function setThreadClient(client) { + threadClient = client; + } + + function getTabTarget() { + return tabTarget; + } + + function setTabTarget(target) { + tabTarget = target; + } + + function lookupTabTarget(tab) { + var options = { client: debuggerClient, form: tab, chrome: false }; + return TargetFactory.forRemoteTab(options); + } + + function createTabs(tabs) { + return tabs.map(tab => { + return Tab({ + title: tab.title, + url: tab.url, + id: tab.actor, + tab, + browser: "firefox" + }); + }); + } + + function connectClient() { + var deferred = defer(); + var useProxy = !getValue("firefox.webSocketConnection"); + var portPref = useProxy ? "firefox.proxyPort" : "firefox.webSocketPort"; + var webSocketPort = getValue(portPref); + + var socket = new WebSocket(`ws://${ document.location.hostname }:${ webSocketPort }`); + var transport = useProxy ? new DebuggerTransport(socket) : new WebsocketTransport(socket); + debuggerClient = new DebuggerClient(transport); + + debuggerClient.connect().then(() => { + return debuggerClient.listTabs().then(response => { + deferred.resolve(createTabs(response.tabs)); + }); + }).catch(err => { + console.log(err); + deferred.resolve([]); + }); + + return deferred.promise; + } + + function connectTab(tab) { + return new Promise((resolve, reject) => { + window.addEventListener("beforeunload", () => { + getTabTarget() && getTabTarget().destroy(); + }); + + lookupTabTarget(tab).then(target => { + tabTarget = target; + target.activeTab.attachThread({}, (res, _threadClient) => { + threadClient = _threadClient; + threadClient.resume(); + resolve(); + }); + }); + }); + } + + function initPage(actions) { + tabTarget = getTabTarget(); + threadClient = getThreadClient(); + + setupCommands({ threadClient, tabTarget, debuggerClient }); + + tabTarget.on("will-navigate", actions.willNavigate); + tabTarget.on("navigate", actions.navigated); + + // Listen to all the requested events. + setupEvents({ threadClient, actions }); + Object.keys(clientEvents).forEach(eventName => { + threadClient.addListener(eventName, clientEvents[eventName]); + }); + + // In Firefox, we need to initially request all of the sources. This + // usually fires off individual `newSource` notifications as the + // debugger finds them, but there may be existing sources already in + // the debugger (if it's paused already, or if loading the page from + // bfcache) so explicity fire `newSource` events for all returned + // sources. + return threadClient.getSources().then((_ref) => { + var sources = _ref.sources; + + actions.newSources(sources.map(createSource)); + + // If the threadClient is already paused, make sure to show a + // paused state. + var pausedPacket = threadClient.getLastPausePacket(); + if (pausedPacket) { + clientEvents.paused(null, pausedPacket); + } + }); + } + + module.exports = { + connectClient, + connectTab, + clientCommands, + getThreadClient, + setThreadClient, + getTabTarget, + setTabTarget, + initPage + }; + +/***/ }, +/* 144 */ +/***/ function(module, exports) { + + module.exports = function defer() { + var resolve = void 0, + reject = void 0; + var promise = new Promise(function () { + resolve = arguments[0]; + reject = arguments[1]; + }); + return { + resolve: resolve, + reject: reject, + promise: promise + }; + }; + +/***/ }, +/* 145 */ +/***/ function(module, exports, __webpack_require__) { + + var t = __webpack_require__(146); + + var Tab = t.struct({ + title: t.String, + url: t.String, + id: t.String, + tab: t.Object, + browser: t.enums.of(["chrome", "firefox"]) + }, "Tab"); + + var SourceText = t.struct({ + text: t.String, + contentType: t.String + }); + + var Source = t.struct({ + id: t.String, + url: t.union([t.String, t.Nil]), + isPrettyPrinted: t.Boolean, + sourceMapURL: t.union([t.String, t.Nil]) + }, "Source"); + + var Location = t.struct({ + sourceId: t.String, + line: t.Number, + column: t.union([t.Number, t.Nil]) + }, "Location"); + + var Breakpoint = t.struct({ + id: t.String, + loading: t.Boolean, + disabled: t.Boolean, + text: t.String, + condition: t.union([t.String, t.Nil]) + }); + + var BreakpointResult = t.struct({ + id: t.String, + actualLocation: Location + }); + + var Frame = t.struct({ + id: t.String, + displayName: t.String, + location: Location, + this: t.union([t.Object, t.Nil]), + scope: t.union([t.Object, t.Nil]) + }, "Frame"); + + module.exports = { + Tab, + Source, + SourceText, + Location, + Breakpoint, + BreakpointResult, + Frame + }; + +/***/ }, +/* 146 */ +/***/ function(module, exports, __webpack_require__) { + + /*! @preserve + * + * tcomb.js - Type checking and DDD for JavaScript + * + * The MIT License (MIT) + * + * Copyright (c) 2014-2016 Giulio Canti + * + */ + + // core + var t = __webpack_require__(147); + + // types + t.Any = __webpack_require__(153); + t.Array = __webpack_require__(161); + t.Boolean = __webpack_require__(162); + t.Date = __webpack_require__(164); + t.Error = __webpack_require__(165); + t.Function = __webpack_require__(166); + t.Nil = __webpack_require__(167); + t.Number = __webpack_require__(168); + t.Integer = __webpack_require__(170); + t.IntegerT = t.Integer; + t.Object = __webpack_require__(176); + t.RegExp = __webpack_require__(177); + t.String = __webpack_require__(178); + t.Type = __webpack_require__(179); + t.TypeT = t.Type; + + // short alias are deprecated + t.Arr = t.Array; + t.Bool = t.Boolean; + t.Dat = t.Date; + t.Err = t.Error; + t.Func = t.Function; + t.Num = t.Number; + t.Obj = t.Object; + t.Re = t.RegExp; + t.Str = t.String; + + // combinators + t.dict = __webpack_require__(180); + t.declare = __webpack_require__(181); + t.enums = __webpack_require__(184); + t.irreducible = __webpack_require__(154); + t.list = __webpack_require__(185); + t.maybe = __webpack_require__(186); + t.refinement = __webpack_require__(171); + t.struct = __webpack_require__(188); + t.tuple = __webpack_require__(194); + t.union = __webpack_require__(195); + t.func = __webpack_require__(196); + t.intersection = __webpack_require__(197); + t.subtype = t.refinement; + t.inter = __webpack_require__(198); // IE8 alias + t['interface'] = t.inter; + + // functions + t.assert = t; + t.update = __webpack_require__(200); + t.mixin = __webpack_require__(182); + t.isType = __webpack_require__(158); + t.is = __webpack_require__(175); + t.getTypeName = __webpack_require__(157); + t.match = __webpack_require__(201); + + module.exports = t; + + +/***/ }, +/* 147 */ +/***/ function(module, exports, __webpack_require__) { + + var isFunction = __webpack_require__(148); + var isNil = __webpack_require__(149); + var fail = __webpack_require__(150); + var stringify = __webpack_require__(151); + + function assert(guard, message) { + if (guard !== true) { + if (isFunction(message)) { // handle lazy messages + message = message(); + } + else if (isNil(message)) { // use a default message + message = 'Assert failed (turn on "Pause on exceptions" in your Source panel)'; + } + assert.fail(message); + } + } + + assert.fail = fail; + assert.stringify = stringify; + + module.exports = assert; + +/***/ }, +/* 148 */ +/***/ function(module, exports) { + + module.exports = function isFunction(x) { + return typeof x === 'function'; + }; + +/***/ }, +/* 149 */ +/***/ function(module, exports) { + + module.exports = function isNil(x) { + return x === null || x === void 0; + }; + +/***/ }, +/* 150 */ +/***/ function(module, exports) { + + module.exports = function fail(message) { + throw new TypeError('[tcomb] ' + message); + }; + +/***/ }, +/* 151 */ +/***/ function(module, exports, __webpack_require__) { + + var getFunctionName = __webpack_require__(152); + + function replacer(key, value) { + if (typeof value === 'function') { + return getFunctionName(value); + } + return value; + } + + module.exports = function stringify(x) { + try { // handle "Converting circular structure to JSON" error + return JSON.stringify(x, replacer, 2); + } + catch (e) { + return String(x); + } + }; + +/***/ }, +/* 152 */ +/***/ function(module, exports) { + + module.exports = function getFunctionName(f) { + return f.displayName || f.name || '<function' + f.length + '>'; + }; + +/***/ }, +/* 153 */ +/***/ function(module, exports, __webpack_require__) { + + var irreducible = __webpack_require__(154); + + module.exports = irreducible('Any', function () { return true; }); + + +/***/ }, +/* 154 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isString = __webpack_require__(155); + var isFunction = __webpack_require__(148); + var forbidNewOperator = __webpack_require__(156); + + module.exports = function irreducible(name, predicate) { + + if (false) { + assert(isString(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to irreducible(name, predicate) (expected a string)'; }); + assert(isFunction(predicate), 'Invalid argument predicate ' + assert.stringify(predicate) + ' supplied to irreducible(name, predicate) (expected a function)'); + } + + function Irreducible(value, path) { + + if (false) { + forbidNewOperator(this, Irreducible); + path = path || [name]; + assert(predicate(value), function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + path.join('/'); }); + } + + return value; + } + + Irreducible.meta = { + kind: 'irreducible', + name: name, + predicate: predicate, + identity: true + }; + + Irreducible.displayName = name; + + Irreducible.is = predicate; + + return Irreducible; + }; + + +/***/ }, +/* 155 */ +/***/ function(module, exports) { + + module.exports = function isString(x) { + return typeof x === 'string'; + }; + +/***/ }, +/* 156 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var getTypeName = __webpack_require__(157); + + module.exports = function forbidNewOperator(x, type) { + assert(!(x instanceof type), function () { return 'Cannot use the new operator to instantiate the type ' + getTypeName(type); }); + }; + +/***/ }, +/* 157 */ +/***/ function(module, exports, __webpack_require__) { + + var isType = __webpack_require__(158); + var getFunctionName = __webpack_require__(152); + + module.exports = function getTypeName(ctor) { + if (isType(ctor)) { + return ctor.displayName; + } + return getFunctionName(ctor); + }; + +/***/ }, +/* 158 */ +/***/ function(module, exports, __webpack_require__) { + + var isFunction = __webpack_require__(148); + var isObject = __webpack_require__(159); + + module.exports = function isType(x) { + return isFunction(x) && isObject(x.meta); + }; + +/***/ }, +/* 159 */ +/***/ function(module, exports, __webpack_require__) { + + var isNil = __webpack_require__(149); + var isArray = __webpack_require__(160); + + module.exports = function isObject(x) { + return !isNil(x) && typeof x === 'object' && !isArray(x); + }; + +/***/ }, +/* 160 */ +/***/ function(module, exports) { + + module.exports = function isArray(x) { + return Array.isArray ? Array.isArray(x) : x instanceof Array; + }; + +/***/ }, +/* 161 */ +/***/ function(module, exports, __webpack_require__) { + + var irreducible = __webpack_require__(154); + var isArray = __webpack_require__(160); + + module.exports = irreducible('Array', isArray); + + +/***/ }, +/* 162 */ +/***/ function(module, exports, __webpack_require__) { + + var irreducible = __webpack_require__(154); + var isBoolean = __webpack_require__(163); + + module.exports = irreducible('Boolean', isBoolean); + + +/***/ }, +/* 163 */ +/***/ function(module, exports) { + + module.exports = function isBoolean(x) { + return x === true || x === false; + }; + +/***/ }, +/* 164 */ +/***/ function(module, exports, __webpack_require__) { + + var irreducible = __webpack_require__(154); + + module.exports = irreducible('Date', function (x) { return x instanceof Date; }); + + +/***/ }, +/* 165 */ +/***/ function(module, exports, __webpack_require__) { + + var irreducible = __webpack_require__(154); + + module.exports = irreducible('Error', function (x) { return x instanceof Error; }); + + +/***/ }, +/* 166 */ +/***/ function(module, exports, __webpack_require__) { + + var irreducible = __webpack_require__(154); + var isFunction = __webpack_require__(148); + + module.exports = irreducible('Function', isFunction); + + +/***/ }, +/* 167 */ +/***/ function(module, exports, __webpack_require__) { + + var irreducible = __webpack_require__(154); + var isNil = __webpack_require__(149); + + module.exports = irreducible('Nil', isNil); + + +/***/ }, +/* 168 */ +/***/ function(module, exports, __webpack_require__) { + + var irreducible = __webpack_require__(154); + var isNumber = __webpack_require__(169); + + module.exports = irreducible('Number', isNumber); + + +/***/ }, +/* 169 */ +/***/ function(module, exports) { + + module.exports = function isNumber(x) { + return typeof x === 'number' && isFinite(x) && !isNaN(x); + }; + +/***/ }, +/* 170 */ +/***/ function(module, exports, __webpack_require__) { + + var refinement = __webpack_require__(171); + var Number = __webpack_require__(168); + + module.exports = refinement(Number, function (x) { return x % 1 === 0; }, 'Integer'); + + +/***/ }, +/* 171 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isTypeName = __webpack_require__(172); + var isFunction = __webpack_require__(148); + var forbidNewOperator = __webpack_require__(156); + var isIdentity = __webpack_require__(173); + var create = __webpack_require__(174); + var is = __webpack_require__(175); + var getTypeName = __webpack_require__(157); + var getFunctionName = __webpack_require__(152); + + function getDefaultName(type, predicate) { + return '{' + getTypeName(type) + ' | ' + getFunctionName(predicate) + '}'; + } + + function refinement(type, predicate, name) { + + if (false) { + assert(isFunction(type), function () { return 'Invalid argument type ' + assert.stringify(type) + ' supplied to refinement(type, predicate, [name]) combinator (expected a type)'; }); + assert(isFunction(predicate), function () { return 'Invalid argument predicate supplied to refinement(type, predicate, [name]) combinator (expected a function)'; }); + assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to refinement(type, predicate, [name]) combinator (expected a string)'; }); + } + + var displayName = name || getDefaultName(type, predicate); + var identity = isIdentity(type); + + function Refinement(value, path) { + + if (false) { + if (identity) { + forbidNewOperator(this, Refinement); + } + path = path || [displayName]; + } + + var x = create(type, value, path); + + if (false) { + assert(predicate(x), function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + path.join('/'); }); + } + + return x; + } + + Refinement.meta = { + kind: 'subtype', + type: type, + predicate: predicate, + name: name, + identity: identity + }; + + Refinement.displayName = displayName; + + Refinement.is = function (x) { + return is(x, type) && predicate(x); + }; + + Refinement.update = function (instance, patch) { + return Refinement(assert.update(instance, patch)); + }; + + return Refinement; + } + + refinement.getDefaultName = getDefaultName; + module.exports = refinement; + + +/***/ }, +/* 172 */ +/***/ function(module, exports, __webpack_require__) { + + var isNil = __webpack_require__(149); + var isString = __webpack_require__(155); + + module.exports = function isTypeName(name) { + return isNil(name) || isString(name); + }; + +/***/ }, +/* 173 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var Boolean = __webpack_require__(162); + var isType = __webpack_require__(158); + var getTypeName = __webpack_require__(157); + + // return true if the type constructor behaves like the identity function + module.exports = function isIdentity(type) { + if (isType(type)) { + if (false) { + assert(Boolean.is(type.meta.identity), function () { return 'Invalid meta identity ' + assert.stringify(type.meta.identity) + ' supplied to type ' + getTypeName(type); }); + } + return type.meta.identity; + } + // for tcomb the other constructors, like ES6 classes, are identity-like + return true; + }; + +/***/ }, +/* 174 */ +/***/ function(module, exports, __webpack_require__) { + + var isType = __webpack_require__(158); + var getFunctionName = __webpack_require__(152); + var assert = __webpack_require__(147); + var stringify = __webpack_require__(151); + + // creates an instance of a type, handling the optional new operator + module.exports = function create(type, value, path) { + if (isType(type)) { + return !type.meta.identity && typeof value === 'object' && value !== null ? new type(value, path): type(value, path); + } + + if (false) { + // here type should be a class constructor and value some instance, just check membership and return the value + path = path || [getFunctionName(type)]; + assert(value instanceof type, function () { return 'Invalid value ' + stringify(value) + ' supplied to ' + path.join('/'); }); + } + + return value; + }; + +/***/ }, +/* 175 */ +/***/ function(module, exports, __webpack_require__) { + + var isType = __webpack_require__(158); + + // returns true if x is an instance of type + module.exports = function is(x, type) { + if (isType(type)) { + return type.is(x); + } + return x instanceof type; // type should be a class constructor + }; + + +/***/ }, +/* 176 */ +/***/ function(module, exports, __webpack_require__) { + + var irreducible = __webpack_require__(154); + var isObject = __webpack_require__(159); + + module.exports = irreducible('Object', isObject); + + +/***/ }, +/* 177 */ +/***/ function(module, exports, __webpack_require__) { + + var irreducible = __webpack_require__(154); + + module.exports = irreducible('RegExp', function (x) { return x instanceof RegExp; }); + + +/***/ }, +/* 178 */ +/***/ function(module, exports, __webpack_require__) { + + var irreducible = __webpack_require__(154); + var isString = __webpack_require__(155); + + module.exports = irreducible('String', isString); + + +/***/ }, +/* 179 */ +/***/ function(module, exports, __webpack_require__) { + + var irreducible = __webpack_require__(154); + var isType = __webpack_require__(158); + + module.exports = irreducible('Type', isType); + +/***/ }, +/* 180 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isTypeName = __webpack_require__(172); + var isFunction = __webpack_require__(148); + var getTypeName = __webpack_require__(157); + var isIdentity = __webpack_require__(173); + var isObject = __webpack_require__(159); + var create = __webpack_require__(174); + var is = __webpack_require__(175); + + function getDefaultName(domain, codomain) { + return '{[key: ' + getTypeName(domain) + ']: ' + getTypeName(codomain) + '}'; + } + + function dict(domain, codomain, name) { + + if (false) { + assert(isFunction(domain), function () { return 'Invalid argument domain ' + assert.stringify(domain) + ' supplied to dict(domain, codomain, [name]) combinator (expected a type)'; }); + assert(isFunction(codomain), function () { return 'Invalid argument codomain ' + assert.stringify(codomain) + ' supplied to dict(domain, codomain, [name]) combinator (expected a type)'; }); + assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to dict(domain, codomain, [name]) combinator (expected a string)'; }); + } + + var displayName = name || getDefaultName(domain, codomain); + var domainNameCache = getTypeName(domain); + var codomainNameCache = getTypeName(codomain); + var identity = isIdentity(domain) && isIdentity(codomain); + + function Dict(value, path) { + + if (true) { + if (identity) { + return value; // just trust the input if elements must not be hydrated + } + } + + if (false) { + path = path || [displayName]; + assert(isObject(value), function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + path.join('/'); }); + } + + var idempotent = true; // will remain true if I can reutilise the input + var ret = {}; // make a temporary copy, will be discarded if idempotent remains true + for (var k in value) { + if (value.hasOwnProperty(k)) { + k = create(domain, k, ( false ? path.concat(domainNameCache) : null )); + var actual = value[k]; + var instance = create(codomain, actual, ( false ? path.concat(k + ': ' + codomainNameCache) : null )); + idempotent = idempotent && ( actual === instance ); + ret[k] = instance; + } + } + + if (idempotent) { // implements idempotency + ret = value; + } + + if (false) { + Object.freeze(ret); + } + + return ret; + } + + Dict.meta = { + kind: 'dict', + domain: domain, + codomain: codomain, + name: name, + identity: identity + }; + + Dict.displayName = displayName; + + Dict.is = function (x) { + if (!isObject(x)) { + return false; + } + for (var k in x) { + if (x.hasOwnProperty(k)) { + if (!is(k, domain) || !is(x[k], codomain)) { + return false; + } + } + } + return true; + }; + + Dict.update = function (instance, patch) { + return Dict(assert.update(instance, patch)); + }; + + return Dict; + } + + dict.getDefaultName = getDefaultName; + module.exports = dict; + + +/***/ }, +/* 181 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isTypeName = __webpack_require__(172); + var isType = __webpack_require__(158); + var isNil = __webpack_require__(149); + var mixin = __webpack_require__(182); + var getTypeName = __webpack_require__(157); + var isUnion = __webpack_require__(183); + + // All the .declare-d types should be clearly different from each other thus they should have + // different names when a name was not explicitly provided. + var nextDeclareUniqueId = 1; + + module.exports = function declare(name) { + if (false) { + assert(isTypeName(name), function () { return 'Invalid argument name ' + name + ' supplied to declare([name]) (expected a string)'; }); + } + + var type; + + function Declare(value, path) { + if (false) { + assert(!isNil(type), function () { return 'Type declared but not defined, don\'t forget to call .define on every declared type'; }); + if (isUnion(type)) { + assert(type.dispatch === Declare.dispatch, function () { return 'Please define the custom ' + name + '.dispatch function before calling ' + name + '.define()'; }); + } + } + return type(value, path); + } + + Declare.define = function (spec) { + if (false) { + assert(isType(spec), function () { return 'Invalid argument type ' + assert.stringify(spec) + ' supplied to define(type) (expected a type)'; }); + assert(isNil(type), function () { return 'Declare.define(type) can only be invoked once'; }); + assert(isNil(spec.meta.name) && Object.keys(spec.prototype).length === 0, function () { return 'Invalid argument type ' + assert.stringify(spec) + ' supplied to define(type) (expected a fresh, unnamed type)'; }); + } + + if (isUnion(spec) && Declare.hasOwnProperty('dispatch')) { + spec.dispatch = Declare.dispatch; + } + type = spec; + mixin(Declare, type, true); // true because it overwrites Declare.displayName + if (name) { + type.displayName = Declare.displayName = name; + Declare.meta.name = name; + } + Declare.meta.identity = type.meta.identity; + Declare.prototype = type.prototype; + return Declare; + }; + + Declare.displayName = name || ( getTypeName(Declare) + "$" + nextDeclareUniqueId++ ); + // in general I can't say if this type will be an identity, for safety setting to false + Declare.meta = { identity: false }; + Declare.prototype = null; + return Declare; + }; + + +/***/ }, +/* 182 */ +/***/ function(module, exports, __webpack_require__) { + + var isNil = __webpack_require__(149); + var assert = __webpack_require__(147); + + // safe mixin, cannot override props unless specified + module.exports = function mixin(target, source, overwrite) { + if (isNil(source)) { return target; } + for (var k in source) { + if (source.hasOwnProperty(k)) { + if (overwrite !== true) { + if (false) { + assert(!target.hasOwnProperty(k) || target[k] === source[k], function () { return 'Invalid call to mixin(target, source, [overwrite]): cannot overwrite property "' + k + '" of target object'; }); + } + } + target[k] = source[k]; + } + } + return target; + }; + +/***/ }, +/* 183 */ +/***/ function(module, exports, __webpack_require__) { + + var isType = __webpack_require__(158); + + module.exports = function isUnion(x) { + return isType(x) && ( x.meta.kind === 'union' ); + }; + +/***/ }, +/* 184 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isTypeName = __webpack_require__(172); + var forbidNewOperator = __webpack_require__(156); + var isString = __webpack_require__(155); + var isObject = __webpack_require__(159); + + function getDefaultName(map) { + return Object.keys(map).map(function (k) { return assert.stringify(k); }).join(' | '); + } + + function enums(map, name) { + + if (false) { + assert(isObject(map), function () { return 'Invalid argument map ' + assert.stringify(map) + ' supplied to enums(map, [name]) combinator (expected a dictionary of String -> String | Number)'; }); + assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to enums(map, [name]) combinator (expected a string)'; }); + } + + var displayName = name || getDefaultName(map); + + function Enums(value, path) { + + if (false) { + forbidNewOperator(this, Enums); + path = path || [displayName]; + assert(Enums.is(value), function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + path.join('/') + ' (expected one of ' + assert.stringify(Object.keys(map)) + ')'; }); + } + + return value; + } + + Enums.meta = { + kind: 'enums', + map: map, + name: name, + identity: true + }; + + Enums.displayName = displayName; + + Enums.is = function (x) { + return map.hasOwnProperty(x); + }; + + return Enums; + } + + enums.of = function (keys, name) { + keys = isString(keys) ? keys.split(' ') : keys; + var value = {}; + keys.forEach(function (k) { + value[k] = k; + }); + return enums(value, name); + }; + + enums.getDefaultName = getDefaultName; + module.exports = enums; + + + +/***/ }, +/* 185 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isTypeName = __webpack_require__(172); + var isFunction = __webpack_require__(148); + var getTypeName = __webpack_require__(157); + var isIdentity = __webpack_require__(173); + var create = __webpack_require__(174); + var is = __webpack_require__(175); + var isArray = __webpack_require__(160); + + function getDefaultName(type) { + return 'Array<' + getTypeName(type) + '>'; + } + + function list(type, name) { + + if (false) { + assert(isFunction(type), function () { return 'Invalid argument type ' + assert.stringify(type) + ' supplied to list(type, [name]) combinator (expected a type)'; }); + assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to list(type, [name]) combinator (expected a string)'; }); + } + + var displayName = name || getDefaultName(type); + var typeNameCache = getTypeName(type); + var identity = isIdentity(type); // the list is identity iif type is identity + + function List(value, path) { + + if (true) { + if (identity) { + return value; // just trust the input if elements must not be hydrated + } + } + + if (false) { + path = path || [displayName]; + assert(isArray(value), function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + path.join('/') + ' (expected an array of ' + typeNameCache + ')'; }); + } + + var idempotent = true; // will remain true if I can reutilise the input + var ret = []; // make a temporary copy, will be discarded if idempotent remains true + for (var i = 0, len = value.length; i < len; i++ ) { + var actual = value[i]; + var instance = create(type, actual, ( false ? path.concat(i + ': ' + typeNameCache) : null )); + idempotent = idempotent && ( actual === instance ); + ret.push(instance); + } + + if (idempotent) { // implements idempotency + ret = value; + } + + if (false) { + Object.freeze(ret); + } + + return ret; + } + + List.meta = { + kind: 'list', + type: type, + name: name, + identity: identity + }; + + List.displayName = displayName; + + List.is = function (x) { + return isArray(x) && x.every(function (e) { + return is(e, type); + }); + }; + + List.update = function (instance, patch) { + return List(assert.update(instance, patch)); + }; + + return List; + } + + list.getDefaultName = getDefaultName; + module.exports = list; + + +/***/ }, +/* 186 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isTypeName = __webpack_require__(172); + var isFunction = __webpack_require__(148); + var isMaybe = __webpack_require__(187); + var isIdentity = __webpack_require__(173); + var Any = __webpack_require__(153); + var create = __webpack_require__(174); + var Nil = __webpack_require__(167); + var forbidNewOperator = __webpack_require__(156); + var is = __webpack_require__(175); + var getTypeName = __webpack_require__(157); + + function getDefaultName(type) { + return '?' + getTypeName(type); + } + + function maybe(type, name) { + + if (isMaybe(type) || type === Any || type === Nil) { // makes the combinator idempotent and handle Any, Nil + return type; + } + + if (false) { + assert(isFunction(type), function () { return 'Invalid argument type ' + assert.stringify(type) + ' supplied to maybe(type, [name]) combinator (expected a type)'; }); + assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to maybe(type, [name]) combinator (expected a string)'; }); + } + + var displayName = name || getDefaultName(type); + var identity = isIdentity(type); + + function Maybe(value, path) { + if (false) { + if (identity) { + forbidNewOperator(this, Maybe); + } + } + return Nil.is(value) ? value : create(type, value, path); + } + + Maybe.meta = { + kind: 'maybe', + type: type, + name: name, + identity: identity + }; + + Maybe.displayName = displayName; + + Maybe.is = function (x) { + return Nil.is(x) || is(x, type); + }; + + return Maybe; + } + + maybe.getDefaultName = getDefaultName; + module.exports = maybe; + + +/***/ }, +/* 187 */ +/***/ function(module, exports, __webpack_require__) { + + var isType = __webpack_require__(158); + + module.exports = function isMaybe(x) { + return isType(x) && ( x.meta.kind === 'maybe' ); + }; + +/***/ }, +/* 188 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isTypeName = __webpack_require__(172); + var String = __webpack_require__(178); + var Function = __webpack_require__(166); + var isBoolean = __webpack_require__(163); + var isObject = __webpack_require__(159); + var isNil = __webpack_require__(149); + var create = __webpack_require__(174); + var getTypeName = __webpack_require__(157); + var dict = __webpack_require__(180); + var getDefaultInterfaceName = __webpack_require__(189); + var extend = __webpack_require__(190); + + function getDefaultName(props) { + return 'Struct' + getDefaultInterfaceName(props); + } + + function extendStruct(mixins, name) { + return extend(struct, mixins, name); + } + + function getOptions(options) { + if (!isObject(options)) { + options = isNil(options) ? {} : { name: options }; + } + if (!options.hasOwnProperty('strict')) { + options.strict = struct.strict; + } + if (!options.hasOwnProperty('defaultProps')) { + options.defaultProps = {}; + } + return options; + } + + function struct(props, options) { + + options = getOptions(options); + var name = options.name; + var strict = options.strict; + var defaultProps = options.defaultProps; + + if (false) { + assert(dict(String, Function).is(props), function () { return 'Invalid argument props ' + assert.stringify(props) + ' supplied to struct(props, [options]) combinator (expected a dictionary String -> Type)'; }); + assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to struct(props, [options]) combinator (expected a string)'; }); + assert(isBoolean(strict), function () { return 'Invalid argument strict ' + assert.stringify(strict) + ' supplied to struct(props, [options]) combinator (expected a boolean)'; }); + assert(isObject(defaultProps), function () { return 'Invalid argument defaultProps ' + assert.stringify(defaultProps) + ' supplied to struct(props, [options]) combinator (expected an object)'; }); + } + + var displayName = name || getDefaultName(props); + + function Struct(value, path) { + + if (Struct.is(value)) { // implements idempotency + return value; + } + + if (false) { + path = path || [displayName]; + assert(isObject(value), function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + path.join('/') + ' (expected an object)'; }); + // strictness + if (strict) { + for (k in value) { + if (value.hasOwnProperty(k)) { + assert(props.hasOwnProperty(k), function () { return 'Invalid additional prop "' + k + '" supplied to ' + path.join('/'); }); + } + } + } + } + + if (!(this instanceof Struct)) { // `new` is optional + return new Struct(value, path); + } + + for (var k in props) { + if (props.hasOwnProperty(k)) { + var expected = props[k]; + var actual = value[k]; + // apply defaults + if (actual === undefined) { + actual = defaultProps[k]; + } + this[k] = create(expected, actual, ( false ? path.concat(k + ': ' + getTypeName(expected)) : null )); + } + } + + if (false) { + Object.freeze(this); + } + + } + + Struct.meta = { + kind: 'struct', + props: props, + name: name, + identity: false, + strict: strict, + defaultProps: defaultProps + }; + + Struct.displayName = displayName; + + Struct.is = function (x) { + return x instanceof Struct; + }; + + Struct.update = function (instance, patch) { + return new Struct(assert.update(instance, patch)); + }; + + Struct.extend = function (xs, name) { + return extendStruct([Struct].concat(xs), name); + }; + + return Struct; + } + + struct.strict = false; + struct.getOptions = getOptions; + struct.getDefaultName = getDefaultName; + struct.extend = extendStruct; + module.exports = struct; + + +/***/ }, +/* 189 */ +/***/ function(module, exports, __webpack_require__) { + + var getTypeName = __webpack_require__(157); + + function getDefaultInterfaceName(props) { + return '{' + Object.keys(props).map(function (prop) { + return prop + ': ' + getTypeName(props[prop]); + }).join(', ') + '}'; + } + + module.exports = getDefaultInterfaceName; + + +/***/ }, +/* 190 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isFunction = __webpack_require__(148); + var isArray = __webpack_require__(160); + var mixin = __webpack_require__(182); + var isStruct = __webpack_require__(191); + var isInterface = __webpack_require__(192); + var isObject = __webpack_require__(159); + var refinement = __webpack_require__(171); + var decompose = __webpack_require__(193); + + function compose(predicates, unrefinedType) { + return predicates.reduce(function (type, predicate) { + return refinement(type, predicate); + }, unrefinedType); + } + + function getProps(type) { + return isObject(type) ? type : type.meta.props; + } + + function getDefaultProps(type) { + return isObject(type) ? null : type.meta.defaultProps; + } + + function pushAll(arr, elements) { + Array.prototype.push.apply(arr, elements); + } + + function extend(combinator, mixins, options) { + if (false) { + assert(isFunction(combinator), function () { return 'Invalid argument combinator supplied to extend(combinator, mixins, options), expected a function'; }); + assert(isArray(mixins), function () { return 'Invalid argument mixins supplied to extend(combinator, mixins, options), expected an array'; }); + } + var props = {}; + var prototype = {}; + var predicates = []; + var defaultProps = {}; + mixins.forEach(function (x, i) { + var decomposition = decompose(x); + var unrefinedType = decomposition.unrefinedType; + if (false) { + assert(isObject(unrefinedType) || isStruct(unrefinedType) || isInterface(unrefinedType), function () { return 'Invalid argument mixins[' + i + '] supplied to extend(combinator, mixins, options), expected an object, struct, interface or a refinement (of struct or interface)'; }); + } + pushAll(predicates, decomposition.predicates); + mixin(props, getProps(unrefinedType)); + mixin(prototype, unrefinedType.prototype); + mixin(defaultProps, getDefaultProps(unrefinedType), true); + }); + options = combinator.getOptions(options); + options.defaultProps = mixin(defaultProps, options.defaultProps, true); + var result = compose(predicates, combinator(props, options)); + mixin(result.prototype, prototype); + return result; + } + + module.exports = extend; + +/***/ }, +/* 191 */ +/***/ function(module, exports, __webpack_require__) { + + var isType = __webpack_require__(158); + + module.exports = function isStruct(x) { + return isType(x) && ( x.meta.kind === 'struct' ); + }; + +/***/ }, +/* 192 */ +/***/ function(module, exports, __webpack_require__) { + + var isType = __webpack_require__(158); + + module.exports = function isInterface(x) { + return isType(x) && ( x.meta.kind === 'interface' ); + }; + +/***/ }, +/* 193 */ +/***/ function(module, exports, __webpack_require__) { + + var isType = __webpack_require__(158); + + function isRefinement(type) { + return isType(type) && type.meta.kind === 'subtype'; + } + + function getPredicates(type) { + return isRefinement(type) ? + [type.meta.predicate].concat(getPredicates(type.meta.type)) : + []; + } + + function getUnrefinedType(type) { + return isRefinement(type) ? + getUnrefinedType(type.meta.type) : + type; + } + + function decompose(type) { + return { + predicates: getPredicates(type), + unrefinedType: getUnrefinedType(type) + }; + } + + module.exports = decompose; + +/***/ }, +/* 194 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isTypeName = __webpack_require__(172); + var isFunction = __webpack_require__(148); + var getTypeName = __webpack_require__(157); + var isIdentity = __webpack_require__(173); + var isArray = __webpack_require__(160); + var create = __webpack_require__(174); + var is = __webpack_require__(175); + + function getDefaultName(types) { + return '[' + types.map(getTypeName).join(', ') + ']'; + } + + function tuple(types, name) { + + if (false) { + assert(isArray(types) && types.every(isFunction), function () { return 'Invalid argument types ' + assert.stringify(types) + ' supplied to tuple(types, [name]) combinator (expected an array of types)'; }); + assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to tuple(types, [name]) combinator (expected a string)'; }); + } + + var displayName = name || getDefaultName(types); + var identity = types.every(isIdentity); + + function Tuple(value, path) { + + if (true) { + if (identity) { + return value; + } + } + + if (false) { + path = path || [displayName]; + assert(isArray(value) && value.length === types.length, function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + path.join('/') + ' (expected an array of length ' + types.length + ')'; }); + } + + var idempotent = true; + var ret = []; + for (var i = 0, len = types.length; i < len; i++) { + var expected = types[i]; + var actual = value[i]; + var instance = create(expected, actual, ( false ? path.concat(i + ': ' + getTypeName(expected)) : null )); + idempotent = idempotent && ( actual === instance ); + ret.push(instance); + } + + if (idempotent) { // implements idempotency + ret = value; + } + + if (false) { + Object.freeze(ret); + } + + return ret; + } + + Tuple.meta = { + kind: 'tuple', + types: types, + name: name, + identity: identity + }; + + Tuple.displayName = displayName; + + Tuple.is = function (x) { + return isArray(x) && + x.length === types.length && + types.every(function (type, i) { + return is(x[i], type); + }); + }; + + Tuple.update = function (instance, patch) { + return Tuple(assert.update(instance, patch)); + }; + + return Tuple; + } + + tuple.getDefaultName = getDefaultName; + module.exports = tuple; + +/***/ }, +/* 195 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isTypeName = __webpack_require__(172); + var isFunction = __webpack_require__(148); + var getTypeName = __webpack_require__(157); + var isIdentity = __webpack_require__(173); + var isArray = __webpack_require__(160); + var create = __webpack_require__(174); + var is = __webpack_require__(175); + var forbidNewOperator = __webpack_require__(156); + var isUnion = __webpack_require__(183); + var isNil = __webpack_require__(149); + + function getDefaultName(types) { + return types.map(getTypeName).join(' | '); + } + + function union(types, name) { + + if (false) { + assert(isArray(types) && types.every(isFunction) && types.length >= 2, function () { return 'Invalid argument types ' + assert.stringify(types) + ' supplied to union(types, [name]) combinator (expected an array of at least 2 types)'; }); + assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to union(types, [name]) combinator (expected a string)'; }); + } + + var displayName = name || getDefaultName(types); + var identity = types.every(isIdentity); + + function Union(value, path) { + + if (true) { + if (identity) { + return value; + } + } + + var type = Union.dispatch(value); + if (!type && Union.is(value)) { + return value; + } + + if (false) { + if (identity) { + forbidNewOperator(this, Union); + } + path = path || [displayName]; + assert(isFunction(type), function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + path.join('/') + ' (no constructor returned by dispatch)'; }); + path[path.length - 1] += '(' + getTypeName(type) + ')'; + } + + return create(type, value, path); + } + + Union.meta = { + kind: 'union', + types: types, + name: name, + identity: identity + }; + + Union.displayName = displayName; + + Union.is = function (x) { + return types.some(function (type) { + return is(x, type); + }); + }; + + Union.dispatch = function (x) { // default dispatch implementation + for (var i = 0, len = types.length; i < len; i++ ) { + var type = types[i]; + if (isUnion(type)) { // handle union of unions + var t = type.dispatch(x); + if (!isNil(t)) { + return t; + } + } + else if (is(x, type)) { + return type; + } + } + }; + + Union.update = function (instance, patch) { + return Union(assert.update(instance, patch)); + }; + + return Union; + } + + union.getDefaultName = getDefaultName; + module.exports = union; + + + +/***/ }, +/* 196 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isTypeName = __webpack_require__(172); + var FunctionType = __webpack_require__(166); + var isArray = __webpack_require__(160); + var list = __webpack_require__(185); + var isObject = __webpack_require__(159); + var create = __webpack_require__(174); + var isNil = __webpack_require__(149); + var isBoolean = __webpack_require__(163); + var tuple = __webpack_require__(194); + var getFunctionName = __webpack_require__(152); + var getTypeName = __webpack_require__(157); + var isType = __webpack_require__(158); + + function getDefaultName(domain, codomain) { + return '(' + domain.map(getTypeName).join(', ') + ') => ' + getTypeName(codomain); + } + + function isInstrumented(f) { + return FunctionType.is(f) && isObject(f.instrumentation); + } + + function getOptionalArgumentsIndex(types) { + var end = types.length; + var areAllMaybes = false; + for (var i = end - 1; i >= 0; i--) { + var type = types[i]; + if (!isType(type) || type.meta.kind !== 'maybe') { + return (i + 1); + } else { + areAllMaybes = true; + } + } + return areAllMaybes ? 0 : end; + } + + function func(domain, codomain, name) { + + domain = isArray(domain) ? domain : [domain]; // handle handy syntax for unary functions + + if (false) { + assert(list(FunctionType).is(domain), function () { return 'Invalid argument domain ' + assert.stringify(domain) + ' supplied to func(domain, codomain, [name]) combinator (expected an array of types)'; }); + assert(FunctionType.is(codomain), function () { return 'Invalid argument codomain ' + assert.stringify(codomain) + ' supplied to func(domain, codomain, [name]) combinator (expected a type)'; }); + assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to func(domain, codomain, [name]) combinator (expected a string)'; }); + } + + var displayName = name || getDefaultName(domain, codomain); + var domainLength = domain.length; + var optionalArgumentsIndex = getOptionalArgumentsIndex(domain); + + function FuncType(value, path) { + + if (!isInstrumented(value)) { // automatically instrument the function + return FuncType.of(value); + } + + if (false) { + path = path || [displayName]; + assert(FuncType.is(value), function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + path.join('/'); }); + } + + return value; + } + + FuncType.meta = { + kind: 'func', + domain: domain, + codomain: codomain, + name: name, + identity: true + }; + + FuncType.displayName = displayName; + + FuncType.is = function (x) { + return isInstrumented(x) && + x.instrumentation.domain.length === domainLength && + x.instrumentation.domain.every(function (type, i) { + return type === domain[i]; + }) && + x.instrumentation.codomain === codomain; + }; + + FuncType.of = function (f, curried) { + + if (false) { + assert(FunctionType.is(f), function () { return 'Invalid argument f supplied to func.of ' + displayName + ' (expected a function)'; }); + assert(isNil(curried) || isBoolean(curried), function () { return 'Invalid argument curried ' + assert.stringify(curried) + ' supplied to func.of ' + displayName + ' (expected a boolean)'; }); + } + + if (FuncType.is(f)) { // makes FuncType.of idempotent + return f; + } + + function fn() { + var args = Array.prototype.slice.call(arguments); + var argsLength = args.length; + + if (false) { + // type-check arguments + var tupleLength = curried ? argsLength : Math.max(argsLength, optionalArgumentsIndex); + tuple(domain.slice(0, tupleLength), 'arguments of function ' + displayName)(args); + } + + if (curried && argsLength < domainLength) { + if (false) { + assert(argsLength > 0, 'Invalid arguments.length = 0 for curried function ' + displayName); + } + var g = Function.prototype.bind.apply(f, [this].concat(args)); + var newDomain = func(domain.slice(argsLength), codomain); + return newDomain.of(g, true); + } + else { + return create(codomain, f.apply(this, args)); + } + } + + fn.instrumentation = { + domain: domain, + codomain: codomain, + f: f + }; + + fn.displayName = getFunctionName(f); + + return fn; + + }; + + return FuncType; + + } + + func.getDefaultName = getDefaultName; + func.getOptionalArgumentsIndex = getOptionalArgumentsIndex; + module.exports = func; + + +/***/ }, +/* 197 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isTypeName = __webpack_require__(172); + var isFunction = __webpack_require__(148); + var isArray = __webpack_require__(160); + var forbidNewOperator = __webpack_require__(173); + var is = __webpack_require__(175); + var getTypeName = __webpack_require__(157); + var isIdentity = __webpack_require__(173); + + function getDefaultName(types) { + return types.map(getTypeName).join(' & '); + } + + function intersection(types, name) { + + if (false) { + assert(isArray(types) && types.every(isFunction) && types.length >= 2, function () { return 'Invalid argument types ' + assert.stringify(types) + ' supplied to intersection(types, [name]) combinator (expected an array of at least 2 types)'; }); + assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to intersection(types, [name]) combinator (expected a string)'; }); + } + + var displayName = name || getDefaultName(types); + var identity = types.every(isIdentity); + + function Intersection(value, path) { + + if (false) { + if (identity) { + forbidNewOperator(this, Intersection); + } + path = path || [displayName]; + assert(Intersection.is(value), function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + path.join('/'); }); + } + + return value; + } + + Intersection.meta = { + kind: 'intersection', + types: types, + name: name, + identity: identity + }; + + Intersection.displayName = displayName; + + Intersection.is = function (x) { + return types.every(function (type) { + return is(x, type); + }); + }; + + Intersection.update = function (instance, patch) { + return Intersection(assert.update(instance, patch)); + }; + + return Intersection; + } + + intersection.getDefaultName = getDefaultName; + module.exports = intersection; + + + +/***/ }, +/* 198 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isTypeName = __webpack_require__(172); + var String = __webpack_require__(178); + var Function = __webpack_require__(166); + var isBoolean = __webpack_require__(163); + var isObject = __webpack_require__(159); + var isNil = __webpack_require__(149); + var create = __webpack_require__(174); + var getTypeName = __webpack_require__(157); + var dict = __webpack_require__(180); + var getDefaultInterfaceName = __webpack_require__(189); + var isIdentity = __webpack_require__(173); + var is = __webpack_require__(175); + var extend = __webpack_require__(190); + var assign = __webpack_require__(199); + + function extendInterface(mixins, name) { + return extend(inter, mixins, name); + } + + function getOptions(options) { + if (!isObject(options)) { + options = isNil(options) ? {} : { name: options }; + } + if (!options.hasOwnProperty('strict')) { + options.strict = inter.strict; + } + return options; + } + + function inter(props, options) { + + options = getOptions(options); + var name = options.name; + var strict = options.strict; + + if (false) { + assert(dict(String, Function).is(props), function () { return 'Invalid argument props ' + assert.stringify(props) + ' supplied to interface(props, [options]) combinator (expected a dictionary String -> Type)'; }); + assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to interface(props, [options]) combinator (expected a string)'; }); + assert(isBoolean(strict), function () { return 'Invalid argument strict ' + assert.stringify(strict) + ' supplied to struct(props, [options]) combinator (expected a boolean)'; }); + } + + var displayName = name || getDefaultInterfaceName(props); + var identity = Object.keys(props).map(function (prop) { return props[prop]; }).every(isIdentity); + + function Interface(value, path) { + + if (true) { + if (identity) { + return value; // just trust the input if elements must not be hydrated + } + } + + if (false) { + path = path || [displayName]; + assert(!isNil(value), function () { return 'Invalid value ' + value + ' supplied to ' + path.join('/'); }); + // strictness + if (strict) { + for (var k in value) { + assert(props.hasOwnProperty(k), function () { return 'Invalid additional prop "' + k + '" supplied to ' + path.join('/'); }); + } + } + } + + var idempotent = true; + var ret = identity ? {} : assign({}, value); + for (var prop in props) { + var expected = props[prop]; + var actual = value[prop]; + var instance = create(expected, actual, ( false ? path.concat(prop + ': ' + getTypeName(expected)) : null )); + idempotent = idempotent && ( actual === instance ); + ret[prop] = instance; + } + + if (idempotent) { // implements idempotency + ret = value; + } + + if (false) { + Object.freeze(ret); + } + + return ret; + + } + + Interface.meta = { + kind: 'interface', + props: props, + name: name, + identity: identity, + strict: strict + }; + + Interface.displayName = displayName; + + Interface.is = function (x) { + if (isNil(x)) { + return false; + } + if (strict) { + for (var k in x) { + if (!props.hasOwnProperty(k)) { + return false; + } + } + } + for (var prop in props) { + if (!is(x[prop], props[prop])) { + return false; + } + } + return true; + }; + + Interface.update = function (instance, patch) { + return Interface(assert.update(instance, patch)); + }; + + Interface.extend = function (xs, name) { + return extendInterface([Interface].concat(xs), name); + }; + + return Interface; + } + + inter.strict = false; + inter.getOptions = getOptions; + inter.getDefaultName = getDefaultInterfaceName; + inter.extend = extendInterface; + module.exports = inter; + + +/***/ }, +/* 199 */ +/***/ function(module, exports) { + + function assign(x, y) { + for (var k in y) { + x[k] = y[k]; + } + return x; + } + + module.exports = assign; + +/***/ }, +/* 200 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isObject = __webpack_require__(159); + var isFunction = __webpack_require__(148); + var isArray = __webpack_require__(160); + var isNumber = __webpack_require__(169); + var assign = __webpack_require__(199); + + function getShallowCopy(x) { + if (isObject(x)) { + if (x instanceof Date || x instanceof RegExp) { + return x; + } + return assign({}, x); + } + if (isArray(x)) { + return x.concat(); + } + return x; + } + + function isCommand(k) { + return update.commands.hasOwnProperty(k); + } + + function getCommand(k) { + return update.commands[k]; + } + + function update(instance, patch) { + + if (false) { + assert(isObject(patch), function () { return 'Invalid argument patch ' + assert.stringify(patch) + ' supplied to function update(instance, patch): expected an object containing commands'; }); + } + + var value = instance; + var isChanged = false; + var newValue; + for (var k in patch) { + if (patch.hasOwnProperty(k)) { + if (isCommand(k)) { + newValue = getCommand(k)(patch[k], value); + if (newValue !== instance) { + isChanged = true; + value = newValue; + } else { + value = instance; + } + } + else { + if (value === instance) { + value = getShallowCopy(instance); + } + newValue = update(value[k], patch[k]); + isChanged = isChanged || ( newValue !== value[k] ); + value[k] = newValue; + } + } + } + return isChanged ? value : instance; + } + + // built-in commands + + function $apply(f, value) { + if (false) { + assert(isFunction(f), 'Invalid argument f supplied to immutability helper { $apply: f } (expected a function)'); + } + return f(value); + } + + function $push(elements, arr) { + if (false) { + assert(isArray(elements), 'Invalid argument elements supplied to immutability helper { $push: elements } (expected an array)'); + assert(isArray(arr), 'Invalid value supplied to immutability helper $push (expected an array)'); + } + if (elements.length > 0) { + return arr.concat(elements); + } + return arr; + } + + function $remove(keys, obj) { + if (false) { + assert(isArray(keys), 'Invalid argument keys supplied to immutability helper { $remove: keys } (expected an array)'); + assert(isObject(obj), 'Invalid value supplied to immutability helper $remove (expected an object)'); + } + if (keys.length > 0) { + obj = getShallowCopy(obj); + for (var i = 0, len = keys.length; i < len; i++ ) { + delete obj[keys[i]]; + } + } + return obj; + } + + function $set(value) { + return value; + } + + function $splice(splices, arr) { + if (false) { + assert(isArray(splices) && splices.every(isArray), 'Invalid argument splices supplied to immutability helper { $splice: splices } (expected an array of arrays)'); + assert(isArray(arr), 'Invalid value supplied to immutability helper $splice (expected an array)'); + } + if (splices.length > 0) { + arr = getShallowCopy(arr); + return splices.reduce(function (acc, splice) { + acc.splice.apply(acc, splice); + return acc; + }, arr); + } + return arr; + } + + function $swap(config, arr) { + if (false) { + assert(isObject(config), 'Invalid argument config supplied to immutability helper { $swap: config } (expected an object)'); + assert(isNumber(config.from), 'Invalid argument config.from supplied to immutability helper { $swap: config } (expected a number)'); + assert(isNumber(config.to), 'Invalid argument config.to supplied to immutability helper { $swap: config } (expected a number)'); + assert(isArray(arr), 'Invalid value supplied to immutability helper $swap (expected an array)'); + } + if (config.from !== config.to) { + arr = getShallowCopy(arr); + var element = arr[config.to]; + arr[config.to] = arr[config.from]; + arr[config.from] = element; + } + return arr; + } + + function $unshift(elements, arr) { + if (false) { + assert(isArray(elements), 'Invalid argument elements supplied to immutability helper {$unshift: elements} (expected an array)'); + assert(isArray(arr), 'Invalid value supplied to immutability helper $unshift (expected an array)'); + } + if (elements.length > 0) { + return elements.concat(arr); + } + return arr; + } + + function $merge(whatToMerge, value) { + var isChanged = false; + var result = getShallowCopy(value); + for (var k in whatToMerge) { + if (whatToMerge.hasOwnProperty(k)) { + result[k] = whatToMerge[k]; + isChanged = isChanged || ( result[k] !== value[k] ); + } + } + return isChanged ? result : value; + } + + update.commands = { + $apply: $apply, + $push: $push, + $remove: $remove, + $set: $set, + $splice: $splice, + $swap: $swap, + $unshift: $unshift, + $merge: $merge + }; + + module.exports = update; + + +/***/ }, +/* 201 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(147); + var isFunction = __webpack_require__(148); + var isType = __webpack_require__(158); + var Any = __webpack_require__(153); + + module.exports = function match(x) { + var type, guard, f, count; + for (var i = 1, len = arguments.length; i < len; ) { + type = arguments[i]; + guard = arguments[i + 1]; + f = arguments[i + 2]; + + if (isFunction(f) && !isType(f)) { + i = i + 3; + } + else { + f = guard; + guard = Any.is; + i = i + 2; + } + + if (false) { + count = (count || 0) + 1; + assert(isType(type), function () { return 'Invalid type in clause #' + count; }); + assert(isFunction(guard), function () { return 'Invalid guard in clause #' + count; }); + assert(isFunction(f), function () { return 'Invalid block in clause #' + count; }); + } + + if (type.is(x) && guard(x)) { + return f(x); + } + } + assert.fail('Match error'); + }; + + +/***/ }, +/* 202 */ +/***/ function(module, exports, __webpack_require__) { + + var _require = __webpack_require__(145); + + var BreakpointResult = _require.BreakpointResult; + var Location = _require.Location; + + var defer = __webpack_require__(144); + + var bpClients = void 0; + var threadClient = void 0; + var tabTarget = void 0; + var debuggerClient = void 0; + + function setupCommands(dependencies) { + threadClient = dependencies.threadClient; + tabTarget = dependencies.tabTarget; + debuggerClient = dependencies.debuggerClient; + bpClients = {}; + } + + function resume() { + return new Promise(resolve => { + threadClient.resume(resolve); + }); + } + + function stepIn() { + return new Promise(resolve => { + threadClient.stepIn(resolve); + }); + } + + function stepOver() { + return new Promise(resolve => { + threadClient.stepOver(resolve); + }); + } + + function stepOut() { + return new Promise(resolve => { + threadClient.stepOut(resolve); + }); + } + + function breakOnNext() { + return threadClient.breakOnNext(); + } + + function sourceContents(sourceId) { + var sourceClient = threadClient.source({ actor: sourceId }); + return sourceClient.source(); + } + + function setBreakpoint(location, condition, noSliding) { + var sourceClient = threadClient.source({ actor: location.sourceId }); + + return sourceClient.setBreakpoint({ + line: location.line, + column: location.column, + condition, + noSliding + }).then(res => onNewBreakpoint(location, res)); + } + + function onNewBreakpoint(location, res) { + var bpClient = res[1]; + var actualLocation = res[0].actualLocation; + bpClients[bpClient.actor] = bpClient; + + // Firefox only returns `actualLocation` if it actually changed, + // but we want it always to exist. Format `actualLocation` if it + // exists, otherwise use `location`. + actualLocation = actualLocation ? { + sourceId: actualLocation.source.actor, + line: actualLocation.line, + column: actualLocation.column + } : location; + + return BreakpointResult({ + id: bpClient.actor, + actualLocation: Location(actualLocation) + }); + } + + function removeBreakpoint(breakpointId) { + var bpClient = bpClients[breakpointId]; + bpClients[breakpointId] = null; + return bpClient.remove(); + } + + function setBreakpointCondition(breakpointId, location, condition, noSliding) { + var bpClient = bpClients[breakpointId]; + bpClients[breakpointId] = null; + + return bpClient.setCondition(threadClient, condition, noSliding).then(_bpClient => onNewBreakpoint(location, [{}, _bpClient])); + } + + function evaluate(script, _ref) { + var frameId = _ref.frameId; + + var deferred = defer(); + tabTarget.activeConsole.evaluateJS(script, result => { + deferred.resolve(result); + }, { frameActor: frameId }); + + return deferred.promise; + } + + function debuggeeCommand(script) { + tabTarget.activeConsole.evaluateJS(script, () => {}); + + var consoleActor = tabTarget.form.consoleActor; + var request = debuggerClient._activeRequests.get(consoleActor); + request.emit("json-reply", {}); + debuggerClient._activeRequests.delete(consoleActor); + + return Promise.resolve(); + } + + function navigate(url) { + return tabTarget.activeTab.navigateTo(url); + } + + function reload() { + return tabTarget.activeTab.reload(); + } + + function getProperties(grip) { + var objClient = threadClient.pauseGrip(grip); + return objClient.getPrototypeAndProperties(); + } + + function pauseOnExceptions(shouldPauseOnExceptions, shouldIgnoreCaughtExceptions) { + return threadClient.pauseOnExceptions(shouldPauseOnExceptions, shouldIgnoreCaughtExceptions); + } + + function prettyPrint(sourceId, indentSize) { + var sourceClient = threadClient.source({ actor: sourceId }); + return sourceClient.prettyPrint(indentSize); + } + + function disablePrettyPrint(sourceId) { + var sourceClient = threadClient.source({ actor: sourceId }); + return sourceClient.disablePrettyPrint(); + } + + var clientCommands = { + resume, + stepIn, + stepOut, + stepOver, + breakOnNext, + sourceContents, + setBreakpoint, + removeBreakpoint, + setBreakpointCondition, + evaluate, + debuggeeCommand, + navigate, + reload, + getProperties, + pauseOnExceptions, + prettyPrint, + disablePrettyPrint + }; + + module.exports = { + setupCommands, + clientCommands + }; + +/***/ }, +/* 203 */ +/***/ function(module, exports, __webpack_require__) { + + var paused = (() => { + var _ref = _asyncToGenerator(function* (_, packet) { + // If paused by an explicit interrupt, which are generated by the + // slow script dialog and internal events such as setting + // breakpoints, ignore the event. + if (packet.why.type === "interrupted" && !packet.why.onNext) { + return; + } + + // Eagerly fetch the frames + var response = yield threadClient.getFrames(0, CALL_STACK_PAGE_SIZE); + var frames = response.frames.map(createFrame); + + var pause = Object.assign({}, packet, { + frame: createFrame(packet.frame), + frames: frames + }); + + actions.paused(pause); + }); + + return function paused(_x, _x2) { + return _ref.apply(this, arguments); + }; + })(); + + function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + + var _require = __webpack_require__(204); + + var createFrame = _require.createFrame; + var createSource = _require.createSource; + + + var CALL_STACK_PAGE_SIZE = 1000; + + var threadClient = void 0; + var actions = void 0; + + function setupEvents(dependencies) { + threadClient = dependencies.threadClient; + actions = dependencies.actions; + } + + function resumed(_, packet) { + actions.resumed(packet); + } + + function newSource(_, _ref2) { + var source = _ref2.source; + + actions.newSource(createSource(source)); + } + + var clientEvents = { + paused, + resumed, + newSource + }; + + module.exports = { + setupEvents, + clientEvents + }; + +/***/ }, +/* 204 */ +/***/ function(module, exports, __webpack_require__) { + + var _require = __webpack_require__(145); + + var Source = _require.Source; + var Frame = _require.Frame; + var Location = _require.Location; + + + function createFrame(frame) { + var title = void 0; + if (frame.type == "call") { + var c = frame.callee; + title = c.name || c.userDisplayName || c.displayName || "(anonymous)"; + } else { + title = "(" + frame.type + ")"; + } + + return Frame({ + id: frame.actor, + displayName: title, + location: Location({ + sourceId: frame.where.source.actor, + line: frame.where.line, + column: frame.where.column + }), + this: frame.this, + scope: frame.environment + }); + } + + function createSource(source) { + return Source({ + id: source.actor, + url: source.url, + isPrettyPrinted: false, + sourceMapURL: source.sourceMapURL + }); + } + + module.exports = { createFrame, createSource }; + +/***/ }, +/* 205 */ +/***/ function(module, exports, __webpack_require__) { + + /* eslint-disable */ + + var _require = __webpack_require__(206); + + var connect = _require.connect; + + var defer = __webpack_require__(144); + + var _require2 = __webpack_require__(145); + + var Tab = _require2.Tab; + + var _require3 = __webpack_require__(89); + + var isEnabled = _require3.isEnabled; + var getValue = _require3.getValue; + + var networkRequest = __webpack_require__(207); + + var _require4 = __webpack_require__(208); + + var setupCommands = _require4.setupCommands; + var clientCommands = _require4.clientCommands; + + var _require5 = __webpack_require__(209); + + var setupEvents = _require5.setupEvents; + var clientEvents = _require5.clientEvents; + var pageEvents = _require5.pageEvents; + + // TODO: figure out a way to avoid patching native prototypes. + // Unfortunately the Chrome client requires it to work. + + Array.prototype.peekLast = function () { + return this[this.length - 1]; + }; + + var connection = void 0; + + function createTabs(tabs) { + + return tabs.filter(tab => { + var isPage = tab.type == "page"; + return isPage; + }).map(tab => { + return Tab({ + title: tab.title, + url: tab.url, + id: tab.id, + tab, + browser: "chrome" + }); + }); + } + + function connectClient() { + var deferred = defer(); + + if (!getValue("chrome.debug")) { + return deferred.resolve(createTabs([])); + } + + var webSocketPort = getValue("chrome.webSocketPort"); + var url = `http://localhost:${ webSocketPort }/json/list`; + networkRequest(url).then(res => { + deferred.resolve(createTabs(JSON.parse(res.content))); + }).catch(err => { + console.log(err); + deferred.reject(); + }); + + return deferred.promise; + } + + function connectTab(tab) { + return connect(tab.webSocketDebuggerUrl).then(conn => { + connection = conn; + }); + } + + function connectNode(url) { + return connect(url).then(conn => { + connection = conn; + }); + } + + function initPage(actions) { + var agents = connection._agents; + + setupCommands({ agents: agents }); + setupEvents({ actions, agents }); + + agents.Debugger.enable(); + agents.Debugger.setPauseOnExceptions("none"); + agents.Debugger.setAsyncCallStackDepth(0); + + agents.Runtime.enable(); + agents.Runtime.run(); + + agents.Page.enable(); + + connection.registerDispatcher("Debugger", clientEvents); + connection.registerDispatcher("Page", pageEvents); + } + + module.exports = { + connectClient, + clientCommands, + connectNode, + connectTab, + initPage + }; + +/***/ }, +/* 206 */ +/***/ function(module, exports) { + + module.exports = {}; + +/***/ }, +/* 207 */ +/***/ function(module, exports) { + + function networkRequest(url, opts) { + return new Promise((resolve, reject) => { + var req = new XMLHttpRequest(); + + req.addEventListener("readystatechange", () => { + if (req.readyState === XMLHttpRequest.DONE) { + if (req.status === 200) { + resolve({ content: req.responseText }); + } else { + resolve(req.statusText); + } + } + }); + + // Not working yet. + // if (!opts.loadFromCache) { + // req.channel.loadFlags = ( + // Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE | + // Components.interfaces.nsIRequest.INHIBIT_CACHING | + // Components.interfaces.nsIRequest.LOAD_ANONYMOUS + // ); + // } + + req.open("GET", url); + req.send(); + }); + } + + module.exports = networkRequest; + +/***/ }, +/* 208 */ +/***/ function(module, exports, __webpack_require__) { + + var _require = __webpack_require__(145); + + var BreakpointResult = _require.BreakpointResult; + var Location = _require.Location; + + + var debuggerAgent = void 0; + var runtimeAgent = void 0; + var pageAgent = void 0; + + function setupCommands(_ref) { + var agents = _ref.agents; + + debuggerAgent = agents.Debugger; + runtimeAgent = agents.Runtime; + pageAgent = agents.Page; + } + + function resume() { + return debuggerAgent.resume(); + } + + function stepIn() { + return debuggerAgent.stepInto(); + } + + function stepOver() { + return debuggerAgent.stepOver(); + } + + function stepOut() { + return debuggerAgent.stepOut(); + } + + function pauseOnExceptions(toggle) { + var state = toggle ? "uncaught" : "none"; + return debuggerAgent.setPauseOnExceptions(state); + } + + function breakOnNext() { + return debuggerAgent.pause(); + } + + function sourceContents(sourceId) { + return debuggerAgent.getScriptSource(sourceId, (err, contents) => ({ + source: contents, + contentType: null + })); + } + + function setBreakpoint(location, condition) { + return new Promise((resolve, reject) => { + return debuggerAgent.setBreakpoint({ + scriptId: location.sourceId, + lineNumber: location.line - 1, + columnNumber: location.column + }, (err, breakpointId, actualLocation) => { + if (err) { + reject(err); + return; + } + + actualLocation = actualLocation ? { + sourceId: actualLocation.scriptId, + line: actualLocation.lineNumber + 1, + column: actualLocation.columnNumber + } : location; + + resolve(BreakpointResult({ + id: breakpointId, + actualLocation: Location(actualLocation) + })); + }); + }); + } + + function removeBreakpoint(breakpointId) { + // TODO: resolve promise when request is completed. + return new Promise((resolve, reject) => { + resolve(debuggerAgent.removeBreakpoint(breakpointId)); + }); + } + + function evaluate(script) { + return runtimeAgent.evaluate(script, (_, result) => { + return result; + }); + } + + function debuggeeCommand(script) { + evaluate(script); + return Promise.resolve(); + } + + function navigate(url) { + return pageAgent.navigate(url, (_, result) => { + return result; + }); + } + + var clientCommands = { + resume, + stepIn, + stepOut, + stepOver, + pauseOnExceptions, + breakOnNext, + sourceContents, + setBreakpoint, + removeBreakpoint, + evaluate, + debuggeeCommand, + navigate + }; + + module.exports = { + setupCommands, + clientCommands + }; + +/***/ }, +/* 209 */ +/***/ function(module, exports, __webpack_require__) { + + var paused = (() => { + var _ref = _asyncToGenerator(function* (callFrames, reason, data, hitBreakpoints, asyncStackTrace) { + var frames = callFrames.map(function (frame) { + return Frame({ + id: frame.callFrameId, + displayName: frame.functionName, + location: Location({ + sourceId: frame.location.scriptId, + line: frame.location.lineNumber + 1, + column: frame.location.columnNumber + }) + }); + }); + + var frame = frames[0]; + var why = Object.assign({}, { + type: reason + }, data); + + pageAgent.setOverlayMessage("Paused in debugger.html"); + + yield actions.paused({ frame, why, frames }); + }); + + return function paused(_x, _x2, _x3, _x4, _x5) { + return _ref.apply(this, arguments); + }; + })(); + + function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + + var _require = __webpack_require__(145); + + var Source = _require.Source; + var Location = _require.Location; + var Frame = _require.Frame; + + + var actions = void 0; + var pageAgent = void 0; + + function setupEvents(dependencies) { + actions = dependencies.actions; + pageAgent = dependencies.agents.Page; + } + + // Debugger Events + function scriptParsed(scriptId, url, startLine, startColumn, endLine, endColumn, executionContextId, hash, isContentScript, isInternalScript, isLiveEdit, sourceMapURL, hasSourceURL, deprecatedCommentWasUsed) { + if (isContentScript) { + return; + } + + actions.newSource(Source({ + id: scriptId, + url, + sourceMapURL, + isPrettyPrinted: false + })); + } + + function scriptFailedToParse() {} + + function resumed() { + pageAgent.setOverlayMessage(undefined); + actions.resumed(); + } + + function globalObjectCleared() {} + + // Page Events + function frameNavigated(frame) { + actions.navigate(); + } + + function frameStartedLoading() { + actions.willNavigate(); + } + + function domContentEventFired() {} + + function loadEventFired() {} + + function frameStoppedLoading() {} + + var clientEvents = { + scriptParsed, + scriptFailedToParse, + paused, + resumed, + globalObjectCleared + }; + + var pageEvents = { + frameNavigated, + frameStartedLoading, + domContentEventFired, + loadEventFired, + frameStoppedLoading + }; + + module.exports = { + setupEvents, + pageEvents, + clientEvents + }; + +/***/ }, +/* 210 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + + var classnames = __webpack_require__(211); + + var _require = __webpack_require__(89); + + var getValue = _require.getValue; + var isDevelopment = _require.isDevelopment; + + + __webpack_require__(212); + + function themeClass() { + var theme = getValue("theme"); + return `theme-${ theme }`; + } + + module.exports = function (component) { + return dom.div({ + className: classnames("theme-body", { [themeClass()]: isDevelopment() }), + style: { flex: 1 } + }, React.createElement(component)); + }; + +/***/ }, +/* 211 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! + Copyright (c) 2016 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames + */ + /* global define */ + + (function () { + 'use strict'; + + var hasOwn = {}.hasOwnProperty; + + function classNames () { + var classes = []; + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + if (!arg) continue; + + var argType = typeof arg; + + if (argType === 'string' || argType === 'number') { + classes.push(arg); + } else if (Array.isArray(arg)) { + classes.push(classNames.apply(null, arg)); + } else if (argType === 'object') { + for (var key in arg) { + if (hasOwn.call(arg, key) && arg[key]) { + classes.push(key); + } + } + } + } + + return classes.join(' '); + } + + if (typeof module !== 'undefined' && module.exports) { + module.exports = classNames; + } else if (true) { + // register as 'classnames', consistent with npm package name + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function () { + return classNames; + }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else { + window.classNames = classNames; + } + }()); + + +/***/ }, +/* 212 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 213 */, +/* 214 */, +/* 215 */, +/* 216 */ +/***/ function(module, exports, __webpack_require__) { + + + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + /* global window */ + + var _require = __webpack_require__(3); + + var createStore = _require.createStore; + var applyMiddleware = _require.applyMiddleware; + + var _require2 = __webpack_require__(217); + + var waitUntilService = _require2.waitUntilService; + + var _require3 = __webpack_require__(218); + + var log = _require3.log; + + var _require4 = __webpack_require__(219); + + var history = _require4.history; + + var _require5 = __webpack_require__(220); + + var promise = _require5.promise; + + var _require6 = __webpack_require__(225); + + var thunk = _require6.thunk; + + + /** + * This creates a dispatcher with all the standard middleware in place + * that all code requires. It can also be optionally configured in + * various ways, such as logging and recording. + * + * @param {object} opts: + * - log: log all dispatched actions to console + * - history: an array to store every action in. Should only be + * used in tests. + * - middleware: array of middleware to be included in the redux store + */ + var configureStore = function () { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + var middleware = [thunk(opts.makeThunkArgs), promise, + + // Order is important: services must go last as they always + // operate on "already transformed" actions. Actions going through + // them shouldn't have any special fields like promises, they + // should just be normal JSON objects. + waitUntilService]; + + if (opts.history) { + middleware.push(history(opts.history)); + } + + if (opts.middleware) { + opts.middleware.forEach(fn => middleware.push(fn)); + } + + if (opts.log) { + middleware.push(log); + } + + // Hook in the redux devtools browser extension if it exists + var devtoolsExt = typeof window === "object" && window.devToolsExtension ? window.devToolsExtension() : f => f; + + return applyMiddleware.apply(undefined, middleware)(devtoolsExt(createStore)); + }; + + module.exports = configureStore; + +/***/ }, +/* 217 */ +/***/ function(module, exports) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; + + /** + * A middleware which acts like a service, because it is stateful + * and "long-running" in the background. It provides the ability + * for actions to install a function to be run once when a specific + * condition is met by an action coming through the system. Think of + * it as a thunk that blocks until the condition is met. Example: + * + * ```js + * const services = { WAIT_UNTIL: require('wait-service').NAME }; + * + * { type: services.WAIT_UNTIL, + * predicate: action => action.type === constants.ADD_ITEM, + * run: (dispatch, getState, action) => { + * // Do anything here. You only need to accept the arguments + * // if you need them. `action` is the action that satisfied + * // the predicate. + * } + * } + * ``` + */ + + var NAME = exports.NAME = "@@service/waitUntil"; + + function waitUntilService(_ref) { + var dispatch = _ref.dispatch; + var getState = _ref.getState; + + var pending = []; + + function checkPending(action) { + var readyRequests = []; + var stillPending = []; + + // Find the pending requests whose predicates are satisfied with + // this action. Wait to run the requests until after we update the + // pending queue because the request handler may synchronously + // dispatch again and run this service (that use case is + // completely valid). + for (var request of pending) { + if (request.predicate(action)) { + readyRequests.push(request); + } else { + stillPending.push(request); + } + } + + pending = stillPending; + for (var _request of readyRequests) { + _request.run(dispatch, getState, action); + } + } + + return next => action => { + if (action.type === NAME) { + pending.push(action); + return null; + } + var result = next(action); + checkPending(action); + return result; + }; + } + exports.waitUntilService = waitUntilService; + +/***/ }, +/* 218 */ +/***/ function(module, exports) { + + /** + * A middleware that logs all actions coming through the system + * to the console. + */ + function log(_ref) { + var dispatch = _ref.dispatch; + var getState = _ref.getState; + + return next => action => { + var actionText = JSON.stringify(action, null, 2); + var truncatedActionText = actionText.slice(0, 1000) + "..."; + console.log(`[DISPATCH ${ action.type }]`, action, truncatedActionText); + next(action); + }; + } + + exports.log = log; + +/***/ }, +/* 219 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var _require = __webpack_require__(89); + + var isDevelopment = _require.isDevelopment; + + /** + * A middleware that stores every action coming through the store in the passed + * in logging object. Should only be used for tests, as it collects all + * action information, which will cause memory bloat. + */ + + exports.history = function () { + var log = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + return (_ref) => { + var dispatch = _ref.dispatch; + var getState = _ref.getState; + + if (isDevelopment()) { + console.warn("Using history middleware stores all actions in state for " + "testing and devtools is not currently running in test " + "mode. Be sure this is intentional."); + } + return next => action => { + log.push(action); + next(action); + }; + }; + }; + +/***/ }, +/* 220 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var defer = __webpack_require__(144); + + var _require = __webpack_require__(221); + + var entries = _require.entries; + var toObject = _require.toObject; + + var _require2 = __webpack_require__(223); + + var executeSoon = _require2.executeSoon; + + + var PROMISE = exports.PROMISE = "@@dispatch/promise"; + var seqIdVal = 1; + + function seqIdGen() { + return seqIdVal++; + } + + function promiseMiddleware(_ref) { + var dispatch = _ref.dispatch; + var getState = _ref.getState; + + return next => action => { + if (!(PROMISE in action)) { + return next(action); + } + + var promiseInst = action[PROMISE]; + var seqId = seqIdGen().toString(); + + // Create a new action that doesn't have the promise field and has + // the `seqId` field that represents the sequence id + action = Object.assign(toObject(entries(action).filter(pair => pair[0] !== PROMISE)), { seqId }); + + dispatch(Object.assign({}, action, { status: "start" })); + + // Return the promise so action creators can still compose if they + // want to. + var deferred = defer(); + promiseInst.then(value => { + executeSoon(() => { + dispatch(Object.assign({}, action, { + status: "done", + value: value + })); + deferred.resolve(value); + }); + }, error => { + executeSoon(() => { + dispatch(Object.assign({}, action, { + status: "error", + error: error.message || error + })); + deferred.reject(error); + }); + }); + return deferred.promise; + }; + } + + exports.promise = promiseMiddleware; + +/***/ }, +/* 221 */ +/***/ function(module, exports, __webpack_require__) { + + var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + + function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + + /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var co = __webpack_require__(222); + + function asPaused(client, func) { + if (client.state != "paused") { + return co(function* () { + yield client.interrupt(); + var result = void 0; + + try { + result = yield func(); + } catch (e) { + // Try to put the debugger back in a working state by resuming + // it + yield client.resume(); + throw e; + } + + yield client.resume(); + return result; + }); + } + return func(); + } + + function handleError(err) { + console.log("ERROR: ", err); + } + + function promisify(context, method) { + for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { + args[_key - 2] = arguments[_key]; + } + + return new Promise((resolve, reject) => { + args.push(response => { + if (response.error) { + reject(response); + } else { + resolve(response); + } + }); + method.apply(context, args); + }); + } + + function truncateStr(str, size) { + if (str.length > size) { + return str.slice(0, size) + "..."; + } + return str; + } + + function endTruncateStr(str, size) { + if (str.length > size) { + return "..." + str.slice(str.length - size); + } + return str; + } + + var msgId = 1; + function workerTask(worker, method) { + return function () { + for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + return new Promise((resolve, reject) => { + var id = msgId++; + worker.postMessage({ id, method, args }); + + var listener = (_ref) => { + var result = _ref.data; + + if (result.id !== id) { + return; + } + + worker.removeEventListener("message", listener); + if (result.error) { + reject(result.error); + } else { + resolve(result.response); + } + }; + + worker.addEventListener("message", listener); + }); + }; + } + + /** + * Interleaves two arrays element by element, returning the combined array, like + * a zip. In the case of arrays with different sizes, undefined values will be + * interleaved at the end along with the extra values of the larger array. + * + * @param Array a + * @param Array b + * @returns Array + * The combined array, in the form [a1, b1, a2, b2, ...] + */ + function zip(a, b) { + if (!b) { + return a; + } + if (!a) { + return b; + } + var pairs = []; + for (var i = 0, aLength = a.length, bLength = b.length; i < aLength || i < bLength; i++) { + pairs.push([a[i], b[i]]); + } + return pairs; + } + + /** + * Converts an object into an array with 2-element arrays as key/value + * pairs of the object. `{ foo: 1, bar: 2}` would become + * `[[foo, 1], [bar 2]]` (order not guaranteed); + * + * @param object obj + * @returns array + */ + function entries(obj) { + return Object.keys(obj).map(k => [k, obj[k]]); + } + + function mapObject(obj, iteratee) { + return toObject(entries(obj).map((_ref2) => { + var _ref3 = _slicedToArray(_ref2, 2); + + var key = _ref3[0]; + var value = _ref3[1]; + + return [key, iteratee(key, value)]; + })); + } + + /** + * Takes an array of 2-element arrays as key/values pairs and + * constructs an object using them. + */ + function toObject(arr) { + var obj = {}; + for (var pair of arr) { + obj[pair[0]] = pair[1]; + } + return obj; + } + + /** + * Composes the given functions into a single function, which will + * apply the results of each function right-to-left, starting with + * applying the given arguments to the right-most function. + * `compose(foo, bar, baz)` === `args => foo(bar(baz(args)` + * + * @param ...function funcs + * @returns function + */ + function compose() { + for (var _len3 = arguments.length, funcs = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + funcs[_key3] = arguments[_key3]; + } + + return function () { + for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { + args[_key4] = arguments[_key4]; + } + + var initialValue = funcs[funcs.length - 1].apply(null, args); + var leftFuncs = funcs.slice(0, -1); + return leftFuncs.reduceRight((composed, f) => f(composed), initialValue); + }; + } + + function updateObj(obj, fields) { + return Object.assign({}, obj, fields); + } + + function throttle(func, ms) { + var timeout = void 0, + _this = void 0; + return function () { + for (var _len5 = arguments.length, args = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { + args[_key5] = arguments[_key5]; + } + + _this = this; + if (!timeout) { + timeout = setTimeout(() => { + func.apply.apply(func, [_this].concat(_toConsumableArray(args))); + timeout = null; + }, ms); + } + }; + } + + module.exports = { + asPaused, + handleError, + promisify, + truncateStr, + endTruncateStr, + workerTask, + zip, + entries, + toObject, + mapObject, + compose, + updateObj, + throttle + }; + +/***/ }, +/* 222 */ +/***/ function(module, exports) { + + + /** + * slice() reference. + */ + + var slice = Array.prototype.slice; + + /** + * Expose `co`. + */ + + module.exports = co['default'] = co.co = co; + + /** + * Wrap the given generator `fn` into a + * function that returns a promise. + * This is a separate function so that + * every `co()` call doesn't create a new, + * unnecessary closure. + * + * @param {GeneratorFunction} fn + * @return {Function} + * @api public + */ + + co.wrap = function (fn) { + createPromise.__generatorFunction__ = fn; + return createPromise; + function createPromise() { + return co.call(this, fn.apply(this, arguments)); + } + }; + + /** + * Execute the generator function or a generator + * and return a promise. + * + * @param {Function} fn + * @return {Promise} + * @api public + */ + + function co(gen) { + var ctx = this; + var args = slice.call(arguments, 1) + + // we wrap everything in a promise to avoid promise chaining, + // which leads to memory leak errors. + // see https://github.com/tj/co/issues/180 + return new Promise(function(resolve, reject) { + if (typeof gen === 'function') gen = gen.apply(ctx, args); + if (!gen || typeof gen.next !== 'function') return resolve(gen); + + onFulfilled(); + + /** + * @param {Mixed} res + * @return {Promise} + * @api private + */ + + function onFulfilled(res) { + var ret; + try { + ret = gen.next(res); + } catch (e) { + return reject(e); + } + next(ret); + } + + /** + * @param {Error} err + * @return {Promise} + * @api private + */ + + function onRejected(err) { + var ret; + try { + ret = gen.throw(err); + } catch (e) { + return reject(e); + } + next(ret); + } + + /** + * Get the next value in the generator, + * return a promise. + * + * @param {Object} ret + * @return {Promise} + * @api private + */ + + function next(ret) { + if (ret.done) return resolve(ret.value); + var value = toPromise.call(ctx, ret.value); + if (value && isPromise(value)) return value.then(onFulfilled, onRejected); + return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, ' + + 'but the following object was passed: "' + String(ret.value) + '"')); + } + }); + } + + /** + * Convert a `yield`ed value into a promise. + * + * @param {Mixed} obj + * @return {Promise} + * @api private + */ + + function toPromise(obj) { + if (!obj) return obj; + if (isPromise(obj)) return obj; + if (isGeneratorFunction(obj) || isGenerator(obj)) return co.call(this, obj); + if ('function' == typeof obj) return thunkToPromise.call(this, obj); + if (Array.isArray(obj)) return arrayToPromise.call(this, obj); + if (isObject(obj)) return objectToPromise.call(this, obj); + return obj; + } + + /** + * Convert a thunk to a promise. + * + * @param {Function} + * @return {Promise} + * @api private + */ + + function thunkToPromise(fn) { + var ctx = this; + return new Promise(function (resolve, reject) { + fn.call(ctx, function (err, res) { + if (err) return reject(err); + if (arguments.length > 2) res = slice.call(arguments, 1); + resolve(res); + }); + }); + } + + /** + * Convert an array of "yieldables" to a promise. + * Uses `Promise.all()` internally. + * + * @param {Array} obj + * @return {Promise} + * @api private + */ + + function arrayToPromise(obj) { + return Promise.all(obj.map(toPromise, this)); + } + + /** + * Convert an object of "yieldables" to a promise. + * Uses `Promise.all()` internally. + * + * @param {Object} obj + * @return {Promise} + * @api private + */ + + function objectToPromise(obj){ + var results = new obj.constructor(); + var keys = Object.keys(obj); + var promises = []; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var promise = toPromise.call(this, obj[key]); + if (promise && isPromise(promise)) defer(promise, key); + else results[key] = obj[key]; + } + return Promise.all(promises).then(function () { + return results; + }); + + function defer(promise, key) { + // predefine the key in the result + results[key] = undefined; + promises.push(promise.then(function (res) { + results[key] = res; + })); + } + } + + /** + * Check if `obj` is a promise. + * + * @param {Object} obj + * @return {Boolean} + * @api private + */ + + function isPromise(obj) { + return 'function' == typeof obj.then; + } + + /** + * Check if `obj` is a generator. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private + */ + + function isGenerator(obj) { + return 'function' == typeof obj.next && 'function' == typeof obj.throw; + } + + /** + * Check if `obj` is a generator function. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private + */ + function isGeneratorFunction(obj) { + var constructor = obj.constructor; + if (!constructor) return false; + if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true; + return isGenerator(constructor.prototype); + } + + /** + * Check for plain object. + * + * @param {Mixed} val + * @return {Boolean} + * @api private + */ + + function isObject(val) { + return Object == val.constructor; + } + + +/***/ }, +/* 223 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(224); + + function reportException(who, exception) { + var msg = who + " threw an exception: "; + console.error(msg, exception); + } + + function executeSoon(fn) { + setTimeout(fn, 0); + } + + module.exports = { + reportException, + executeSoon, + assert + }; + +/***/ }, +/* 224 */ +/***/ function(module, exports) { + + function assert(condition, message) { + if (!condition) { + throw new Error("Assertion failure: " + message); + } + } + + module.exports = assert; + +/***/ }, +/* 225 */ +/***/ function(module, exports) { + + + /** + * A middleware that allows thunks (functions) to be dispatched. If + * it's a thunk, it is called with an argument that contains + * `dispatch`, `getState`, and any additional args passed in via the + * middleware constructure. This allows the action to create multiple + * actions (most likely asynchronously). + */ + function thunk(makeArgs) { + return (_ref) => { + var dispatch = _ref.dispatch; + var getState = _ref.getState; + + var args = { dispatch, getState }; + + return next => action => { + return typeof action === "function" ? action(makeArgs ? makeArgs(args, getState()) : args) : next(action); + }; + }; + } + exports.thunk = thunk; + +/***/ }, +/* 226 */ +/***/ function(module, exports, __webpack_require__) { + + var tabs = __webpack_require__(227); + + module.exports = { + tabs + }; + +/***/ }, +/* 227 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var constants = __webpack_require__(228); + var Immutable = __webpack_require__(229); + var fromJS = __webpack_require__(230); + + var initialState = fromJS({ + tabs: {}, + selectedTab: null + }); + + function update() { + var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState; + var action = arguments[1]; + + switch (action.type) { + case constants.ADD_TABS: + var tabs = action.value; + if (!tabs) { + return state; + } + + return state.mergeIn(["tabs"], Immutable.Map(tabs.map(tab => { + tab = Object.assign({}, tab, { id: getTabId(tab) }); + return [tab.id, Immutable.Map(tab)]; + }))); + case constants.SELECT_TAB: + var tab = state.getIn(["tabs", action.id]); + return state.setIn(["selectedTab"], tab); + } + + return state; + } + + function getTabId(tab) { + var id = tab.id; + var isFirefox = tab.browser == "firefox"; + + // NOTE: we're getting the last part of the actor because + // we want to ignore the connection id + if (isFirefox) { + id = tab.id.split(".").pop(); + } + + return id; + } + + module.exports = update; + +/***/ }, +/* 228 */ +/***/ function(module, exports) { + + /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + exports.ADD_TABS = "ADD_TABS"; + exports.SELECT_TAB = "SELECT_TAB"; + +/***/ }, +/* 229 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Copyright (c) 2014-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + + (function (global, factory) { + true ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.Immutable = factory()); + }(this, function () { 'use strict';var SLICE$0 = Array.prototype.slice; + + function createClass(ctor, superClass) { + if (superClass) { + ctor.prototype = Object.create(superClass.prototype); + } + ctor.prototype.constructor = ctor; + } + + function Iterable(value) { + return isIterable(value) ? value : Seq(value); + } + + + createClass(KeyedIterable, Iterable); + function KeyedIterable(value) { + return isKeyed(value) ? value : KeyedSeq(value); + } + + + createClass(IndexedIterable, Iterable); + function IndexedIterable(value) { + return isIndexed(value) ? value : IndexedSeq(value); + } + + + createClass(SetIterable, Iterable); + function SetIterable(value) { + return isIterable(value) && !isAssociative(value) ? value : SetSeq(value); + } + + + + function isIterable(maybeIterable) { + return !!(maybeIterable && maybeIterable[IS_ITERABLE_SENTINEL]); + } + + function isKeyed(maybeKeyed) { + return !!(maybeKeyed && maybeKeyed[IS_KEYED_SENTINEL]); + } + + function isIndexed(maybeIndexed) { + return !!(maybeIndexed && maybeIndexed[IS_INDEXED_SENTINEL]); + } + + function isAssociative(maybeAssociative) { + return isKeyed(maybeAssociative) || isIndexed(maybeAssociative); + } + + function isOrdered(maybeOrdered) { + return !!(maybeOrdered && maybeOrdered[IS_ORDERED_SENTINEL]); + } + + Iterable.isIterable = isIterable; + Iterable.isKeyed = isKeyed; + Iterable.isIndexed = isIndexed; + Iterable.isAssociative = isAssociative; + Iterable.isOrdered = isOrdered; + + Iterable.Keyed = KeyedIterable; + Iterable.Indexed = IndexedIterable; + Iterable.Set = SetIterable; + + + var IS_ITERABLE_SENTINEL = '@@__IMMUTABLE_ITERABLE__@@'; + var IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@'; + var IS_INDEXED_SENTINEL = '@@__IMMUTABLE_INDEXED__@@'; + var IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@'; + + // Used for setting prototype methods that IE8 chokes on. + var DELETE = 'delete'; + + // Constants describing the size of trie nodes. + var SHIFT = 5; // Resulted in best performance after ______? + var SIZE = 1 << SHIFT; + var MASK = SIZE - 1; + + // A consistent shared value representing "not set" which equals nothing other + // than itself, and nothing that could be provided externally. + var NOT_SET = {}; + + // Boolean references, Rough equivalent of `bool &`. + var CHANGE_LENGTH = { value: false }; + var DID_ALTER = { value: false }; + + function MakeRef(ref) { + ref.value = false; + return ref; + } + + function SetRef(ref) { + ref && (ref.value = true); + } + + // A function which returns a value representing an "owner" for transient writes + // to tries. The return value will only ever equal itself, and will not equal + // the return of any subsequent call of this function. + function OwnerID() {} + + // http://jsperf.com/copy-array-inline + function arrCopy(arr, offset) { + offset = offset || 0; + var len = Math.max(0, arr.length - offset); + var newArr = new Array(len); + for (var ii = 0; ii < len; ii++) { + newArr[ii] = arr[ii + offset]; + } + return newArr; + } + + function ensureSize(iter) { + if (iter.size === undefined) { + iter.size = iter.__iterate(returnTrue); + } + return iter.size; + } + + function wrapIndex(iter, index) { + // This implements "is array index" which the ECMAString spec defines as: + // + // A String property name P is an array index if and only if + // ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal + // to 2^32−1. + // + // http://www.ecma-international.org/ecma-262/6.0/#sec-array-exotic-objects + if (typeof index !== 'number') { + var uint32Index = index >>> 0; // N >>> 0 is shorthand for ToUint32 + if ('' + uint32Index !== index || uint32Index === 4294967295) { + return NaN; + } + index = uint32Index; + } + return index < 0 ? ensureSize(iter) + index : index; + } + + function returnTrue() { + return true; + } + + function wholeSlice(begin, end, size) { + return (begin === 0 || (size !== undefined && begin <= -size)) && + (end === undefined || (size !== undefined && end >= size)); + } + + function resolveBegin(begin, size) { + return resolveIndex(begin, size, 0); + } + + function resolveEnd(end, size) { + return resolveIndex(end, size, size); + } + + function resolveIndex(index, size, defaultIndex) { + return index === undefined ? + defaultIndex : + index < 0 ? + Math.max(0, size + index) : + size === undefined ? + index : + Math.min(size, index); + } + + /* global Symbol */ + + var ITERATE_KEYS = 0; + var ITERATE_VALUES = 1; + var ITERATE_ENTRIES = 2; + + var REAL_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; + var FAUX_ITERATOR_SYMBOL = '@@iterator'; + + var ITERATOR_SYMBOL = REAL_ITERATOR_SYMBOL || FAUX_ITERATOR_SYMBOL; + + + function Iterator(next) { + this.next = next; + } + + Iterator.prototype.toString = function() { + return '[Iterator]'; + }; + + + Iterator.KEYS = ITERATE_KEYS; + Iterator.VALUES = ITERATE_VALUES; + Iterator.ENTRIES = ITERATE_ENTRIES; + + Iterator.prototype.inspect = + Iterator.prototype.toSource = function () { return this.toString(); } + Iterator.prototype[ITERATOR_SYMBOL] = function () { + return this; + }; + + + function iteratorValue(type, k, v, iteratorResult) { + var value = type === 0 ? k : type === 1 ? v : [k, v]; + iteratorResult ? (iteratorResult.value = value) : (iteratorResult = { + value: value, done: false + }); + return iteratorResult; + } + + function iteratorDone() { + return { value: undefined, done: true }; + } + + function hasIterator(maybeIterable) { + return !!getIteratorFn(maybeIterable); + } + + function isIterator(maybeIterator) { + return maybeIterator && typeof maybeIterator.next === 'function'; + } + + function getIterator(iterable) { + var iteratorFn = getIteratorFn(iterable); + return iteratorFn && iteratorFn.call(iterable); + } + + function getIteratorFn(iterable) { + var iteratorFn = iterable && ( + (REAL_ITERATOR_SYMBOL && iterable[REAL_ITERATOR_SYMBOL]) || + iterable[FAUX_ITERATOR_SYMBOL] + ); + if (typeof iteratorFn === 'function') { + return iteratorFn; + } + } + + function isArrayLike(value) { + return value && typeof value.length === 'number'; + } + + createClass(Seq, Iterable); + function Seq(value) { + return value === null || value === undefined ? emptySequence() : + isIterable(value) ? value.toSeq() : seqFromValue(value); + } + + Seq.of = function(/*...values*/) { + return Seq(arguments); + }; + + Seq.prototype.toSeq = function() { + return this; + }; + + Seq.prototype.toString = function() { + return this.__toString('Seq {', '}'); + }; + + Seq.prototype.cacheResult = function() { + if (!this._cache && this.__iterateUncached) { + this._cache = this.entrySeq().toArray(); + this.size = this._cache.length; + } + return this; + }; + + // abstract __iterateUncached(fn, reverse) + + Seq.prototype.__iterate = function(fn, reverse) { + return seqIterate(this, fn, reverse, true); + }; + + // abstract __iteratorUncached(type, reverse) + + Seq.prototype.__iterator = function(type, reverse) { + return seqIterator(this, type, reverse, true); + }; + + + + createClass(KeyedSeq, Seq); + function KeyedSeq(value) { + return value === null || value === undefined ? + emptySequence().toKeyedSeq() : + isIterable(value) ? + (isKeyed(value) ? value.toSeq() : value.fromEntrySeq()) : + keyedSeqFromValue(value); + } + + KeyedSeq.prototype.toKeyedSeq = function() { + return this; + }; + + + + createClass(IndexedSeq, Seq); + function IndexedSeq(value) { + return value === null || value === undefined ? emptySequence() : + !isIterable(value) ? indexedSeqFromValue(value) : + isKeyed(value) ? value.entrySeq() : value.toIndexedSeq(); + } + + IndexedSeq.of = function(/*...values*/) { + return IndexedSeq(arguments); + }; + + IndexedSeq.prototype.toIndexedSeq = function() { + return this; + }; + + IndexedSeq.prototype.toString = function() { + return this.__toString('Seq [', ']'); + }; + + IndexedSeq.prototype.__iterate = function(fn, reverse) { + return seqIterate(this, fn, reverse, false); + }; + + IndexedSeq.prototype.__iterator = function(type, reverse) { + return seqIterator(this, type, reverse, false); + }; + + + + createClass(SetSeq, Seq); + function SetSeq(value) { + return ( + value === null || value === undefined ? emptySequence() : + !isIterable(value) ? indexedSeqFromValue(value) : + isKeyed(value) ? value.entrySeq() : value + ).toSetSeq(); + } + + SetSeq.of = function(/*...values*/) { + return SetSeq(arguments); + }; + + SetSeq.prototype.toSetSeq = function() { + return this; + }; + + + + Seq.isSeq = isSeq; + Seq.Keyed = KeyedSeq; + Seq.Set = SetSeq; + Seq.Indexed = IndexedSeq; + + var IS_SEQ_SENTINEL = '@@__IMMUTABLE_SEQ__@@'; + + Seq.prototype[IS_SEQ_SENTINEL] = true; + + + + createClass(ArraySeq, IndexedSeq); + function ArraySeq(array) { + this._array = array; + this.size = array.length; + } + + ArraySeq.prototype.get = function(index, notSetValue) { + return this.has(index) ? this._array[wrapIndex(this, index)] : notSetValue; + }; + + ArraySeq.prototype.__iterate = function(fn, reverse) { + var array = this._array; + var maxIndex = array.length - 1; + for (var ii = 0; ii <= maxIndex; ii++) { + if (fn(array[reverse ? maxIndex - ii : ii], ii, this) === false) { + return ii + 1; + } + } + return ii; + }; + + ArraySeq.prototype.__iterator = function(type, reverse) { + var array = this._array; + var maxIndex = array.length - 1; + var ii = 0; + return new Iterator(function() + {return ii > maxIndex ? + iteratorDone() : + iteratorValue(type, ii, array[reverse ? maxIndex - ii++ : ii++])} + ); + }; + + + + createClass(ObjectSeq, KeyedSeq); + function ObjectSeq(object) { + var keys = Object.keys(object); + this._object = object; + this._keys = keys; + this.size = keys.length; + } + + ObjectSeq.prototype.get = function(key, notSetValue) { + if (notSetValue !== undefined && !this.has(key)) { + return notSetValue; + } + return this._object[key]; + }; + + ObjectSeq.prototype.has = function(key) { + return this._object.hasOwnProperty(key); + }; + + ObjectSeq.prototype.__iterate = function(fn, reverse) { + var object = this._object; + var keys = this._keys; + var maxIndex = keys.length - 1; + for (var ii = 0; ii <= maxIndex; ii++) { + var key = keys[reverse ? maxIndex - ii : ii]; + if (fn(object[key], key, this) === false) { + return ii + 1; + } + } + return ii; + }; + + ObjectSeq.prototype.__iterator = function(type, reverse) { + var object = this._object; + var keys = this._keys; + var maxIndex = keys.length - 1; + var ii = 0; + return new Iterator(function() { + var key = keys[reverse ? maxIndex - ii : ii]; + return ii++ > maxIndex ? + iteratorDone() : + iteratorValue(type, key, object[key]); + }); + }; + + ObjectSeq.prototype[IS_ORDERED_SENTINEL] = true; + + + createClass(IterableSeq, IndexedSeq); + function IterableSeq(iterable) { + this._iterable = iterable; + this.size = iterable.length || iterable.size; + } + + IterableSeq.prototype.__iterateUncached = function(fn, reverse) { + if (reverse) { + return this.cacheResult().__iterate(fn, reverse); + } + var iterable = this._iterable; + var iterator = getIterator(iterable); + var iterations = 0; + if (isIterator(iterator)) { + var step; + while (!(step = iterator.next()).done) { + if (fn(step.value, iterations++, this) === false) { + break; + } + } + } + return iterations; + }; + + IterableSeq.prototype.__iteratorUncached = function(type, reverse) { + if (reverse) { + return this.cacheResult().__iterator(type, reverse); + } + var iterable = this._iterable; + var iterator = getIterator(iterable); + if (!isIterator(iterator)) { + return new Iterator(iteratorDone); + } + var iterations = 0; + return new Iterator(function() { + var step = iterator.next(); + return step.done ? step : iteratorValue(type, iterations++, step.value); + }); + }; + + + + createClass(IteratorSeq, IndexedSeq); + function IteratorSeq(iterator) { + this._iterator = iterator; + this._iteratorCache = []; + } + + IteratorSeq.prototype.__iterateUncached = function(fn, reverse) { + if (reverse) { + return this.cacheResult().__iterate(fn, reverse); + } + var iterator = this._iterator; + var cache = this._iteratorCache; + var iterations = 0; + while (iterations < cache.length) { + if (fn(cache[iterations], iterations++, this) === false) { + return iterations; + } + } + var step; + while (!(step = iterator.next()).done) { + var val = step.value; + cache[iterations] = val; + if (fn(val, iterations++, this) === false) { + break; + } + } + return iterations; + }; + + IteratorSeq.prototype.__iteratorUncached = function(type, reverse) { + if (reverse) { + return this.cacheResult().__iterator(type, reverse); + } + var iterator = this._iterator; + var cache = this._iteratorCache; + var iterations = 0; + return new Iterator(function() { + if (iterations >= cache.length) { + var step = iterator.next(); + if (step.done) { + return step; + } + cache[iterations] = step.value; + } + return iteratorValue(type, iterations, cache[iterations++]); + }); + }; + + + + + // # pragma Helper functions + + function isSeq(maybeSeq) { + return !!(maybeSeq && maybeSeq[IS_SEQ_SENTINEL]); + } + + var EMPTY_SEQ; + + function emptySequence() { + return EMPTY_SEQ || (EMPTY_SEQ = new ArraySeq([])); + } + + function keyedSeqFromValue(value) { + var seq = + Array.isArray(value) ? new ArraySeq(value).fromEntrySeq() : + isIterator(value) ? new IteratorSeq(value).fromEntrySeq() : + hasIterator(value) ? new IterableSeq(value).fromEntrySeq() : + typeof value === 'object' ? new ObjectSeq(value) : + undefined; + if (!seq) { + throw new TypeError( + 'Expected Array or iterable object of [k, v] entries, '+ + 'or keyed object: ' + value + ); + } + return seq; + } + + function indexedSeqFromValue(value) { + var seq = maybeIndexedSeqFromValue(value); + if (!seq) { + throw new TypeError( + 'Expected Array or iterable object of values: ' + value + ); + } + return seq; + } + + function seqFromValue(value) { + var seq = maybeIndexedSeqFromValue(value) || + (typeof value === 'object' && new ObjectSeq(value)); + if (!seq) { + throw new TypeError( + 'Expected Array or iterable object of values, or keyed object: ' + value + ); + } + return seq; + } + + function maybeIndexedSeqFromValue(value) { + return ( + isArrayLike(value) ? new ArraySeq(value) : + isIterator(value) ? new IteratorSeq(value) : + hasIterator(value) ? new IterableSeq(value) : + undefined + ); + } + + function seqIterate(seq, fn, reverse, useKeys) { + var cache = seq._cache; + if (cache) { + var maxIndex = cache.length - 1; + for (var ii = 0; ii <= maxIndex; ii++) { + var entry = cache[reverse ? maxIndex - ii : ii]; + if (fn(entry[1], useKeys ? entry[0] : ii, seq) === false) { + return ii + 1; + } + } + return ii; + } + return seq.__iterateUncached(fn, reverse); + } + + function seqIterator(seq, type, reverse, useKeys) { + var cache = seq._cache; + if (cache) { + var maxIndex = cache.length - 1; + var ii = 0; + return new Iterator(function() { + var entry = cache[reverse ? maxIndex - ii : ii]; + return ii++ > maxIndex ? + iteratorDone() : + iteratorValue(type, useKeys ? entry[0] : ii - 1, entry[1]); + }); + } + return seq.__iteratorUncached(type, reverse); + } + + function fromJS(json, converter) { + return converter ? + fromJSWith(converter, json, '', {'': json}) : + fromJSDefault(json); + } + + function fromJSWith(converter, json, key, parentJSON) { + if (Array.isArray(json)) { + return converter.call(parentJSON, key, IndexedSeq(json).map(function(v, k) {return fromJSWith(converter, v, k, json)})); + } + if (isPlainObj(json)) { + return converter.call(parentJSON, key, KeyedSeq(json).map(function(v, k) {return fromJSWith(converter, v, k, json)})); + } + return json; + } + + function fromJSDefault(json) { + if (Array.isArray(json)) { + return IndexedSeq(json).map(fromJSDefault).toList(); + } + if (isPlainObj(json)) { + return KeyedSeq(json).map(fromJSDefault).toMap(); + } + return json; + } + + function isPlainObj(value) { + return value && (value.constructor === Object || value.constructor === undefined); + } + + /** + * An extension of the "same-value" algorithm as [described for use by ES6 Map + * and Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality) + * + * NaN is considered the same as NaN, however -0 and 0 are considered the same + * value, which is different from the algorithm described by + * [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). + * + * This is extended further to allow Objects to describe the values they + * represent, by way of `valueOf` or `equals` (and `hashCode`). + * + * Note: because of this extension, the key equality of Immutable.Map and the + * value equality of Immutable.Set will differ from ES6 Map and Set. + * + * ### Defining custom values + * + * The easiest way to describe the value an object represents is by implementing + * `valueOf`. For example, `Date` represents a value by returning a unix + * timestamp for `valueOf`: + * + * var date1 = new Date(1234567890000); // Fri Feb 13 2009 ... + * var date2 = new Date(1234567890000); + * date1.valueOf(); // 1234567890000 + * assert( date1 !== date2 ); + * assert( Immutable.is( date1, date2 ) ); + * + * Note: overriding `valueOf` may have other implications if you use this object + * where JavaScript expects a primitive, such as implicit string coercion. + * + * For more complex types, especially collections, implementing `valueOf` may + * not be performant. An alternative is to implement `equals` and `hashCode`. + * + * `equals` takes another object, presumably of similar type, and returns true + * if the it is equal. Equality is symmetrical, so the same result should be + * returned if this and the argument are flipped. + * + * assert( a.equals(b) === b.equals(a) ); + * + * `hashCode` returns a 32bit integer number representing the object which will + * be used to determine how to store the value object in a Map or Set. You must + * provide both or neither methods, one must not exist without the other. + * + * Also, an important relationship between these methods must be upheld: if two + * values are equal, they *must* return the same hashCode. If the values are not + * equal, they might have the same hashCode; this is called a hash collision, + * and while undesirable for performance reasons, it is acceptable. + * + * if (a.equals(b)) { + * assert( a.hashCode() === b.hashCode() ); + * } + * + * All Immutable collections implement `equals` and `hashCode`. + * + */ + function is(valueA, valueB) { + if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) { + return true; + } + if (!valueA || !valueB) { + return false; + } + if (typeof valueA.valueOf === 'function' && + typeof valueB.valueOf === 'function') { + valueA = valueA.valueOf(); + valueB = valueB.valueOf(); + if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) { + return true; + } + if (!valueA || !valueB) { + return false; + } + } + if (typeof valueA.equals === 'function' && + typeof valueB.equals === 'function' && + valueA.equals(valueB)) { + return true; + } + return false; + } + + function deepEqual(a, b) { + if (a === b) { + return true; + } + + if ( + !isIterable(b) || + a.size !== undefined && b.size !== undefined && a.size !== b.size || + a.__hash !== undefined && b.__hash !== undefined && a.__hash !== b.__hash || + isKeyed(a) !== isKeyed(b) || + isIndexed(a) !== isIndexed(b) || + isOrdered(a) !== isOrdered(b) + ) { + return false; + } + + if (a.size === 0 && b.size === 0) { + return true; + } + + var notAssociative = !isAssociative(a); + + if (isOrdered(a)) { + var entries = a.entries(); + return b.every(function(v, k) { + var entry = entries.next().value; + return entry && is(entry[1], v) && (notAssociative || is(entry[0], k)); + }) && entries.next().done; + } + + var flipped = false; + + if (a.size === undefined) { + if (b.size === undefined) { + if (typeof a.cacheResult === 'function') { + a.cacheResult(); + } + } else { + flipped = true; + var _ = a; + a = b; + b = _; + } + } + + var allEqual = true; + var bSize = b.__iterate(function(v, k) { + if (notAssociative ? !a.has(v) : + flipped ? !is(v, a.get(k, NOT_SET)) : !is(a.get(k, NOT_SET), v)) { + allEqual = false; + return false; + } + }); + + return allEqual && a.size === bSize; + } + + createClass(Repeat, IndexedSeq); + + function Repeat(value, times) { + if (!(this instanceof Repeat)) { + return new Repeat(value, times); + } + this._value = value; + this.size = times === undefined ? Infinity : Math.max(0, times); + if (this.size === 0) { + if (EMPTY_REPEAT) { + return EMPTY_REPEAT; + } + EMPTY_REPEAT = this; + } + } + + Repeat.prototype.toString = function() { + if (this.size === 0) { + return 'Repeat []'; + } + return 'Repeat [ ' + this._value + ' ' + this.size + ' times ]'; + }; + + Repeat.prototype.get = function(index, notSetValue) { + return this.has(index) ? this._value : notSetValue; + }; + + Repeat.prototype.includes = function(searchValue) { + return is(this._value, searchValue); + }; + + Repeat.prototype.slice = function(begin, end) { + var size = this.size; + return wholeSlice(begin, end, size) ? this : + new Repeat(this._value, resolveEnd(end, size) - resolveBegin(begin, size)); + }; + + Repeat.prototype.reverse = function() { + return this; + }; + + Repeat.prototype.indexOf = function(searchValue) { + if (is(this._value, searchValue)) { + return 0; + } + return -1; + }; + + Repeat.prototype.lastIndexOf = function(searchValue) { + if (is(this._value, searchValue)) { + return this.size; + } + return -1; + }; + + Repeat.prototype.__iterate = function(fn, reverse) { + for (var ii = 0; ii < this.size; ii++) { + if (fn(this._value, ii, this) === false) { + return ii + 1; + } + } + return ii; + }; + + Repeat.prototype.__iterator = function(type, reverse) {var this$0 = this; + var ii = 0; + return new Iterator(function() + {return ii < this$0.size ? iteratorValue(type, ii++, this$0._value) : iteratorDone()} + ); + }; + + Repeat.prototype.equals = function(other) { + return other instanceof Repeat ? + is(this._value, other._value) : + deepEqual(other); + }; + + + var EMPTY_REPEAT; + + function invariant(condition, error) { + if (!condition) throw new Error(error); + } + + createClass(Range, IndexedSeq); + + function Range(start, end, step) { + if (!(this instanceof Range)) { + return new Range(start, end, step); + } + invariant(step !== 0, 'Cannot step a Range by 0'); + start = start || 0; + if (end === undefined) { + end = Infinity; + } + step = step === undefined ? 1 : Math.abs(step); + if (end < start) { + step = -step; + } + this._start = start; + this._end = end; + this._step = step; + this.size = Math.max(0, Math.ceil((end - start) / step - 1) + 1); + if (this.size === 0) { + if (EMPTY_RANGE) { + return EMPTY_RANGE; + } + EMPTY_RANGE = this; + } + } + + Range.prototype.toString = function() { + if (this.size === 0) { + return 'Range []'; + } + return 'Range [ ' + + this._start + '...' + this._end + + (this._step !== 1 ? ' by ' + this._step : '') + + ' ]'; + }; + + Range.prototype.get = function(index, notSetValue) { + return this.has(index) ? + this._start + wrapIndex(this, index) * this._step : + notSetValue; + }; + + Range.prototype.includes = function(searchValue) { + var possibleIndex = (searchValue - this._start) / this._step; + return possibleIndex >= 0 && + possibleIndex < this.size && + possibleIndex === Math.floor(possibleIndex); + }; + + Range.prototype.slice = function(begin, end) { + if (wholeSlice(begin, end, this.size)) { + return this; + } + begin = resolveBegin(begin, this.size); + end = resolveEnd(end, this.size); + if (end <= begin) { + return new Range(0, 0); + } + return new Range(this.get(begin, this._end), this.get(end, this._end), this._step); + }; + + Range.prototype.indexOf = function(searchValue) { + var offsetValue = searchValue - this._start; + if (offsetValue % this._step === 0) { + var index = offsetValue / this._step; + if (index >= 0 && index < this.size) { + return index + } + } + return -1; + }; + + Range.prototype.lastIndexOf = function(searchValue) { + return this.indexOf(searchValue); + }; + + Range.prototype.__iterate = function(fn, reverse) { + var maxIndex = this.size - 1; + var step = this._step; + var value = reverse ? this._start + maxIndex * step : this._start; + for (var ii = 0; ii <= maxIndex; ii++) { + if (fn(value, ii, this) === false) { + return ii + 1; + } + value += reverse ? -step : step; + } + return ii; + }; + + Range.prototype.__iterator = function(type, reverse) { + var maxIndex = this.size - 1; + var step = this._step; + var value = reverse ? this._start + maxIndex * step : this._start; + var ii = 0; + return new Iterator(function() { + var v = value; + value += reverse ? -step : step; + return ii > maxIndex ? iteratorDone() : iteratorValue(type, ii++, v); + }); + }; + + Range.prototype.equals = function(other) { + return other instanceof Range ? + this._start === other._start && + this._end === other._end && + this._step === other._step : + deepEqual(this, other); + }; + + + var EMPTY_RANGE; + + createClass(Collection, Iterable); + function Collection() { + throw TypeError('Abstract'); + } + + + createClass(KeyedCollection, Collection);function KeyedCollection() {} + + createClass(IndexedCollection, Collection);function IndexedCollection() {} + + createClass(SetCollection, Collection);function SetCollection() {} + + + Collection.Keyed = KeyedCollection; + Collection.Indexed = IndexedCollection; + Collection.Set = SetCollection; + + var imul = + typeof Math.imul === 'function' && Math.imul(0xffffffff, 2) === -2 ? + Math.imul : + function imul(a, b) { + a = a | 0; // int + b = b | 0; // int + var c = a & 0xffff; + var d = b & 0xffff; + // Shift by 0 fixes the sign on the high part. + return (c * d) + ((((a >>> 16) * d + c * (b >>> 16)) << 16) >>> 0) | 0; // int + }; + + // v8 has an optimization for storing 31-bit signed numbers. + // Values which have either 00 or 11 as the high order bits qualify. + // This function drops the highest order bit in a signed number, maintaining + // the sign bit. + function smi(i32) { + return ((i32 >>> 1) & 0x40000000) | (i32 & 0xBFFFFFFF); + } + + function hash(o) { + if (o === false || o === null || o === undefined) { + return 0; + } + if (typeof o.valueOf === 'function') { + o = o.valueOf(); + if (o === false || o === null || o === undefined) { + return 0; + } + } + if (o === true) { + return 1; + } + var type = typeof o; + if (type === 'number') { + if (o !== o || o === Infinity) { + return 0; + } + var h = o | 0; + if (h !== o) { + h ^= o * 0xFFFFFFFF; + } + while (o > 0xFFFFFFFF) { + o /= 0xFFFFFFFF; + h ^= o; + } + return smi(h); + } + if (type === 'string') { + return o.length > STRING_HASH_CACHE_MIN_STRLEN ? cachedHashString(o) : hashString(o); + } + if (typeof o.hashCode === 'function') { + return o.hashCode(); + } + if (type === 'object') { + return hashJSObj(o); + } + if (typeof o.toString === 'function') { + return hashString(o.toString()); + } + throw new Error('Value type ' + type + ' cannot be hashed.'); + } + + function cachedHashString(string) { + var hash = stringHashCache[string]; + if (hash === undefined) { + hash = hashString(string); + if (STRING_HASH_CACHE_SIZE === STRING_HASH_CACHE_MAX_SIZE) { + STRING_HASH_CACHE_SIZE = 0; + stringHashCache = {}; + } + STRING_HASH_CACHE_SIZE++; + stringHashCache[string] = hash; + } + return hash; + } + + // http://jsperf.com/hashing-strings + function hashString(string) { + // This is the hash from JVM + // The hash code for a string is computed as + // s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1], + // where s[i] is the ith character of the string and n is the length of + // the string. We "mod" the result to make it between 0 (inclusive) and 2^31 + // (exclusive) by dropping high bits. + var hash = 0; + for (var ii = 0; ii < string.length; ii++) { + hash = 31 * hash + string.charCodeAt(ii) | 0; + } + return smi(hash); + } + + function hashJSObj(obj) { + var hash; + if (usingWeakMap) { + hash = weakMap.get(obj); + if (hash !== undefined) { + return hash; + } + } + + hash = obj[UID_HASH_KEY]; + if (hash !== undefined) { + return hash; + } + + if (!canDefineProperty) { + hash = obj.propertyIsEnumerable && obj.propertyIsEnumerable[UID_HASH_KEY]; + if (hash !== undefined) { + return hash; + } + + hash = getIENodeHash(obj); + if (hash !== undefined) { + return hash; + } + } + + hash = ++objHashUID; + if (objHashUID & 0x40000000) { + objHashUID = 0; + } + + if (usingWeakMap) { + weakMap.set(obj, hash); + } else if (isExtensible !== undefined && isExtensible(obj) === false) { + throw new Error('Non-extensible objects are not allowed as keys.'); + } else if (canDefineProperty) { + Object.defineProperty(obj, UID_HASH_KEY, { + 'enumerable': false, + 'configurable': false, + 'writable': false, + 'value': hash + }); + } else if (obj.propertyIsEnumerable !== undefined && + obj.propertyIsEnumerable === obj.constructor.prototype.propertyIsEnumerable) { + // Since we can't define a non-enumerable property on the object + // we'll hijack one of the less-used non-enumerable properties to + // save our hash on it. Since this is a function it will not show up in + // `JSON.stringify` which is what we want. + obj.propertyIsEnumerable = function() { + return this.constructor.prototype.propertyIsEnumerable.apply(this, arguments); + }; + obj.propertyIsEnumerable[UID_HASH_KEY] = hash; + } else if (obj.nodeType !== undefined) { + // At this point we couldn't get the IE `uniqueID` to use as a hash + // and we couldn't use a non-enumerable property to exploit the + // dontEnum bug so we simply add the `UID_HASH_KEY` on the node + // itself. + obj[UID_HASH_KEY] = hash; + } else { + throw new Error('Unable to set a non-enumerable property on object.'); + } + + return hash; + } + + // Get references to ES5 object methods. + var isExtensible = Object.isExtensible; + + // True if Object.defineProperty works as expected. IE8 fails this test. + var canDefineProperty = (function() { + try { + Object.defineProperty({}, '@', {}); + return true; + } catch (e) { + return false; + } + }()); + + // IE has a `uniqueID` property on DOM nodes. We can construct the hash from it + // and avoid memory leaks from the IE cloneNode bug. + function getIENodeHash(node) { + if (node && node.nodeType > 0) { + switch (node.nodeType) { + case 1: // Element + return node.uniqueID; + case 9: // Document + return node.documentElement && node.documentElement.uniqueID; + } + } + } + + // If possible, use a WeakMap. + var usingWeakMap = typeof WeakMap === 'function'; + var weakMap; + if (usingWeakMap) { + weakMap = new WeakMap(); + } + + var objHashUID = 0; + + var UID_HASH_KEY = '__immutablehash__'; + if (typeof Symbol === 'function') { + UID_HASH_KEY = Symbol(UID_HASH_KEY); + } + + var STRING_HASH_CACHE_MIN_STRLEN = 16; + var STRING_HASH_CACHE_MAX_SIZE = 255; + var STRING_HASH_CACHE_SIZE = 0; + var stringHashCache = {}; + + function assertNotInfinite(size) { + invariant( + size !== Infinity, + 'Cannot perform this action with an infinite size.' + ); + } + + createClass(Map, KeyedCollection); + + // @pragma Construction + + function Map(value) { + return value === null || value === undefined ? emptyMap() : + isMap(value) && !isOrdered(value) ? value : + emptyMap().withMutations(function(map ) { + var iter = KeyedIterable(value); + assertNotInfinite(iter.size); + iter.forEach(function(v, k) {return map.set(k, v)}); + }); + } + + Map.of = function() {var keyValues = SLICE$0.call(arguments, 0); + return emptyMap().withMutations(function(map ) { + for (var i = 0; i < keyValues.length; i += 2) { + if (i + 1 >= keyValues.length) { + throw new Error('Missing value for key: ' + keyValues[i]); + } + map.set(keyValues[i], keyValues[i + 1]); + } + }); + }; + + Map.prototype.toString = function() { + return this.__toString('Map {', '}'); + }; + + // @pragma Access + + Map.prototype.get = function(k, notSetValue) { + return this._root ? + this._root.get(0, undefined, k, notSetValue) : + notSetValue; + }; + + // @pragma Modification + + Map.prototype.set = function(k, v) { + return updateMap(this, k, v); + }; + + Map.prototype.setIn = function(keyPath, v) { + return this.updateIn(keyPath, NOT_SET, function() {return v}); + }; + + Map.prototype.remove = function(k) { + return updateMap(this, k, NOT_SET); + }; + + Map.prototype.deleteIn = function(keyPath) { + return this.updateIn(keyPath, function() {return NOT_SET}); + }; + + Map.prototype.update = function(k, notSetValue, updater) { + return arguments.length === 1 ? + k(this) : + this.updateIn([k], notSetValue, updater); + }; + + Map.prototype.updateIn = function(keyPath, notSetValue, updater) { + if (!updater) { + updater = notSetValue; + notSetValue = undefined; + } + var updatedValue = updateInDeepMap( + this, + forceIterator(keyPath), + notSetValue, + updater + ); + return updatedValue === NOT_SET ? undefined : updatedValue; + }; + + Map.prototype.clear = function() { + if (this.size === 0) { + return this; + } + if (this.__ownerID) { + this.size = 0; + this._root = null; + this.__hash = undefined; + this.__altered = true; + return this; + } + return emptyMap(); + }; + + // @pragma Composition + + Map.prototype.merge = function(/*...iters*/) { + return mergeIntoMapWith(this, undefined, arguments); + }; + + Map.prototype.mergeWith = function(merger) {var iters = SLICE$0.call(arguments, 1); + return mergeIntoMapWith(this, merger, iters); + }; + + Map.prototype.mergeIn = function(keyPath) {var iters = SLICE$0.call(arguments, 1); + return this.updateIn( + keyPath, + emptyMap(), + function(m ) {return typeof m.merge === 'function' ? + m.merge.apply(m, iters) : + iters[iters.length - 1]} + ); + }; + + Map.prototype.mergeDeep = function(/*...iters*/) { + return mergeIntoMapWith(this, deepMerger, arguments); + }; + + Map.prototype.mergeDeepWith = function(merger) {var iters = SLICE$0.call(arguments, 1); + return mergeIntoMapWith(this, deepMergerWith(merger), iters); + }; + + Map.prototype.mergeDeepIn = function(keyPath) {var iters = SLICE$0.call(arguments, 1); + return this.updateIn( + keyPath, + emptyMap(), + function(m ) {return typeof m.mergeDeep === 'function' ? + m.mergeDeep.apply(m, iters) : + iters[iters.length - 1]} + ); + }; + + Map.prototype.sort = function(comparator) { + // Late binding + return OrderedMap(sortFactory(this, comparator)); + }; + + Map.prototype.sortBy = function(mapper, comparator) { + // Late binding + return OrderedMap(sortFactory(this, comparator, mapper)); + }; + + // @pragma Mutability + + Map.prototype.withMutations = function(fn) { + var mutable = this.asMutable(); + fn(mutable); + return mutable.wasAltered() ? mutable.__ensureOwner(this.__ownerID) : this; + }; + + Map.prototype.asMutable = function() { + return this.__ownerID ? this : this.__ensureOwner(new OwnerID()); + }; + + Map.prototype.asImmutable = function() { + return this.__ensureOwner(); + }; + + Map.prototype.wasAltered = function() { + return this.__altered; + }; + + Map.prototype.__iterator = function(type, reverse) { + return new MapIterator(this, type, reverse); + }; + + Map.prototype.__iterate = function(fn, reverse) {var this$0 = this; + var iterations = 0; + this._root && this._root.iterate(function(entry ) { + iterations++; + return fn(entry[1], entry[0], this$0); + }, reverse); + return iterations; + }; + + Map.prototype.__ensureOwner = function(ownerID) { + if (ownerID === this.__ownerID) { + return this; + } + if (!ownerID) { + this.__ownerID = ownerID; + this.__altered = false; + return this; + } + return makeMap(this.size, this._root, ownerID, this.__hash); + }; + + + function isMap(maybeMap) { + return !!(maybeMap && maybeMap[IS_MAP_SENTINEL]); + } + + Map.isMap = isMap; + + var IS_MAP_SENTINEL = '@@__IMMUTABLE_MAP__@@'; + + var MapPrototype = Map.prototype; + MapPrototype[IS_MAP_SENTINEL] = true; + MapPrototype[DELETE] = MapPrototype.remove; + MapPrototype.removeIn = MapPrototype.deleteIn; + + + // #pragma Trie Nodes + + + + function ArrayMapNode(ownerID, entries) { + this.ownerID = ownerID; + this.entries = entries; + } + + ArrayMapNode.prototype.get = function(shift, keyHash, key, notSetValue) { + var entries = this.entries; + for (var ii = 0, len = entries.length; ii < len; ii++) { + if (is(key, entries[ii][0])) { + return entries[ii][1]; + } + } + return notSetValue; + }; + + ArrayMapNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) { + var removed = value === NOT_SET; + + var entries = this.entries; + var idx = 0; + for (var len = entries.length; idx < len; idx++) { + if (is(key, entries[idx][0])) { + break; + } + } + var exists = idx < len; + + if (exists ? entries[idx][1] === value : removed) { + return this; + } + + SetRef(didAlter); + (removed || !exists) && SetRef(didChangeSize); + + if (removed && entries.length === 1) { + return; // undefined + } + + if (!exists && !removed && entries.length >= MAX_ARRAY_MAP_SIZE) { + return createNodes(ownerID, entries, key, value); + } + + var isEditable = ownerID && ownerID === this.ownerID; + var newEntries = isEditable ? entries : arrCopy(entries); + + if (exists) { + if (removed) { + idx === len - 1 ? newEntries.pop() : (newEntries[idx] = newEntries.pop()); + } else { + newEntries[idx] = [key, value]; + } + } else { + newEntries.push([key, value]); + } + + if (isEditable) { + this.entries = newEntries; + return this; + } + + return new ArrayMapNode(ownerID, newEntries); + }; + + + + + function BitmapIndexedNode(ownerID, bitmap, nodes) { + this.ownerID = ownerID; + this.bitmap = bitmap; + this.nodes = nodes; + } + + BitmapIndexedNode.prototype.get = function(shift, keyHash, key, notSetValue) { + if (keyHash === undefined) { + keyHash = hash(key); + } + var bit = (1 << ((shift === 0 ? keyHash : keyHash >>> shift) & MASK)); + var bitmap = this.bitmap; + return (bitmap & bit) === 0 ? notSetValue : + this.nodes[popCount(bitmap & (bit - 1))].get(shift + SHIFT, keyHash, key, notSetValue); + }; + + BitmapIndexedNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) { + if (keyHash === undefined) { + keyHash = hash(key); + } + var keyHashFrag = (shift === 0 ? keyHash : keyHash >>> shift) & MASK; + var bit = 1 << keyHashFrag; + var bitmap = this.bitmap; + var exists = (bitmap & bit) !== 0; + + if (!exists && value === NOT_SET) { + return this; + } + + var idx = popCount(bitmap & (bit - 1)); + var nodes = this.nodes; + var node = exists ? nodes[idx] : undefined; + var newNode = updateNode(node, ownerID, shift + SHIFT, keyHash, key, value, didChangeSize, didAlter); + + if (newNode === node) { + return this; + } + + if (!exists && newNode && nodes.length >= MAX_BITMAP_INDEXED_SIZE) { + return expandNodes(ownerID, nodes, bitmap, keyHashFrag, newNode); + } + + if (exists && !newNode && nodes.length === 2 && isLeafNode(nodes[idx ^ 1])) { + return nodes[idx ^ 1]; + } + + if (exists && newNode && nodes.length === 1 && isLeafNode(newNode)) { + return newNode; + } + + var isEditable = ownerID && ownerID === this.ownerID; + var newBitmap = exists ? newNode ? bitmap : bitmap ^ bit : bitmap | bit; + var newNodes = exists ? newNode ? + setIn(nodes, idx, newNode, isEditable) : + spliceOut(nodes, idx, isEditable) : + spliceIn(nodes, idx, newNode, isEditable); + + if (isEditable) { + this.bitmap = newBitmap; + this.nodes = newNodes; + return this; + } + + return new BitmapIndexedNode(ownerID, newBitmap, newNodes); + }; + + + + + function HashArrayMapNode(ownerID, count, nodes) { + this.ownerID = ownerID; + this.count = count; + this.nodes = nodes; + } + + HashArrayMapNode.prototype.get = function(shift, keyHash, key, notSetValue) { + if (keyHash === undefined) { + keyHash = hash(key); + } + var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK; + var node = this.nodes[idx]; + return node ? node.get(shift + SHIFT, keyHash, key, notSetValue) : notSetValue; + }; + + HashArrayMapNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) { + if (keyHash === undefined) { + keyHash = hash(key); + } + var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK; + var removed = value === NOT_SET; + var nodes = this.nodes; + var node = nodes[idx]; + + if (removed && !node) { + return this; + } + + var newNode = updateNode(node, ownerID, shift + SHIFT, keyHash, key, value, didChangeSize, didAlter); + if (newNode === node) { + return this; + } + + var newCount = this.count; + if (!node) { + newCount++; + } else if (!newNode) { + newCount--; + if (newCount < MIN_HASH_ARRAY_MAP_SIZE) { + return packNodes(ownerID, nodes, newCount, idx); + } + } + + var isEditable = ownerID && ownerID === this.ownerID; + var newNodes = setIn(nodes, idx, newNode, isEditable); + + if (isEditable) { + this.count = newCount; + this.nodes = newNodes; + return this; + } + + return new HashArrayMapNode(ownerID, newCount, newNodes); + }; + + + + + function HashCollisionNode(ownerID, keyHash, entries) { + this.ownerID = ownerID; + this.keyHash = keyHash; + this.entries = entries; + } + + HashCollisionNode.prototype.get = function(shift, keyHash, key, notSetValue) { + var entries = this.entries; + for (var ii = 0, len = entries.length; ii < len; ii++) { + if (is(key, entries[ii][0])) { + return entries[ii][1]; + } + } + return notSetValue; + }; + + HashCollisionNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) { + if (keyHash === undefined) { + keyHash = hash(key); + } + + var removed = value === NOT_SET; + + if (keyHash !== this.keyHash) { + if (removed) { + return this; + } + SetRef(didAlter); + SetRef(didChangeSize); + return mergeIntoNode(this, ownerID, shift, keyHash, [key, value]); + } + + var entries = this.entries; + var idx = 0; + for (var len = entries.length; idx < len; idx++) { + if (is(key, entries[idx][0])) { + break; + } + } + var exists = idx < len; + + if (exists ? entries[idx][1] === value : removed) { + return this; + } + + SetRef(didAlter); + (removed || !exists) && SetRef(didChangeSize); + + if (removed && len === 2) { + return new ValueNode(ownerID, this.keyHash, entries[idx ^ 1]); + } + + var isEditable = ownerID && ownerID === this.ownerID; + var newEntries = isEditable ? entries : arrCopy(entries); + + if (exists) { + if (removed) { + idx === len - 1 ? newEntries.pop() : (newEntries[idx] = newEntries.pop()); + } else { + newEntries[idx] = [key, value]; + } + } else { + newEntries.push([key, value]); + } + + if (isEditable) { + this.entries = newEntries; + return this; + } + + return new HashCollisionNode(ownerID, this.keyHash, newEntries); + }; + + + + + function ValueNode(ownerID, keyHash, entry) { + this.ownerID = ownerID; + this.keyHash = keyHash; + this.entry = entry; + } + + ValueNode.prototype.get = function(shift, keyHash, key, notSetValue) { + return is(key, this.entry[0]) ? this.entry[1] : notSetValue; + }; + + ValueNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) { + var removed = value === NOT_SET; + var keyMatch = is(key, this.entry[0]); + if (keyMatch ? value === this.entry[1] : removed) { + return this; + } + + SetRef(didAlter); + + if (removed) { + SetRef(didChangeSize); + return; // undefined + } + + if (keyMatch) { + if (ownerID && ownerID === this.ownerID) { + this.entry[1] = value; + return this; + } + return new ValueNode(ownerID, this.keyHash, [key, value]); + } + + SetRef(didChangeSize); + return mergeIntoNode(this, ownerID, shift, hash(key), [key, value]); + }; + + + + // #pragma Iterators + + ArrayMapNode.prototype.iterate = + HashCollisionNode.prototype.iterate = function (fn, reverse) { + var entries = this.entries; + for (var ii = 0, maxIndex = entries.length - 1; ii <= maxIndex; ii++) { + if (fn(entries[reverse ? maxIndex - ii : ii]) === false) { + return false; + } + } + } + + BitmapIndexedNode.prototype.iterate = + HashArrayMapNode.prototype.iterate = function (fn, reverse) { + var nodes = this.nodes; + for (var ii = 0, maxIndex = nodes.length - 1; ii <= maxIndex; ii++) { + var node = nodes[reverse ? maxIndex - ii : ii]; + if (node && node.iterate(fn, reverse) === false) { + return false; + } + } + } + + ValueNode.prototype.iterate = function (fn, reverse) { + return fn(this.entry); + } + + createClass(MapIterator, Iterator); + + function MapIterator(map, type, reverse) { + this._type = type; + this._reverse = reverse; + this._stack = map._root && mapIteratorFrame(map._root); + } + + MapIterator.prototype.next = function() { + var type = this._type; + var stack = this._stack; + while (stack) { + var node = stack.node; + var index = stack.index++; + var maxIndex; + if (node.entry) { + if (index === 0) { + return mapIteratorValue(type, node.entry); + } + } else if (node.entries) { + maxIndex = node.entries.length - 1; + if (index <= maxIndex) { + return mapIteratorValue(type, node.entries[this._reverse ? maxIndex - index : index]); + } + } else { + maxIndex = node.nodes.length - 1; + if (index <= maxIndex) { + var subNode = node.nodes[this._reverse ? maxIndex - index : index]; + if (subNode) { + if (subNode.entry) { + return mapIteratorValue(type, subNode.entry); + } + stack = this._stack = mapIteratorFrame(subNode, stack); + } + continue; + } + } + stack = this._stack = this._stack.__prev; + } + return iteratorDone(); + }; + + + function mapIteratorValue(type, entry) { + return iteratorValue(type, entry[0], entry[1]); + } + + function mapIteratorFrame(node, prev) { + return { + node: node, + index: 0, + __prev: prev + }; + } + + function makeMap(size, root, ownerID, hash) { + var map = Object.create(MapPrototype); + map.size = size; + map._root = root; + map.__ownerID = ownerID; + map.__hash = hash; + map.__altered = false; + return map; + } + + var EMPTY_MAP; + function emptyMap() { + return EMPTY_MAP || (EMPTY_MAP = makeMap(0)); + } + + function updateMap(map, k, v) { + var newRoot; + var newSize; + if (!map._root) { + if (v === NOT_SET) { + return map; + } + newSize = 1; + newRoot = new ArrayMapNode(map.__ownerID, [[k, v]]); + } else { + var didChangeSize = MakeRef(CHANGE_LENGTH); + var didAlter = MakeRef(DID_ALTER); + newRoot = updateNode(map._root, map.__ownerID, 0, undefined, k, v, didChangeSize, didAlter); + if (!didAlter.value) { + return map; + } + newSize = map.size + (didChangeSize.value ? v === NOT_SET ? -1 : 1 : 0); + } + if (map.__ownerID) { + map.size = newSize; + map._root = newRoot; + map.__hash = undefined; + map.__altered = true; + return map; + } + return newRoot ? makeMap(newSize, newRoot) : emptyMap(); + } + + function updateNode(node, ownerID, shift, keyHash, key, value, didChangeSize, didAlter) { + if (!node) { + if (value === NOT_SET) { + return node; + } + SetRef(didAlter); + SetRef(didChangeSize); + return new ValueNode(ownerID, keyHash, [key, value]); + } + return node.update(ownerID, shift, keyHash, key, value, didChangeSize, didAlter); + } + + function isLeafNode(node) { + return node.constructor === ValueNode || node.constructor === HashCollisionNode; + } + + function mergeIntoNode(node, ownerID, shift, keyHash, entry) { + if (node.keyHash === keyHash) { + return new HashCollisionNode(ownerID, keyHash, [node.entry, entry]); + } + + var idx1 = (shift === 0 ? node.keyHash : node.keyHash >>> shift) & MASK; + var idx2 = (shift === 0 ? keyHash : keyHash >>> shift) & MASK; + + var newNode; + var nodes = idx1 === idx2 ? + [mergeIntoNode(node, ownerID, shift + SHIFT, keyHash, entry)] : + ((newNode = new ValueNode(ownerID, keyHash, entry)), idx1 < idx2 ? [node, newNode] : [newNode, node]); + + return new BitmapIndexedNode(ownerID, (1 << idx1) | (1 << idx2), nodes); + } + + function createNodes(ownerID, entries, key, value) { + if (!ownerID) { + ownerID = new OwnerID(); + } + var node = new ValueNode(ownerID, hash(key), [key, value]); + for (var ii = 0; ii < entries.length; ii++) { + var entry = entries[ii]; + node = node.update(ownerID, 0, undefined, entry[0], entry[1]); + } + return node; + } + + function packNodes(ownerID, nodes, count, excluding) { + var bitmap = 0; + var packedII = 0; + var packedNodes = new Array(count); + for (var ii = 0, bit = 1, len = nodes.length; ii < len; ii++, bit <<= 1) { + var node = nodes[ii]; + if (node !== undefined && ii !== excluding) { + bitmap |= bit; + packedNodes[packedII++] = node; + } + } + return new BitmapIndexedNode(ownerID, bitmap, packedNodes); + } + + function expandNodes(ownerID, nodes, bitmap, including, node) { + var count = 0; + var expandedNodes = new Array(SIZE); + for (var ii = 0; bitmap !== 0; ii++, bitmap >>>= 1) { + expandedNodes[ii] = bitmap & 1 ? nodes[count++] : undefined; + } + expandedNodes[including] = node; + return new HashArrayMapNode(ownerID, count + 1, expandedNodes); + } + + function mergeIntoMapWith(map, merger, iterables) { + var iters = []; + for (var ii = 0; ii < iterables.length; ii++) { + var value = iterables[ii]; + var iter = KeyedIterable(value); + if (!isIterable(value)) { + iter = iter.map(function(v ) {return fromJS(v)}); + } + iters.push(iter); + } + return mergeIntoCollectionWith(map, merger, iters); + } + + function deepMerger(existing, value, key) { + return existing && existing.mergeDeep && isIterable(value) ? + existing.mergeDeep(value) : + is(existing, value) ? existing : value; + } + + function deepMergerWith(merger) { + return function(existing, value, key) { + if (existing && existing.mergeDeepWith && isIterable(value)) { + return existing.mergeDeepWith(merger, value); + } + var nextValue = merger(existing, value, key); + return is(existing, nextValue) ? existing : nextValue; + }; + } + + function mergeIntoCollectionWith(collection, merger, iters) { + iters = iters.filter(function(x ) {return x.size !== 0}); + if (iters.length === 0) { + return collection; + } + if (collection.size === 0 && !collection.__ownerID && iters.length === 1) { + return collection.constructor(iters[0]); + } + return collection.withMutations(function(collection ) { + var mergeIntoMap = merger ? + function(value, key) { + collection.update(key, NOT_SET, function(existing ) + {return existing === NOT_SET ? value : merger(existing, value, key)} + ); + } : + function(value, key) { + collection.set(key, value); + } + for (var ii = 0; ii < iters.length; ii++) { + iters[ii].forEach(mergeIntoMap); + } + }); + } + + function updateInDeepMap(existing, keyPathIter, notSetValue, updater) { + var isNotSet = existing === NOT_SET; + var step = keyPathIter.next(); + if (step.done) { + var existingValue = isNotSet ? notSetValue : existing; + var newValue = updater(existingValue); + return newValue === existingValue ? existing : newValue; + } + invariant( + isNotSet || (existing && existing.set), + 'invalid keyPath' + ); + var key = step.value; + var nextExisting = isNotSet ? NOT_SET : existing.get(key, NOT_SET); + var nextUpdated = updateInDeepMap( + nextExisting, + keyPathIter, + notSetValue, + updater + ); + return nextUpdated === nextExisting ? existing : + nextUpdated === NOT_SET ? existing.remove(key) : + (isNotSet ? emptyMap() : existing).set(key, nextUpdated); + } + + function popCount(x) { + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0f0f0f0f; + x = x + (x >> 8); + x = x + (x >> 16); + return x & 0x7f; + } + + function setIn(array, idx, val, canEdit) { + var newArray = canEdit ? array : arrCopy(array); + newArray[idx] = val; + return newArray; + } + + function spliceIn(array, idx, val, canEdit) { + var newLen = array.length + 1; + if (canEdit && idx + 1 === newLen) { + array[idx] = val; + return array; + } + var newArray = new Array(newLen); + var after = 0; + for (var ii = 0; ii < newLen; ii++) { + if (ii === idx) { + newArray[ii] = val; + after = -1; + } else { + newArray[ii] = array[ii + after]; + } + } + return newArray; + } + + function spliceOut(array, idx, canEdit) { + var newLen = array.length - 1; + if (canEdit && idx === newLen) { + array.pop(); + return array; + } + var newArray = new Array(newLen); + var after = 0; + for (var ii = 0; ii < newLen; ii++) { + if (ii === idx) { + after = 1; + } + newArray[ii] = array[ii + after]; + } + return newArray; + } + + var MAX_ARRAY_MAP_SIZE = SIZE / 4; + var MAX_BITMAP_INDEXED_SIZE = SIZE / 2; + var MIN_HASH_ARRAY_MAP_SIZE = SIZE / 4; + + createClass(List, IndexedCollection); + + // @pragma Construction + + function List(value) { + var empty = emptyList(); + if (value === null || value === undefined) { + return empty; + } + if (isList(value)) { + return value; + } + var iter = IndexedIterable(value); + var size = iter.size; + if (size === 0) { + return empty; + } + assertNotInfinite(size); + if (size > 0 && size < SIZE) { + return makeList(0, size, SHIFT, null, new VNode(iter.toArray())); + } + return empty.withMutations(function(list ) { + list.setSize(size); + iter.forEach(function(v, i) {return list.set(i, v)}); + }); + } + + List.of = function(/*...values*/) { + return this(arguments); + }; + + List.prototype.toString = function() { + return this.__toString('List [', ']'); + }; + + // @pragma Access + + List.prototype.get = function(index, notSetValue) { + index = wrapIndex(this, index); + if (index >= 0 && index < this.size) { + index += this._origin; + var node = listNodeFor(this, index); + return node && node.array[index & MASK]; + } + return notSetValue; + }; + + // @pragma Modification + + List.prototype.set = function(index, value) { + return updateList(this, index, value); + }; + + List.prototype.remove = function(index) { + return !this.has(index) ? this : + index === 0 ? this.shift() : + index === this.size - 1 ? this.pop() : + this.splice(index, 1); + }; + + List.prototype.insert = function(index, value) { + return this.splice(index, 0, value); + }; + + List.prototype.clear = function() { + if (this.size === 0) { + return this; + } + if (this.__ownerID) { + this.size = this._origin = this._capacity = 0; + this._level = SHIFT; + this._root = this._tail = null; + this.__hash = undefined; + this.__altered = true; + return this; + } + return emptyList(); + }; + + List.prototype.push = function(/*...values*/) { + var values = arguments; + var oldSize = this.size; + return this.withMutations(function(list ) { + setListBounds(list, 0, oldSize + values.length); + for (var ii = 0; ii < values.length; ii++) { + list.set(oldSize + ii, values[ii]); + } + }); + }; + + List.prototype.pop = function() { + return setListBounds(this, 0, -1); + }; + + List.prototype.unshift = function(/*...values*/) { + var values = arguments; + return this.withMutations(function(list ) { + setListBounds(list, -values.length); + for (var ii = 0; ii < values.length; ii++) { + list.set(ii, values[ii]); + } + }); + }; + + List.prototype.shift = function() { + return setListBounds(this, 1); + }; + + // @pragma Composition + + List.prototype.merge = function(/*...iters*/) { + return mergeIntoListWith(this, undefined, arguments); + }; + + List.prototype.mergeWith = function(merger) {var iters = SLICE$0.call(arguments, 1); + return mergeIntoListWith(this, merger, iters); + }; + + List.prototype.mergeDeep = function(/*...iters*/) { + return mergeIntoListWith(this, deepMerger, arguments); + }; + + List.prototype.mergeDeepWith = function(merger) {var iters = SLICE$0.call(arguments, 1); + return mergeIntoListWith(this, deepMergerWith(merger), iters); + }; + + List.prototype.setSize = function(size) { + return setListBounds(this, 0, size); + }; + + // @pragma Iteration + + List.prototype.slice = function(begin, end) { + var size = this.size; + if (wholeSlice(begin, end, size)) { + return this; + } + return setListBounds( + this, + resolveBegin(begin, size), + resolveEnd(end, size) + ); + }; + + List.prototype.__iterator = function(type, reverse) { + var index = 0; + var values = iterateList(this, reverse); + return new Iterator(function() { + var value = values(); + return value === DONE ? + iteratorDone() : + iteratorValue(type, index++, value); + }); + }; + + List.prototype.__iterate = function(fn, reverse) { + var index = 0; + var values = iterateList(this, reverse); + var value; + while ((value = values()) !== DONE) { + if (fn(value, index++, this) === false) { + break; + } + } + return index; + }; + + List.prototype.__ensureOwner = function(ownerID) { + if (ownerID === this.__ownerID) { + return this; + } + if (!ownerID) { + this.__ownerID = ownerID; + return this; + } + return makeList(this._origin, this._capacity, this._level, this._root, this._tail, ownerID, this.__hash); + }; + + + function isList(maybeList) { + return !!(maybeList && maybeList[IS_LIST_SENTINEL]); + } + + List.isList = isList; + + var IS_LIST_SENTINEL = '@@__IMMUTABLE_LIST__@@'; + + var ListPrototype = List.prototype; + ListPrototype[IS_LIST_SENTINEL] = true; + ListPrototype[DELETE] = ListPrototype.remove; + ListPrototype.setIn = MapPrototype.setIn; + ListPrototype.deleteIn = + ListPrototype.removeIn = MapPrototype.removeIn; + ListPrototype.update = MapPrototype.update; + ListPrototype.updateIn = MapPrototype.updateIn; + ListPrototype.mergeIn = MapPrototype.mergeIn; + ListPrototype.mergeDeepIn = MapPrototype.mergeDeepIn; + ListPrototype.withMutations = MapPrototype.withMutations; + ListPrototype.asMutable = MapPrototype.asMutable; + ListPrototype.asImmutable = MapPrototype.asImmutable; + ListPrototype.wasAltered = MapPrototype.wasAltered; + + + + function VNode(array, ownerID) { + this.array = array; + this.ownerID = ownerID; + } + + // TODO: seems like these methods are very similar + + VNode.prototype.removeBefore = function(ownerID, level, index) { + if (index === level ? 1 << level : 0 || this.array.length === 0) { + return this; + } + var originIndex = (index >>> level) & MASK; + if (originIndex >= this.array.length) { + return new VNode([], ownerID); + } + var removingFirst = originIndex === 0; + var newChild; + if (level > 0) { + var oldChild = this.array[originIndex]; + newChild = oldChild && oldChild.removeBefore(ownerID, level - SHIFT, index); + if (newChild === oldChild && removingFirst) { + return this; + } + } + if (removingFirst && !newChild) { + return this; + } + var editable = editableVNode(this, ownerID); + if (!removingFirst) { + for (var ii = 0; ii < originIndex; ii++) { + editable.array[ii] = undefined; + } + } + if (newChild) { + editable.array[originIndex] = newChild; + } + return editable; + }; + + VNode.prototype.removeAfter = function(ownerID, level, index) { + if (index === (level ? 1 << level : 0) || this.array.length === 0) { + return this; + } + var sizeIndex = ((index - 1) >>> level) & MASK; + if (sizeIndex >= this.array.length) { + return this; + } + + var newChild; + if (level > 0) { + var oldChild = this.array[sizeIndex]; + newChild = oldChild && oldChild.removeAfter(ownerID, level - SHIFT, index); + if (newChild === oldChild && sizeIndex === this.array.length - 1) { + return this; + } + } + + var editable = editableVNode(this, ownerID); + editable.array.splice(sizeIndex + 1); + if (newChild) { + editable.array[sizeIndex] = newChild; + } + return editable; + }; + + + + var DONE = {}; + + function iterateList(list, reverse) { + var left = list._origin; + var right = list._capacity; + var tailPos = getTailOffset(right); + var tail = list._tail; + + return iterateNodeOrLeaf(list._root, list._level, 0); + + function iterateNodeOrLeaf(node, level, offset) { + return level === 0 ? + iterateLeaf(node, offset) : + iterateNode(node, level, offset); + } + + function iterateLeaf(node, offset) { + var array = offset === tailPos ? tail && tail.array : node && node.array; + var from = offset > left ? 0 : left - offset; + var to = right - offset; + if (to > SIZE) { + to = SIZE; + } + return function() { + if (from === to) { + return DONE; + } + var idx = reverse ? --to : from++; + return array && array[idx]; + }; + } + + function iterateNode(node, level, offset) { + var values; + var array = node && node.array; + var from = offset > left ? 0 : (left - offset) >> level; + var to = ((right - offset) >> level) + 1; + if (to > SIZE) { + to = SIZE; + } + return function() { + do { + if (values) { + var value = values(); + if (value !== DONE) { + return value; + } + values = null; + } + if (from === to) { + return DONE; + } + var idx = reverse ? --to : from++; + values = iterateNodeOrLeaf( + array && array[idx], level - SHIFT, offset + (idx << level) + ); + } while (true); + }; + } + } + + function makeList(origin, capacity, level, root, tail, ownerID, hash) { + var list = Object.create(ListPrototype); + list.size = capacity - origin; + list._origin = origin; + list._capacity = capacity; + list._level = level; + list._root = root; + list._tail = tail; + list.__ownerID = ownerID; + list.__hash = hash; + list.__altered = false; + return list; + } + + var EMPTY_LIST; + function emptyList() { + return EMPTY_LIST || (EMPTY_LIST = makeList(0, 0, SHIFT)); + } + + function updateList(list, index, value) { + index = wrapIndex(list, index); + + if (index !== index) { + return list; + } + + if (index >= list.size || index < 0) { + return list.withMutations(function(list ) { + index < 0 ? + setListBounds(list, index).set(0, value) : + setListBounds(list, 0, index + 1).set(index, value) + }); + } + + index += list._origin; + + var newTail = list._tail; + var newRoot = list._root; + var didAlter = MakeRef(DID_ALTER); + if (index >= getTailOffset(list._capacity)) { + newTail = updateVNode(newTail, list.__ownerID, 0, index, value, didAlter); + } else { + newRoot = updateVNode(newRoot, list.__ownerID, list._level, index, value, didAlter); + } + + if (!didAlter.value) { + return list; + } + + if (list.__ownerID) { + list._root = newRoot; + list._tail = newTail; + list.__hash = undefined; + list.__altered = true; + return list; + } + return makeList(list._origin, list._capacity, list._level, newRoot, newTail); + } + + function updateVNode(node, ownerID, level, index, value, didAlter) { + var idx = (index >>> level) & MASK; + var nodeHas = node && idx < node.array.length; + if (!nodeHas && value === undefined) { + return node; + } + + var newNode; + + if (level > 0) { + var lowerNode = node && node.array[idx]; + var newLowerNode = updateVNode(lowerNode, ownerID, level - SHIFT, index, value, didAlter); + if (newLowerNode === lowerNode) { + return node; + } + newNode = editableVNode(node, ownerID); + newNode.array[idx] = newLowerNode; + return newNode; + } + + if (nodeHas && node.array[idx] === value) { + return node; + } + + SetRef(didAlter); + + newNode = editableVNode(node, ownerID); + if (value === undefined && idx === newNode.array.length - 1) { + newNode.array.pop(); + } else { + newNode.array[idx] = value; + } + return newNode; + } + + function editableVNode(node, ownerID) { + if (ownerID && node && ownerID === node.ownerID) { + return node; + } + return new VNode(node ? node.array.slice() : [], ownerID); + } + + function listNodeFor(list, rawIndex) { + if (rawIndex >= getTailOffset(list._capacity)) { + return list._tail; + } + if (rawIndex < 1 << (list._level + SHIFT)) { + var node = list._root; + var level = list._level; + while (node && level > 0) { + node = node.array[(rawIndex >>> level) & MASK]; + level -= SHIFT; + } + return node; + } + } + + function setListBounds(list, begin, end) { + // Sanitize begin & end using this shorthand for ToInt32(argument) + // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32 + if (begin !== undefined) { + begin = begin | 0; + } + if (end !== undefined) { + end = end | 0; + } + var owner = list.__ownerID || new OwnerID(); + var oldOrigin = list._origin; + var oldCapacity = list._capacity; + var newOrigin = oldOrigin + begin; + var newCapacity = end === undefined ? oldCapacity : end < 0 ? oldCapacity + end : oldOrigin + end; + if (newOrigin === oldOrigin && newCapacity === oldCapacity) { + return list; + } + + // If it's going to end after it starts, it's empty. + if (newOrigin >= newCapacity) { + return list.clear(); + } + + var newLevel = list._level; + var newRoot = list._root; + + // New origin might need creating a higher root. + var offsetShift = 0; + while (newOrigin + offsetShift < 0) { + newRoot = new VNode(newRoot && newRoot.array.length ? [undefined, newRoot] : [], owner); + newLevel += SHIFT; + offsetShift += 1 << newLevel; + } + if (offsetShift) { + newOrigin += offsetShift; + oldOrigin += offsetShift; + newCapacity += offsetShift; + oldCapacity += offsetShift; + } + + var oldTailOffset = getTailOffset(oldCapacity); + var newTailOffset = getTailOffset(newCapacity); + + // New size might need creating a higher root. + while (newTailOffset >= 1 << (newLevel + SHIFT)) { + newRoot = new VNode(newRoot && newRoot.array.length ? [newRoot] : [], owner); + newLevel += SHIFT; + } + + // Locate or create the new tail. + var oldTail = list._tail; + var newTail = newTailOffset < oldTailOffset ? + listNodeFor(list, newCapacity - 1) : + newTailOffset > oldTailOffset ? new VNode([], owner) : oldTail; + + // Merge Tail into tree. + if (oldTail && newTailOffset > oldTailOffset && newOrigin < oldCapacity && oldTail.array.length) { + newRoot = editableVNode(newRoot, owner); + var node = newRoot; + for (var level = newLevel; level > SHIFT; level -= SHIFT) { + var idx = (oldTailOffset >>> level) & MASK; + node = node.array[idx] = editableVNode(node.array[idx], owner); + } + node.array[(oldTailOffset >>> SHIFT) & MASK] = oldTail; + } + + // If the size has been reduced, there's a chance the tail needs to be trimmed. + if (newCapacity < oldCapacity) { + newTail = newTail && newTail.removeAfter(owner, 0, newCapacity); + } + + // If the new origin is within the tail, then we do not need a root. + if (newOrigin >= newTailOffset) { + newOrigin -= newTailOffset; + newCapacity -= newTailOffset; + newLevel = SHIFT; + newRoot = null; + newTail = newTail && newTail.removeBefore(owner, 0, newOrigin); + + // Otherwise, if the root has been trimmed, garbage collect. + } else if (newOrigin > oldOrigin || newTailOffset < oldTailOffset) { + offsetShift = 0; + + // Identify the new top root node of the subtree of the old root. + while (newRoot) { + var beginIndex = (newOrigin >>> newLevel) & MASK; + if (beginIndex !== (newTailOffset >>> newLevel) & MASK) { + break; + } + if (beginIndex) { + offsetShift += (1 << newLevel) * beginIndex; + } + newLevel -= SHIFT; + newRoot = newRoot.array[beginIndex]; + } + + // Trim the new sides of the new root. + if (newRoot && newOrigin > oldOrigin) { + newRoot = newRoot.removeBefore(owner, newLevel, newOrigin - offsetShift); + } + if (newRoot && newTailOffset < oldTailOffset) { + newRoot = newRoot.removeAfter(owner, newLevel, newTailOffset - offsetShift); + } + if (offsetShift) { + newOrigin -= offsetShift; + newCapacity -= offsetShift; + } + } + + if (list.__ownerID) { + list.size = newCapacity - newOrigin; + list._origin = newOrigin; + list._capacity = newCapacity; + list._level = newLevel; + list._root = newRoot; + list._tail = newTail; + list.__hash = undefined; + list.__altered = true; + return list; + } + return makeList(newOrigin, newCapacity, newLevel, newRoot, newTail); + } + + function mergeIntoListWith(list, merger, iterables) { + var iters = []; + var maxSize = 0; + for (var ii = 0; ii < iterables.length; ii++) { + var value = iterables[ii]; + var iter = IndexedIterable(value); + if (iter.size > maxSize) { + maxSize = iter.size; + } + if (!isIterable(value)) { + iter = iter.map(function(v ) {return fromJS(v)}); + } + iters.push(iter); + } + if (maxSize > list.size) { + list = list.setSize(maxSize); + } + return mergeIntoCollectionWith(list, merger, iters); + } + + function getTailOffset(size) { + return size < SIZE ? 0 : (((size - 1) >>> SHIFT) << SHIFT); + } + + createClass(OrderedMap, Map); + + // @pragma Construction + + function OrderedMap(value) { + return value === null || value === undefined ? emptyOrderedMap() : + isOrderedMap(value) ? value : + emptyOrderedMap().withMutations(function(map ) { + var iter = KeyedIterable(value); + assertNotInfinite(iter.size); + iter.forEach(function(v, k) {return map.set(k, v)}); + }); + } + + OrderedMap.of = function(/*...values*/) { + return this(arguments); + }; + + OrderedMap.prototype.toString = function() { + return this.__toString('OrderedMap {', '}'); + }; + + // @pragma Access + + OrderedMap.prototype.get = function(k, notSetValue) { + var index = this._map.get(k); + return index !== undefined ? this._list.get(index)[1] : notSetValue; + }; + + // @pragma Modification + + OrderedMap.prototype.clear = function() { + if (this.size === 0) { + return this; + } + if (this.__ownerID) { + this.size = 0; + this._map.clear(); + this._list.clear(); + return this; + } + return emptyOrderedMap(); + }; + + OrderedMap.prototype.set = function(k, v) { + return updateOrderedMap(this, k, v); + }; + + OrderedMap.prototype.remove = function(k) { + return updateOrderedMap(this, k, NOT_SET); + }; + + OrderedMap.prototype.wasAltered = function() { + return this._map.wasAltered() || this._list.wasAltered(); + }; + + OrderedMap.prototype.__iterate = function(fn, reverse) {var this$0 = this; + return this._list.__iterate( + function(entry ) {return entry && fn(entry[1], entry[0], this$0)}, + reverse + ); + }; + + OrderedMap.prototype.__iterator = function(type, reverse) { + return this._list.fromEntrySeq().__iterator(type, reverse); + }; + + OrderedMap.prototype.__ensureOwner = function(ownerID) { + if (ownerID === this.__ownerID) { + return this; + } + var newMap = this._map.__ensureOwner(ownerID); + var newList = this._list.__ensureOwner(ownerID); + if (!ownerID) { + this.__ownerID = ownerID; + this._map = newMap; + this._list = newList; + return this; + } + return makeOrderedMap(newMap, newList, ownerID, this.__hash); + }; + + + function isOrderedMap(maybeOrderedMap) { + return isMap(maybeOrderedMap) && isOrdered(maybeOrderedMap); + } + + OrderedMap.isOrderedMap = isOrderedMap; + + OrderedMap.prototype[IS_ORDERED_SENTINEL] = true; + OrderedMap.prototype[DELETE] = OrderedMap.prototype.remove; + + + + function makeOrderedMap(map, list, ownerID, hash) { + var omap = Object.create(OrderedMap.prototype); + omap.size = map ? map.size : 0; + omap._map = map; + omap._list = list; + omap.__ownerID = ownerID; + omap.__hash = hash; + return omap; + } + + var EMPTY_ORDERED_MAP; + function emptyOrderedMap() { + return EMPTY_ORDERED_MAP || (EMPTY_ORDERED_MAP = makeOrderedMap(emptyMap(), emptyList())); + } + + function updateOrderedMap(omap, k, v) { + var map = omap._map; + var list = omap._list; + var i = map.get(k); + var has = i !== undefined; + var newMap; + var newList; + if (v === NOT_SET) { // removed + if (!has) { + return omap; + } + if (list.size >= SIZE && list.size >= map.size * 2) { + newList = list.filter(function(entry, idx) {return entry !== undefined && i !== idx}); + newMap = newList.toKeyedSeq().map(function(entry ) {return entry[0]}).flip().toMap(); + if (omap.__ownerID) { + newMap.__ownerID = newList.__ownerID = omap.__ownerID; + } + } else { + newMap = map.remove(k); + newList = i === list.size - 1 ? list.pop() : list.set(i, undefined); + } + } else { + if (has) { + if (v === list.get(i)[1]) { + return omap; + } + newMap = map; + newList = list.set(i, [k, v]); + } else { + newMap = map.set(k, list.size); + newList = list.set(list.size, [k, v]); + } + } + if (omap.__ownerID) { + omap.size = newMap.size; + omap._map = newMap; + omap._list = newList; + omap.__hash = undefined; + return omap; + } + return makeOrderedMap(newMap, newList); + } + + createClass(ToKeyedSequence, KeyedSeq); + function ToKeyedSequence(indexed, useKeys) { + this._iter = indexed; + this._useKeys = useKeys; + this.size = indexed.size; + } + + ToKeyedSequence.prototype.get = function(key, notSetValue) { + return this._iter.get(key, notSetValue); + }; + + ToKeyedSequence.prototype.has = function(key) { + return this._iter.has(key); + }; + + ToKeyedSequence.prototype.valueSeq = function() { + return this._iter.valueSeq(); + }; + + ToKeyedSequence.prototype.reverse = function() {var this$0 = this; + var reversedSequence = reverseFactory(this, true); + if (!this._useKeys) { + reversedSequence.valueSeq = function() {return this$0._iter.toSeq().reverse()}; + } + return reversedSequence; + }; + + ToKeyedSequence.prototype.map = function(mapper, context) {var this$0 = this; + var mappedSequence = mapFactory(this, mapper, context); + if (!this._useKeys) { + mappedSequence.valueSeq = function() {return this$0._iter.toSeq().map(mapper, context)}; + } + return mappedSequence; + }; + + ToKeyedSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this; + var ii; + return this._iter.__iterate( + this._useKeys ? + function(v, k) {return fn(v, k, this$0)} : + ((ii = reverse ? resolveSize(this) : 0), + function(v ) {return fn(v, reverse ? --ii : ii++, this$0)}), + reverse + ); + }; + + ToKeyedSequence.prototype.__iterator = function(type, reverse) { + if (this._useKeys) { + return this._iter.__iterator(type, reverse); + } + var iterator = this._iter.__iterator(ITERATE_VALUES, reverse); + var ii = reverse ? resolveSize(this) : 0; + return new Iterator(function() { + var step = iterator.next(); + return step.done ? step : + iteratorValue(type, reverse ? --ii : ii++, step.value, step); + }); + }; + + ToKeyedSequence.prototype[IS_ORDERED_SENTINEL] = true; + + + createClass(ToIndexedSequence, IndexedSeq); + function ToIndexedSequence(iter) { + this._iter = iter; + this.size = iter.size; + } + + ToIndexedSequence.prototype.includes = function(value) { + return this._iter.includes(value); + }; + + ToIndexedSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this; + var iterations = 0; + return this._iter.__iterate(function(v ) {return fn(v, iterations++, this$0)}, reverse); + }; + + ToIndexedSequence.prototype.__iterator = function(type, reverse) { + var iterator = this._iter.__iterator(ITERATE_VALUES, reverse); + var iterations = 0; + return new Iterator(function() { + var step = iterator.next(); + return step.done ? step : + iteratorValue(type, iterations++, step.value, step) + }); + }; + + + + createClass(ToSetSequence, SetSeq); + function ToSetSequence(iter) { + this._iter = iter; + this.size = iter.size; + } + + ToSetSequence.prototype.has = function(key) { + return this._iter.includes(key); + }; + + ToSetSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this; + return this._iter.__iterate(function(v ) {return fn(v, v, this$0)}, reverse); + }; + + ToSetSequence.prototype.__iterator = function(type, reverse) { + var iterator = this._iter.__iterator(ITERATE_VALUES, reverse); + return new Iterator(function() { + var step = iterator.next(); + return step.done ? step : + iteratorValue(type, step.value, step.value, step); + }); + }; + + + + createClass(FromEntriesSequence, KeyedSeq); + function FromEntriesSequence(entries) { + this._iter = entries; + this.size = entries.size; + } + + FromEntriesSequence.prototype.entrySeq = function() { + return this._iter.toSeq(); + }; + + FromEntriesSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this; + return this._iter.__iterate(function(entry ) { + // Check if entry exists first so array access doesn't throw for holes + // in the parent iteration. + if (entry) { + validateEntry(entry); + var indexedIterable = isIterable(entry); + return fn( + indexedIterable ? entry.get(1) : entry[1], + indexedIterable ? entry.get(0) : entry[0], + this$0 + ); + } + }, reverse); + }; + + FromEntriesSequence.prototype.__iterator = function(type, reverse) { + var iterator = this._iter.__iterator(ITERATE_VALUES, reverse); + return new Iterator(function() { + while (true) { + var step = iterator.next(); + if (step.done) { + return step; + } + var entry = step.value; + // Check if entry exists first so array access doesn't throw for holes + // in the parent iteration. + if (entry) { + validateEntry(entry); + var indexedIterable = isIterable(entry); + return iteratorValue( + type, + indexedIterable ? entry.get(0) : entry[0], + indexedIterable ? entry.get(1) : entry[1], + step + ); + } + } + }); + }; + + + ToIndexedSequence.prototype.cacheResult = + ToKeyedSequence.prototype.cacheResult = + ToSetSequence.prototype.cacheResult = + FromEntriesSequence.prototype.cacheResult = + cacheResultThrough; + + + function flipFactory(iterable) { + var flipSequence = makeSequence(iterable); + flipSequence._iter = iterable; + flipSequence.size = iterable.size; + flipSequence.flip = function() {return iterable}; + flipSequence.reverse = function () { + var reversedSequence = iterable.reverse.apply(this); // super.reverse() + reversedSequence.flip = function() {return iterable.reverse()}; + return reversedSequence; + }; + flipSequence.has = function(key ) {return iterable.includes(key)}; + flipSequence.includes = function(key ) {return iterable.has(key)}; + flipSequence.cacheResult = cacheResultThrough; + flipSequence.__iterateUncached = function (fn, reverse) {var this$0 = this; + return iterable.__iterate(function(v, k) {return fn(k, v, this$0) !== false}, reverse); + } + flipSequence.__iteratorUncached = function(type, reverse) { + if (type === ITERATE_ENTRIES) { + var iterator = iterable.__iterator(type, reverse); + return new Iterator(function() { + var step = iterator.next(); + if (!step.done) { + var k = step.value[0]; + step.value[0] = step.value[1]; + step.value[1] = k; + } + return step; + }); + } + return iterable.__iterator( + type === ITERATE_VALUES ? ITERATE_KEYS : ITERATE_VALUES, + reverse + ); + } + return flipSequence; + } + + + function mapFactory(iterable, mapper, context) { + var mappedSequence = makeSequence(iterable); + mappedSequence.size = iterable.size; + mappedSequence.has = function(key ) {return iterable.has(key)}; + mappedSequence.get = function(key, notSetValue) { + var v = iterable.get(key, NOT_SET); + return v === NOT_SET ? + notSetValue : + mapper.call(context, v, key, iterable); + }; + mappedSequence.__iterateUncached = function (fn, reverse) {var this$0 = this; + return iterable.__iterate( + function(v, k, c) {return fn(mapper.call(context, v, k, c), k, this$0) !== false}, + reverse + ); + } + mappedSequence.__iteratorUncached = function (type, reverse) { + var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse); + return new Iterator(function() { + var step = iterator.next(); + if (step.done) { + return step; + } + var entry = step.value; + var key = entry[0]; + return iteratorValue( + type, + key, + mapper.call(context, entry[1], key, iterable), + step + ); + }); + } + return mappedSequence; + } + + + function reverseFactory(iterable, useKeys) { + var reversedSequence = makeSequence(iterable); + reversedSequence._iter = iterable; + reversedSequence.size = iterable.size; + reversedSequence.reverse = function() {return iterable}; + if (iterable.flip) { + reversedSequence.flip = function () { + var flipSequence = flipFactory(iterable); + flipSequence.reverse = function() {return iterable.flip()}; + return flipSequence; + }; + } + reversedSequence.get = function(key, notSetValue) + {return iterable.get(useKeys ? key : -1 - key, notSetValue)}; + reversedSequence.has = function(key ) + {return iterable.has(useKeys ? key : -1 - key)}; + reversedSequence.includes = function(value ) {return iterable.includes(value)}; + reversedSequence.cacheResult = cacheResultThrough; + reversedSequence.__iterate = function (fn, reverse) {var this$0 = this; + return iterable.__iterate(function(v, k) {return fn(v, k, this$0)}, !reverse); + }; + reversedSequence.__iterator = + function(type, reverse) {return iterable.__iterator(type, !reverse)}; + return reversedSequence; + } + + + function filterFactory(iterable, predicate, context, useKeys) { + var filterSequence = makeSequence(iterable); + if (useKeys) { + filterSequence.has = function(key ) { + var v = iterable.get(key, NOT_SET); + return v !== NOT_SET && !!predicate.call(context, v, key, iterable); + }; + filterSequence.get = function(key, notSetValue) { + var v = iterable.get(key, NOT_SET); + return v !== NOT_SET && predicate.call(context, v, key, iterable) ? + v : notSetValue; + }; + } + filterSequence.__iterateUncached = function (fn, reverse) {var this$0 = this; + var iterations = 0; + iterable.__iterate(function(v, k, c) { + if (predicate.call(context, v, k, c)) { + iterations++; + return fn(v, useKeys ? k : iterations - 1, this$0); + } + }, reverse); + return iterations; + }; + filterSequence.__iteratorUncached = function (type, reverse) { + var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse); + var iterations = 0; + return new Iterator(function() { + while (true) { + var step = iterator.next(); + if (step.done) { + return step; + } + var entry = step.value; + var key = entry[0]; + var value = entry[1]; + if (predicate.call(context, value, key, iterable)) { + return iteratorValue(type, useKeys ? key : iterations++, value, step); + } + } + }); + } + return filterSequence; + } + + + function countByFactory(iterable, grouper, context) { + var groups = Map().asMutable(); + iterable.__iterate(function(v, k) { + groups.update( + grouper.call(context, v, k, iterable), + 0, + function(a ) {return a + 1} + ); + }); + return groups.asImmutable(); + } + + + function groupByFactory(iterable, grouper, context) { + var isKeyedIter = isKeyed(iterable); + var groups = (isOrdered(iterable) ? OrderedMap() : Map()).asMutable(); + iterable.__iterate(function(v, k) { + groups.update( + grouper.call(context, v, k, iterable), + function(a ) {return (a = a || [], a.push(isKeyedIter ? [k, v] : v), a)} + ); + }); + var coerce = iterableClass(iterable); + return groups.map(function(arr ) {return reify(iterable, coerce(arr))}); + } + + + function sliceFactory(iterable, begin, end, useKeys) { + var originalSize = iterable.size; + + // Sanitize begin & end using this shorthand for ToInt32(argument) + // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32 + if (begin !== undefined) { + begin = begin | 0; + } + if (end !== undefined) { + if (end === Infinity) { + end = originalSize; + } else { + end = end | 0; + } + } + + if (wholeSlice(begin, end, originalSize)) { + return iterable; + } + + var resolvedBegin = resolveBegin(begin, originalSize); + var resolvedEnd = resolveEnd(end, originalSize); + + // begin or end will be NaN if they were provided as negative numbers and + // this iterable's size is unknown. In that case, cache first so there is + // a known size and these do not resolve to NaN. + if (resolvedBegin !== resolvedBegin || resolvedEnd !== resolvedEnd) { + return sliceFactory(iterable.toSeq().cacheResult(), begin, end, useKeys); + } + + // Note: resolvedEnd is undefined when the original sequence's length is + // unknown and this slice did not supply an end and should contain all + // elements after resolvedBegin. + // In that case, resolvedSize will be NaN and sliceSize will remain undefined. + var resolvedSize = resolvedEnd - resolvedBegin; + var sliceSize; + if (resolvedSize === resolvedSize) { + sliceSize = resolvedSize < 0 ? 0 : resolvedSize; + } + + var sliceSeq = makeSequence(iterable); + + // If iterable.size is undefined, the size of the realized sliceSeq is + // unknown at this point unless the number of items to slice is 0 + sliceSeq.size = sliceSize === 0 ? sliceSize : iterable.size && sliceSize || undefined; + + if (!useKeys && isSeq(iterable) && sliceSize >= 0) { + sliceSeq.get = function (index, notSetValue) { + index = wrapIndex(this, index); + return index >= 0 && index < sliceSize ? + iterable.get(index + resolvedBegin, notSetValue) : + notSetValue; + } + } + + sliceSeq.__iterateUncached = function(fn, reverse) {var this$0 = this; + if (sliceSize === 0) { + return 0; + } + if (reverse) { + return this.cacheResult().__iterate(fn, reverse); + } + var skipped = 0; + var isSkipping = true; + var iterations = 0; + iterable.__iterate(function(v, k) { + if (!(isSkipping && (isSkipping = skipped++ < resolvedBegin))) { + iterations++; + return fn(v, useKeys ? k : iterations - 1, this$0) !== false && + iterations !== sliceSize; + } + }); + return iterations; + }; + + sliceSeq.__iteratorUncached = function(type, reverse) { + if (sliceSize !== 0 && reverse) { + return this.cacheResult().__iterator(type, reverse); + } + // Don't bother instantiating parent iterator if taking 0. + var iterator = sliceSize !== 0 && iterable.__iterator(type, reverse); + var skipped = 0; + var iterations = 0; + return new Iterator(function() { + while (skipped++ < resolvedBegin) { + iterator.next(); + } + if (++iterations > sliceSize) { + return iteratorDone(); + } + var step = iterator.next(); + if (useKeys || type === ITERATE_VALUES) { + return step; + } else if (type === ITERATE_KEYS) { + return iteratorValue(type, iterations - 1, undefined, step); + } else { + return iteratorValue(type, iterations - 1, step.value[1], step); + } + }); + } + + return sliceSeq; + } + + + function takeWhileFactory(iterable, predicate, context) { + var takeSequence = makeSequence(iterable); + takeSequence.__iterateUncached = function(fn, reverse) {var this$0 = this; + if (reverse) { + return this.cacheResult().__iterate(fn, reverse); + } + var iterations = 0; + iterable.__iterate(function(v, k, c) + {return predicate.call(context, v, k, c) && ++iterations && fn(v, k, this$0)} + ); + return iterations; + }; + takeSequence.__iteratorUncached = function(type, reverse) {var this$0 = this; + if (reverse) { + return this.cacheResult().__iterator(type, reverse); + } + var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse); + var iterating = true; + return new Iterator(function() { + if (!iterating) { + return iteratorDone(); + } + var step = iterator.next(); + if (step.done) { + return step; + } + var entry = step.value; + var k = entry[0]; + var v = entry[1]; + if (!predicate.call(context, v, k, this$0)) { + iterating = false; + return iteratorDone(); + } + return type === ITERATE_ENTRIES ? step : + iteratorValue(type, k, v, step); + }); + }; + return takeSequence; + } + + + function skipWhileFactory(iterable, predicate, context, useKeys) { + var skipSequence = makeSequence(iterable); + skipSequence.__iterateUncached = function (fn, reverse) {var this$0 = this; + if (reverse) { + return this.cacheResult().__iterate(fn, reverse); + } + var isSkipping = true; + var iterations = 0; + iterable.__iterate(function(v, k, c) { + if (!(isSkipping && (isSkipping = predicate.call(context, v, k, c)))) { + iterations++; + return fn(v, useKeys ? k : iterations - 1, this$0); + } + }); + return iterations; + }; + skipSequence.__iteratorUncached = function(type, reverse) {var this$0 = this; + if (reverse) { + return this.cacheResult().__iterator(type, reverse); + } + var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse); + var skipping = true; + var iterations = 0; + return new Iterator(function() { + var step, k, v; + do { + step = iterator.next(); + if (step.done) { + if (useKeys || type === ITERATE_VALUES) { + return step; + } else if (type === ITERATE_KEYS) { + return iteratorValue(type, iterations++, undefined, step); + } else { + return iteratorValue(type, iterations++, step.value[1], step); + } + } + var entry = step.value; + k = entry[0]; + v = entry[1]; + skipping && (skipping = predicate.call(context, v, k, this$0)); + } while (skipping); + return type === ITERATE_ENTRIES ? step : + iteratorValue(type, k, v, step); + }); + }; + return skipSequence; + } + + + function concatFactory(iterable, values) { + var isKeyedIterable = isKeyed(iterable); + var iters = [iterable].concat(values).map(function(v ) { + if (!isIterable(v)) { + v = isKeyedIterable ? + keyedSeqFromValue(v) : + indexedSeqFromValue(Array.isArray(v) ? v : [v]); + } else if (isKeyedIterable) { + v = KeyedIterable(v); + } + return v; + }).filter(function(v ) {return v.size !== 0}); + + if (iters.length === 0) { + return iterable; + } + + if (iters.length === 1) { + var singleton = iters[0]; + if (singleton === iterable || + isKeyedIterable && isKeyed(singleton) || + isIndexed(iterable) && isIndexed(singleton)) { + return singleton; + } + } + + var concatSeq = new ArraySeq(iters); + if (isKeyedIterable) { + concatSeq = concatSeq.toKeyedSeq(); + } else if (!isIndexed(iterable)) { + concatSeq = concatSeq.toSetSeq(); + } + concatSeq = concatSeq.flatten(true); + concatSeq.size = iters.reduce( + function(sum, seq) { + if (sum !== undefined) { + var size = seq.size; + if (size !== undefined) { + return sum + size; + } + } + }, + 0 + ); + return concatSeq; + } + + + function flattenFactory(iterable, depth, useKeys) { + var flatSequence = makeSequence(iterable); + flatSequence.__iterateUncached = function(fn, reverse) { + var iterations = 0; + var stopped = false; + function flatDeep(iter, currentDepth) {var this$0 = this; + iter.__iterate(function(v, k) { + if ((!depth || currentDepth < depth) && isIterable(v)) { + flatDeep(v, currentDepth + 1); + } else if (fn(v, useKeys ? k : iterations++, this$0) === false) { + stopped = true; + } + return !stopped; + }, reverse); + } + flatDeep(iterable, 0); + return iterations; + } + flatSequence.__iteratorUncached = function(type, reverse) { + var iterator = iterable.__iterator(type, reverse); + var stack = []; + var iterations = 0; + return new Iterator(function() { + while (iterator) { + var step = iterator.next(); + if (step.done !== false) { + iterator = stack.pop(); + continue; + } + var v = step.value; + if (type === ITERATE_ENTRIES) { + v = v[1]; + } + if ((!depth || stack.length < depth) && isIterable(v)) { + stack.push(iterator); + iterator = v.__iterator(type, reverse); + } else { + return useKeys ? step : iteratorValue(type, iterations++, v, step); + } + } + return iteratorDone(); + }); + } + return flatSequence; + } + + + function flatMapFactory(iterable, mapper, context) { + var coerce = iterableClass(iterable); + return iterable.toSeq().map( + function(v, k) {return coerce(mapper.call(context, v, k, iterable))} + ).flatten(true); + } + + + function interposeFactory(iterable, separator) { + var interposedSequence = makeSequence(iterable); + interposedSequence.size = iterable.size && iterable.size * 2 -1; + interposedSequence.__iterateUncached = function(fn, reverse) {var this$0 = this; + var iterations = 0; + iterable.__iterate(function(v, k) + {return (!iterations || fn(separator, iterations++, this$0) !== false) && + fn(v, iterations++, this$0) !== false}, + reverse + ); + return iterations; + }; + interposedSequence.__iteratorUncached = function(type, reverse) { + var iterator = iterable.__iterator(ITERATE_VALUES, reverse); + var iterations = 0; + var step; + return new Iterator(function() { + if (!step || iterations % 2) { + step = iterator.next(); + if (step.done) { + return step; + } + } + return iterations % 2 ? + iteratorValue(type, iterations++, separator) : + iteratorValue(type, iterations++, step.value, step); + }); + }; + return interposedSequence; + } + + + function sortFactory(iterable, comparator, mapper) { + if (!comparator) { + comparator = defaultComparator; + } + var isKeyedIterable = isKeyed(iterable); + var index = 0; + var entries = iterable.toSeq().map( + function(v, k) {return [k, v, index++, mapper ? mapper(v, k, iterable) : v]} + ).toArray(); + entries.sort(function(a, b) {return comparator(a[3], b[3]) || a[2] - b[2]}).forEach( + isKeyedIterable ? + function(v, i) { entries[i].length = 2; } : + function(v, i) { entries[i] = v[1]; } + ); + return isKeyedIterable ? KeyedSeq(entries) : + isIndexed(iterable) ? IndexedSeq(entries) : + SetSeq(entries); + } + + + function maxFactory(iterable, comparator, mapper) { + if (!comparator) { + comparator = defaultComparator; + } + if (mapper) { + var entry = iterable.toSeq() + .map(function(v, k) {return [v, mapper(v, k, iterable)]}) + .reduce(function(a, b) {return maxCompare(comparator, a[1], b[1]) ? b : a}); + return entry && entry[0]; + } else { + return iterable.reduce(function(a, b) {return maxCompare(comparator, a, b) ? b : a}); + } + } + + function maxCompare(comparator, a, b) { + var comp = comparator(b, a); + // b is considered the new max if the comparator declares them equal, but + // they are not equal and b is in fact a nullish value. + return (comp === 0 && b !== a && (b === undefined || b === null || b !== b)) || comp > 0; + } + + + function zipWithFactory(keyIter, zipper, iters) { + var zipSequence = makeSequence(keyIter); + zipSequence.size = new ArraySeq(iters).map(function(i ) {return i.size}).min(); + // Note: this a generic base implementation of __iterate in terms of + // __iterator which may be more generically useful in the future. + zipSequence.__iterate = function(fn, reverse) { + /* generic: + var iterator = this.__iterator(ITERATE_ENTRIES, reverse); + var step; + var iterations = 0; + while (!(step = iterator.next()).done) { + iterations++; + if (fn(step.value[1], step.value[0], this) === false) { + break; + } + } + return iterations; + */ + // indexed: + var iterator = this.__iterator(ITERATE_VALUES, reverse); + var step; + var iterations = 0; + while (!(step = iterator.next()).done) { + if (fn(step.value, iterations++, this) === false) { + break; + } + } + return iterations; + }; + zipSequence.__iteratorUncached = function(type, reverse) { + var iterators = iters.map(function(i ) + {return (i = Iterable(i), getIterator(reverse ? i.reverse() : i))} + ); + var iterations = 0; + var isDone = false; + return new Iterator(function() { + var steps; + if (!isDone) { + steps = iterators.map(function(i ) {return i.next()}); + isDone = steps.some(function(s ) {return s.done}); + } + if (isDone) { + return iteratorDone(); + } + return iteratorValue( + type, + iterations++, + zipper.apply(null, steps.map(function(s ) {return s.value})) + ); + }); + }; + return zipSequence + } + + + // #pragma Helper Functions + + function reify(iter, seq) { + return isSeq(iter) ? seq : iter.constructor(seq); + } + + function validateEntry(entry) { + if (entry !== Object(entry)) { + throw new TypeError('Expected [K, V] tuple: ' + entry); + } + } + + function resolveSize(iter) { + assertNotInfinite(iter.size); + return ensureSize(iter); + } + + function iterableClass(iterable) { + return isKeyed(iterable) ? KeyedIterable : + isIndexed(iterable) ? IndexedIterable : + SetIterable; + } + + function makeSequence(iterable) { + return Object.create( + ( + isKeyed(iterable) ? KeyedSeq : + isIndexed(iterable) ? IndexedSeq : + SetSeq + ).prototype + ); + } + + function cacheResultThrough() { + if (this._iter.cacheResult) { + this._iter.cacheResult(); + this.size = this._iter.size; + return this; + } else { + return Seq.prototype.cacheResult.call(this); + } + } + + function defaultComparator(a, b) { + return a > b ? 1 : a < b ? -1 : 0; + } + + function forceIterator(keyPath) { + var iter = getIterator(keyPath); + if (!iter) { + // Array might not be iterable in this environment, so we need a fallback + // to our wrapped type. + if (!isArrayLike(keyPath)) { + throw new TypeError('Expected iterable or array-like: ' + keyPath); + } + iter = getIterator(Iterable(keyPath)); + } + return iter; + } + + createClass(Record, KeyedCollection); + + function Record(defaultValues, name) { + var hasInitialized; + + var RecordType = function Record(values) { + if (values instanceof RecordType) { + return values; + } + if (!(this instanceof RecordType)) { + return new RecordType(values); + } + if (!hasInitialized) { + hasInitialized = true; + var keys = Object.keys(defaultValues); + setProps(RecordTypePrototype, keys); + RecordTypePrototype.size = keys.length; + RecordTypePrototype._name = name; + RecordTypePrototype._keys = keys; + RecordTypePrototype._defaultValues = defaultValues; + } + this._map = Map(values); + }; + + var RecordTypePrototype = RecordType.prototype = Object.create(RecordPrototype); + RecordTypePrototype.constructor = RecordType; + + return RecordType; + } + + Record.prototype.toString = function() { + return this.__toString(recordName(this) + ' {', '}'); + }; + + // @pragma Access + + Record.prototype.has = function(k) { + return this._defaultValues.hasOwnProperty(k); + }; + + Record.prototype.get = function(k, notSetValue) { + if (!this.has(k)) { + return notSetValue; + } + var defaultVal = this._defaultValues[k]; + return this._map ? this._map.get(k, defaultVal) : defaultVal; + }; + + // @pragma Modification + + Record.prototype.clear = function() { + if (this.__ownerID) { + this._map && this._map.clear(); + return this; + } + var RecordType = this.constructor; + return RecordType._empty || (RecordType._empty = makeRecord(this, emptyMap())); + }; + + Record.prototype.set = function(k, v) { + if (!this.has(k)) { + throw new Error('Cannot set unknown key "' + k + '" on ' + recordName(this)); + } + if (this._map && !this._map.has(k)) { + var defaultVal = this._defaultValues[k]; + if (v === defaultVal) { + return this; + } + } + var newMap = this._map && this._map.set(k, v); + if (this.__ownerID || newMap === this._map) { + return this; + } + return makeRecord(this, newMap); + }; + + Record.prototype.remove = function(k) { + if (!this.has(k)) { + return this; + } + var newMap = this._map && this._map.remove(k); + if (this.__ownerID || newMap === this._map) { + return this; + } + return makeRecord(this, newMap); + }; + + Record.prototype.wasAltered = function() { + return this._map.wasAltered(); + }; + + Record.prototype.__iterator = function(type, reverse) {var this$0 = this; + return KeyedIterable(this._defaultValues).map(function(_, k) {return this$0.get(k)}).__iterator(type, reverse); + }; + + Record.prototype.__iterate = function(fn, reverse) {var this$0 = this; + return KeyedIterable(this._defaultValues).map(function(_, k) {return this$0.get(k)}).__iterate(fn, reverse); + }; + + Record.prototype.__ensureOwner = function(ownerID) { + if (ownerID === this.__ownerID) { + return this; + } + var newMap = this._map && this._map.__ensureOwner(ownerID); + if (!ownerID) { + this.__ownerID = ownerID; + this._map = newMap; + return this; + } + return makeRecord(this, newMap, ownerID); + }; + + + var RecordPrototype = Record.prototype; + RecordPrototype[DELETE] = RecordPrototype.remove; + RecordPrototype.deleteIn = + RecordPrototype.removeIn = MapPrototype.removeIn; + RecordPrototype.merge = MapPrototype.merge; + RecordPrototype.mergeWith = MapPrototype.mergeWith; + RecordPrototype.mergeIn = MapPrototype.mergeIn; + RecordPrototype.mergeDeep = MapPrototype.mergeDeep; + RecordPrototype.mergeDeepWith = MapPrototype.mergeDeepWith; + RecordPrototype.mergeDeepIn = MapPrototype.mergeDeepIn; + RecordPrototype.setIn = MapPrototype.setIn; + RecordPrototype.update = MapPrototype.update; + RecordPrototype.updateIn = MapPrototype.updateIn; + RecordPrototype.withMutations = MapPrototype.withMutations; + RecordPrototype.asMutable = MapPrototype.asMutable; + RecordPrototype.asImmutable = MapPrototype.asImmutable; + + + function makeRecord(likeRecord, map, ownerID) { + var record = Object.create(Object.getPrototypeOf(likeRecord)); + record._map = map; + record.__ownerID = ownerID; + return record; + } + + function recordName(record) { + return record._name || record.constructor.name || 'Record'; + } + + function setProps(prototype, names) { + try { + names.forEach(setProp.bind(undefined, prototype)); + } catch (error) { + // Object.defineProperty failed. Probably IE8. + } + } + + function setProp(prototype, name) { + Object.defineProperty(prototype, name, { + get: function() { + return this.get(name); + }, + set: function(value) { + invariant(this.__ownerID, 'Cannot set on an immutable record.'); + this.set(name, value); + } + }); + } + + createClass(Set, SetCollection); + + // @pragma Construction + + function Set(value) { + return value === null || value === undefined ? emptySet() : + isSet(value) && !isOrdered(value) ? value : + emptySet().withMutations(function(set ) { + var iter = SetIterable(value); + assertNotInfinite(iter.size); + iter.forEach(function(v ) {return set.add(v)}); + }); + } + + Set.of = function(/*...values*/) { + return this(arguments); + }; + + Set.fromKeys = function(value) { + return this(KeyedIterable(value).keySeq()); + }; + + Set.prototype.toString = function() { + return this.__toString('Set {', '}'); + }; + + // @pragma Access + + Set.prototype.has = function(value) { + return this._map.has(value); + }; + + // @pragma Modification + + Set.prototype.add = function(value) { + return updateSet(this, this._map.set(value, true)); + }; + + Set.prototype.remove = function(value) { + return updateSet(this, this._map.remove(value)); + }; + + Set.prototype.clear = function() { + return updateSet(this, this._map.clear()); + }; + + // @pragma Composition + + Set.prototype.union = function() {var iters = SLICE$0.call(arguments, 0); + iters = iters.filter(function(x ) {return x.size !== 0}); + if (iters.length === 0) { + return this; + } + if (this.size === 0 && !this.__ownerID && iters.length === 1) { + return this.constructor(iters[0]); + } + return this.withMutations(function(set ) { + for (var ii = 0; ii < iters.length; ii++) { + SetIterable(iters[ii]).forEach(function(value ) {return set.add(value)}); + } + }); + }; + + Set.prototype.intersect = function() {var iters = SLICE$0.call(arguments, 0); + if (iters.length === 0) { + return this; + } + iters = iters.map(function(iter ) {return SetIterable(iter)}); + var originalSet = this; + return this.withMutations(function(set ) { + originalSet.forEach(function(value ) { + if (!iters.every(function(iter ) {return iter.includes(value)})) { + set.remove(value); + } + }); + }); + }; + + Set.prototype.subtract = function() {var iters = SLICE$0.call(arguments, 0); + if (iters.length === 0) { + return this; + } + iters = iters.map(function(iter ) {return SetIterable(iter)}); + var originalSet = this; + return this.withMutations(function(set ) { + originalSet.forEach(function(value ) { + if (iters.some(function(iter ) {return iter.includes(value)})) { + set.remove(value); + } + }); + }); + }; + + Set.prototype.merge = function() { + return this.union.apply(this, arguments); + }; + + Set.prototype.mergeWith = function(merger) {var iters = SLICE$0.call(arguments, 1); + return this.union.apply(this, iters); + }; + + Set.prototype.sort = function(comparator) { + // Late binding + return OrderedSet(sortFactory(this, comparator)); + }; + + Set.prototype.sortBy = function(mapper, comparator) { + // Late binding + return OrderedSet(sortFactory(this, comparator, mapper)); + }; + + Set.prototype.wasAltered = function() { + return this._map.wasAltered(); + }; + + Set.prototype.__iterate = function(fn, reverse) {var this$0 = this; + return this._map.__iterate(function(_, k) {return fn(k, k, this$0)}, reverse); + }; + + Set.prototype.__iterator = function(type, reverse) { + return this._map.map(function(_, k) {return k}).__iterator(type, reverse); + }; + + Set.prototype.__ensureOwner = function(ownerID) { + if (ownerID === this.__ownerID) { + return this; + } + var newMap = this._map.__ensureOwner(ownerID); + if (!ownerID) { + this.__ownerID = ownerID; + this._map = newMap; + return this; + } + return this.__make(newMap, ownerID); + }; + + + function isSet(maybeSet) { + return !!(maybeSet && maybeSet[IS_SET_SENTINEL]); + } + + Set.isSet = isSet; + + var IS_SET_SENTINEL = '@@__IMMUTABLE_SET__@@'; + + var SetPrototype = Set.prototype; + SetPrototype[IS_SET_SENTINEL] = true; + SetPrototype[DELETE] = SetPrototype.remove; + SetPrototype.mergeDeep = SetPrototype.merge; + SetPrototype.mergeDeepWith = SetPrototype.mergeWith; + SetPrototype.withMutations = MapPrototype.withMutations; + SetPrototype.asMutable = MapPrototype.asMutable; + SetPrototype.asImmutable = MapPrototype.asImmutable; + + SetPrototype.__empty = emptySet; + SetPrototype.__make = makeSet; + + function updateSet(set, newMap) { + if (set.__ownerID) { + set.size = newMap.size; + set._map = newMap; + return set; + } + return newMap === set._map ? set : + newMap.size === 0 ? set.__empty() : + set.__make(newMap); + } + + function makeSet(map, ownerID) { + var set = Object.create(SetPrototype); + set.size = map ? map.size : 0; + set._map = map; + set.__ownerID = ownerID; + return set; + } + + var EMPTY_SET; + function emptySet() { + return EMPTY_SET || (EMPTY_SET = makeSet(emptyMap())); + } + + createClass(OrderedSet, Set); + + // @pragma Construction + + function OrderedSet(value) { + return value === null || value === undefined ? emptyOrderedSet() : + isOrderedSet(value) ? value : + emptyOrderedSet().withMutations(function(set ) { + var iter = SetIterable(value); + assertNotInfinite(iter.size); + iter.forEach(function(v ) {return set.add(v)}); + }); + } + + OrderedSet.of = function(/*...values*/) { + return this(arguments); + }; + + OrderedSet.fromKeys = function(value) { + return this(KeyedIterable(value).keySeq()); + }; + + OrderedSet.prototype.toString = function() { + return this.__toString('OrderedSet {', '}'); + }; + + + function isOrderedSet(maybeOrderedSet) { + return isSet(maybeOrderedSet) && isOrdered(maybeOrderedSet); + } + + OrderedSet.isOrderedSet = isOrderedSet; + + var OrderedSetPrototype = OrderedSet.prototype; + OrderedSetPrototype[IS_ORDERED_SENTINEL] = true; + + OrderedSetPrototype.__empty = emptyOrderedSet; + OrderedSetPrototype.__make = makeOrderedSet; + + function makeOrderedSet(map, ownerID) { + var set = Object.create(OrderedSetPrototype); + set.size = map ? map.size : 0; + set._map = map; + set.__ownerID = ownerID; + return set; + } + + var EMPTY_ORDERED_SET; + function emptyOrderedSet() { + return EMPTY_ORDERED_SET || (EMPTY_ORDERED_SET = makeOrderedSet(emptyOrderedMap())); + } + + createClass(Stack, IndexedCollection); + + // @pragma Construction + + function Stack(value) { + return value === null || value === undefined ? emptyStack() : + isStack(value) ? value : + emptyStack().unshiftAll(value); + } + + Stack.of = function(/*...values*/) { + return this(arguments); + }; + + Stack.prototype.toString = function() { + return this.__toString('Stack [', ']'); + }; + + // @pragma Access + + Stack.prototype.get = function(index, notSetValue) { + var head = this._head; + index = wrapIndex(this, index); + while (head && index--) { + head = head.next; + } + return head ? head.value : notSetValue; + }; + + Stack.prototype.peek = function() { + return this._head && this._head.value; + }; + + // @pragma Modification + + Stack.prototype.push = function(/*...values*/) { + if (arguments.length === 0) { + return this; + } + var newSize = this.size + arguments.length; + var head = this._head; + for (var ii = arguments.length - 1; ii >= 0; ii--) { + head = { + value: arguments[ii], + next: head + }; + } + if (this.__ownerID) { + this.size = newSize; + this._head = head; + this.__hash = undefined; + this.__altered = true; + return this; + } + return makeStack(newSize, head); + }; + + Stack.prototype.pushAll = function(iter) { + iter = IndexedIterable(iter); + if (iter.size === 0) { + return this; + } + assertNotInfinite(iter.size); + var newSize = this.size; + var head = this._head; + iter.reverse().forEach(function(value ) { + newSize++; + head = { + value: value, + next: head + }; + }); + if (this.__ownerID) { + this.size = newSize; + this._head = head; + this.__hash = undefined; + this.__altered = true; + return this; + } + return makeStack(newSize, head); + }; + + Stack.prototype.pop = function() { + return this.slice(1); + }; + + Stack.prototype.unshift = function(/*...values*/) { + return this.push.apply(this, arguments); + }; + + Stack.prototype.unshiftAll = function(iter) { + return this.pushAll(iter); + }; + + Stack.prototype.shift = function() { + return this.pop.apply(this, arguments); + }; + + Stack.prototype.clear = function() { + if (this.size === 0) { + return this; + } + if (this.__ownerID) { + this.size = 0; + this._head = undefined; + this.__hash = undefined; + this.__altered = true; + return this; + } + return emptyStack(); + }; + + Stack.prototype.slice = function(begin, end) { + if (wholeSlice(begin, end, this.size)) { + return this; + } + var resolvedBegin = resolveBegin(begin, this.size); + var resolvedEnd = resolveEnd(end, this.size); + if (resolvedEnd !== this.size) { + // super.slice(begin, end); + return IndexedCollection.prototype.slice.call(this, begin, end); + } + var newSize = this.size - resolvedBegin; + var head = this._head; + while (resolvedBegin--) { + head = head.next; + } + if (this.__ownerID) { + this.size = newSize; + this._head = head; + this.__hash = undefined; + this.__altered = true; + return this; + } + return makeStack(newSize, head); + }; + + // @pragma Mutability + + Stack.prototype.__ensureOwner = function(ownerID) { + if (ownerID === this.__ownerID) { + return this; + } + if (!ownerID) { + this.__ownerID = ownerID; + this.__altered = false; + return this; + } + return makeStack(this.size, this._head, ownerID, this.__hash); + }; + + // @pragma Iteration + + Stack.prototype.__iterate = function(fn, reverse) { + if (reverse) { + return this.reverse().__iterate(fn); + } + var iterations = 0; + var node = this._head; + while (node) { + if (fn(node.value, iterations++, this) === false) { + break; + } + node = node.next; + } + return iterations; + }; + + Stack.prototype.__iterator = function(type, reverse) { + if (reverse) { + return this.reverse().__iterator(type); + } + var iterations = 0; + var node = this._head; + return new Iterator(function() { + if (node) { + var value = node.value; + node = node.next; + return iteratorValue(type, iterations++, value); + } + return iteratorDone(); + }); + }; + + + function isStack(maybeStack) { + return !!(maybeStack && maybeStack[IS_STACK_SENTINEL]); + } + + Stack.isStack = isStack; + + var IS_STACK_SENTINEL = '@@__IMMUTABLE_STACK__@@'; + + var StackPrototype = Stack.prototype; + StackPrototype[IS_STACK_SENTINEL] = true; + StackPrototype.withMutations = MapPrototype.withMutations; + StackPrototype.asMutable = MapPrototype.asMutable; + StackPrototype.asImmutable = MapPrototype.asImmutable; + StackPrototype.wasAltered = MapPrototype.wasAltered; + + + function makeStack(size, head, ownerID, hash) { + var map = Object.create(StackPrototype); + map.size = size; + map._head = head; + map.__ownerID = ownerID; + map.__hash = hash; + map.__altered = false; + return map; + } + + var EMPTY_STACK; + function emptyStack() { + return EMPTY_STACK || (EMPTY_STACK = makeStack(0)); + } + + /** + * Contributes additional methods to a constructor + */ + function mixin(ctor, methods) { + var keyCopier = function(key ) { ctor.prototype[key] = methods[key]; }; + Object.keys(methods).forEach(keyCopier); + Object.getOwnPropertySymbols && + Object.getOwnPropertySymbols(methods).forEach(keyCopier); + return ctor; + } + + Iterable.Iterator = Iterator; + + mixin(Iterable, { + + // ### Conversion to other types + + toArray: function() { + assertNotInfinite(this.size); + var array = new Array(this.size || 0); + this.valueSeq().__iterate(function(v, i) { array[i] = v; }); + return array; + }, + + toIndexedSeq: function() { + return new ToIndexedSequence(this); + }, + + toJS: function() { + return this.toSeq().map( + function(value ) {return value && typeof value.toJS === 'function' ? value.toJS() : value} + ).__toJS(); + }, + + toJSON: function() { + return this.toSeq().map( + function(value ) {return value && typeof value.toJSON === 'function' ? value.toJSON() : value} + ).__toJS(); + }, + + toKeyedSeq: function() { + return new ToKeyedSequence(this, true); + }, + + toMap: function() { + // Use Late Binding here to solve the circular dependency. + return Map(this.toKeyedSeq()); + }, + + toObject: function() { + assertNotInfinite(this.size); + var object = {}; + this.__iterate(function(v, k) { object[k] = v; }); + return object; + }, + + toOrderedMap: function() { + // Use Late Binding here to solve the circular dependency. + return OrderedMap(this.toKeyedSeq()); + }, + + toOrderedSet: function() { + // Use Late Binding here to solve the circular dependency. + return OrderedSet(isKeyed(this) ? this.valueSeq() : this); + }, + + toSet: function() { + // Use Late Binding here to solve the circular dependency. + return Set(isKeyed(this) ? this.valueSeq() : this); + }, + + toSetSeq: function() { + return new ToSetSequence(this); + }, + + toSeq: function() { + return isIndexed(this) ? this.toIndexedSeq() : + isKeyed(this) ? this.toKeyedSeq() : + this.toSetSeq(); + }, + + toStack: function() { + // Use Late Binding here to solve the circular dependency. + return Stack(isKeyed(this) ? this.valueSeq() : this); + }, + + toList: function() { + // Use Late Binding here to solve the circular dependency. + return List(isKeyed(this) ? this.valueSeq() : this); + }, + + + // ### Common JavaScript methods and properties + + toString: function() { + return '[Iterable]'; + }, + + __toString: function(head, tail) { + if (this.size === 0) { + return head + tail; + } + return head + ' ' + this.toSeq().map(this.__toStringMapper).join(', ') + ' ' + tail; + }, + + + // ### ES6 Collection methods (ES6 Array and Map) + + concat: function() {var values = SLICE$0.call(arguments, 0); + return reify(this, concatFactory(this, values)); + }, + + includes: function(searchValue) { + return this.some(function(value ) {return is(value, searchValue)}); + }, + + entries: function() { + return this.__iterator(ITERATE_ENTRIES); + }, + + every: function(predicate, context) { + assertNotInfinite(this.size); + var returnValue = true; + this.__iterate(function(v, k, c) { + if (!predicate.call(context, v, k, c)) { + returnValue = false; + return false; + } + }); + return returnValue; + }, + + filter: function(predicate, context) { + return reify(this, filterFactory(this, predicate, context, true)); + }, + + find: function(predicate, context, notSetValue) { + var entry = this.findEntry(predicate, context); + return entry ? entry[1] : notSetValue; + }, + + forEach: function(sideEffect, context) { + assertNotInfinite(this.size); + return this.__iterate(context ? sideEffect.bind(context) : sideEffect); + }, + + join: function(separator) { + assertNotInfinite(this.size); + separator = separator !== undefined ? '' + separator : ','; + var joined = ''; + var isFirst = true; + this.__iterate(function(v ) { + isFirst ? (isFirst = false) : (joined += separator); + joined += v !== null && v !== undefined ? v.toString() : ''; + }); + return joined; + }, + + keys: function() { + return this.__iterator(ITERATE_KEYS); + }, + + map: function(mapper, context) { + return reify(this, mapFactory(this, mapper, context)); + }, + + reduce: function(reducer, initialReduction, context) { + assertNotInfinite(this.size); + var reduction; + var useFirst; + if (arguments.length < 2) { + useFirst = true; + } else { + reduction = initialReduction; + } + this.__iterate(function(v, k, c) { + if (useFirst) { + useFirst = false; + reduction = v; + } else { + reduction = reducer.call(context, reduction, v, k, c); + } + }); + return reduction; + }, + + reduceRight: function(reducer, initialReduction, context) { + var reversed = this.toKeyedSeq().reverse(); + return reversed.reduce.apply(reversed, arguments); + }, + + reverse: function() { + return reify(this, reverseFactory(this, true)); + }, + + slice: function(begin, end) { + return reify(this, sliceFactory(this, begin, end, true)); + }, + + some: function(predicate, context) { + return !this.every(not(predicate), context); + }, + + sort: function(comparator) { + return reify(this, sortFactory(this, comparator)); + }, + + values: function() { + return this.__iterator(ITERATE_VALUES); + }, + + + // ### More sequential methods + + butLast: function() { + return this.slice(0, -1); + }, + + isEmpty: function() { + return this.size !== undefined ? this.size === 0 : !this.some(function() {return true}); + }, + + count: function(predicate, context) { + return ensureSize( + predicate ? this.toSeq().filter(predicate, context) : this + ); + }, + + countBy: function(grouper, context) { + return countByFactory(this, grouper, context); + }, + + equals: function(other) { + return deepEqual(this, other); + }, + + entrySeq: function() { + var iterable = this; + if (iterable._cache) { + // We cache as an entries array, so we can just return the cache! + return new ArraySeq(iterable._cache); + } + var entriesSequence = iterable.toSeq().map(entryMapper).toIndexedSeq(); + entriesSequence.fromEntrySeq = function() {return iterable.toSeq()}; + return entriesSequence; + }, + + filterNot: function(predicate, context) { + return this.filter(not(predicate), context); + }, + + findEntry: function(predicate, context, notSetValue) { + var found = notSetValue; + this.__iterate(function(v, k, c) { + if (predicate.call(context, v, k, c)) { + found = [k, v]; + return false; + } + }); + return found; + }, + + findKey: function(predicate, context) { + var entry = this.findEntry(predicate, context); + return entry && entry[0]; + }, + + findLast: function(predicate, context, notSetValue) { + return this.toKeyedSeq().reverse().find(predicate, context, notSetValue); + }, + + findLastEntry: function(predicate, context, notSetValue) { + return this.toKeyedSeq().reverse().findEntry(predicate, context, notSetValue); + }, + + findLastKey: function(predicate, context) { + return this.toKeyedSeq().reverse().findKey(predicate, context); + }, + + first: function() { + return this.find(returnTrue); + }, + + flatMap: function(mapper, context) { + return reify(this, flatMapFactory(this, mapper, context)); + }, + + flatten: function(depth) { + return reify(this, flattenFactory(this, depth, true)); + }, + + fromEntrySeq: function() { + return new FromEntriesSequence(this); + }, + + get: function(searchKey, notSetValue) { + return this.find(function(_, key) {return is(key, searchKey)}, undefined, notSetValue); + }, + + getIn: function(searchKeyPath, notSetValue) { + var nested = this; + // Note: in an ES6 environment, we would prefer: + // for (var key of searchKeyPath) { + var iter = forceIterator(searchKeyPath); + var step; + while (!(step = iter.next()).done) { + var key = step.value; + nested = nested && nested.get ? nested.get(key, NOT_SET) : NOT_SET; + if (nested === NOT_SET) { + return notSetValue; + } + } + return nested; + }, + + groupBy: function(grouper, context) { + return groupByFactory(this, grouper, context); + }, + + has: function(searchKey) { + return this.get(searchKey, NOT_SET) !== NOT_SET; + }, + + hasIn: function(searchKeyPath) { + return this.getIn(searchKeyPath, NOT_SET) !== NOT_SET; + }, + + isSubset: function(iter) { + iter = typeof iter.includes === 'function' ? iter : Iterable(iter); + return this.every(function(value ) {return iter.includes(value)}); + }, + + isSuperset: function(iter) { + iter = typeof iter.isSubset === 'function' ? iter : Iterable(iter); + return iter.isSubset(this); + }, + + keyOf: function(searchValue) { + return this.findKey(function(value ) {return is(value, searchValue)}); + }, + + keySeq: function() { + return this.toSeq().map(keyMapper).toIndexedSeq(); + }, + + last: function() { + return this.toSeq().reverse().first(); + }, + + lastKeyOf: function(searchValue) { + return this.toKeyedSeq().reverse().keyOf(searchValue); + }, + + max: function(comparator) { + return maxFactory(this, comparator); + }, + + maxBy: function(mapper, comparator) { + return maxFactory(this, comparator, mapper); + }, + + min: function(comparator) { + return maxFactory(this, comparator ? neg(comparator) : defaultNegComparator); + }, + + minBy: function(mapper, comparator) { + return maxFactory(this, comparator ? neg(comparator) : defaultNegComparator, mapper); + }, + + rest: function() { + return this.slice(1); + }, + + skip: function(amount) { + return this.slice(Math.max(0, amount)); + }, + + skipLast: function(amount) { + return reify(this, this.toSeq().reverse().skip(amount).reverse()); + }, + + skipWhile: function(predicate, context) { + return reify(this, skipWhileFactory(this, predicate, context, true)); + }, + + skipUntil: function(predicate, context) { + return this.skipWhile(not(predicate), context); + }, + + sortBy: function(mapper, comparator) { + return reify(this, sortFactory(this, comparator, mapper)); + }, + + take: function(amount) { + return this.slice(0, Math.max(0, amount)); + }, + + takeLast: function(amount) { + return reify(this, this.toSeq().reverse().take(amount).reverse()); + }, + + takeWhile: function(predicate, context) { + return reify(this, takeWhileFactory(this, predicate, context)); + }, + + takeUntil: function(predicate, context) { + return this.takeWhile(not(predicate), context); + }, + + valueSeq: function() { + return this.toIndexedSeq(); + }, + + + // ### Hashable Object + + hashCode: function() { + return this.__hash || (this.__hash = hashIterable(this)); + } + + + // ### Internal + + // abstract __iterate(fn, reverse) + + // abstract __iterator(type, reverse) + }); + + // var IS_ITERABLE_SENTINEL = '@@__IMMUTABLE_ITERABLE__@@'; + // var IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@'; + // var IS_INDEXED_SENTINEL = '@@__IMMUTABLE_INDEXED__@@'; + // var IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@'; + + var IterablePrototype = Iterable.prototype; + IterablePrototype[IS_ITERABLE_SENTINEL] = true; + IterablePrototype[ITERATOR_SYMBOL] = IterablePrototype.values; + IterablePrototype.__toJS = IterablePrototype.toArray; + IterablePrototype.__toStringMapper = quoteString; + IterablePrototype.inspect = + IterablePrototype.toSource = function() { return this.toString(); }; + IterablePrototype.chain = IterablePrototype.flatMap; + IterablePrototype.contains = IterablePrototype.includes; + + mixin(KeyedIterable, { + + // ### More sequential methods + + flip: function() { + return reify(this, flipFactory(this)); + }, + + mapEntries: function(mapper, context) {var this$0 = this; + var iterations = 0; + return reify(this, + this.toSeq().map( + function(v, k) {return mapper.call(context, [k, v], iterations++, this$0)} + ).fromEntrySeq() + ); + }, + + mapKeys: function(mapper, context) {var this$0 = this; + return reify(this, + this.toSeq().flip().map( + function(k, v) {return mapper.call(context, k, v, this$0)} + ).flip() + ); + } + + }); + + var KeyedIterablePrototype = KeyedIterable.prototype; + KeyedIterablePrototype[IS_KEYED_SENTINEL] = true; + KeyedIterablePrototype[ITERATOR_SYMBOL] = IterablePrototype.entries; + KeyedIterablePrototype.__toJS = IterablePrototype.toObject; + KeyedIterablePrototype.__toStringMapper = function(v, k) {return JSON.stringify(k) + ': ' + quoteString(v)}; + + + + mixin(IndexedIterable, { + + // ### Conversion to other types + + toKeyedSeq: function() { + return new ToKeyedSequence(this, false); + }, + + + // ### ES6 Collection methods (ES6 Array and Map) + + filter: function(predicate, context) { + return reify(this, filterFactory(this, predicate, context, false)); + }, + + findIndex: function(predicate, context) { + var entry = this.findEntry(predicate, context); + return entry ? entry[0] : -1; + }, + + indexOf: function(searchValue) { + var key = this.keyOf(searchValue); + return key === undefined ? -1 : key; + }, + + lastIndexOf: function(searchValue) { + var key = this.lastKeyOf(searchValue); + return key === undefined ? -1 : key; + }, + + reverse: function() { + return reify(this, reverseFactory(this, false)); + }, + + slice: function(begin, end) { + return reify(this, sliceFactory(this, begin, end, false)); + }, + + splice: function(index, removeNum /*, ...values*/) { + var numArgs = arguments.length; + removeNum = Math.max(removeNum | 0, 0); + if (numArgs === 0 || (numArgs === 2 && !removeNum)) { + return this; + } + // If index is negative, it should resolve relative to the size of the + // collection. However size may be expensive to compute if not cached, so + // only call count() if the number is in fact negative. + index = resolveBegin(index, index < 0 ? this.count() : this.size); + var spliced = this.slice(0, index); + return reify( + this, + numArgs === 1 ? + spliced : + spliced.concat(arrCopy(arguments, 2), this.slice(index + removeNum)) + ); + }, + + + // ### More collection methods + + findLastIndex: function(predicate, context) { + var entry = this.findLastEntry(predicate, context); + return entry ? entry[0] : -1; + }, + + first: function() { + return this.get(0); + }, + + flatten: function(depth) { + return reify(this, flattenFactory(this, depth, false)); + }, + + get: function(index, notSetValue) { + index = wrapIndex(this, index); + return (index < 0 || (this.size === Infinity || + (this.size !== undefined && index > this.size))) ? + notSetValue : + this.find(function(_, key) {return key === index}, undefined, notSetValue); + }, + + has: function(index) { + index = wrapIndex(this, index); + return index >= 0 && (this.size !== undefined ? + this.size === Infinity || index < this.size : + this.indexOf(index) !== -1 + ); + }, + + interpose: function(separator) { + return reify(this, interposeFactory(this, separator)); + }, + + interleave: function(/*...iterables*/) { + var iterables = [this].concat(arrCopy(arguments)); + var zipped = zipWithFactory(this.toSeq(), IndexedSeq.of, iterables); + var interleaved = zipped.flatten(true); + if (zipped.size) { + interleaved.size = zipped.size * iterables.length; + } + return reify(this, interleaved); + }, + + keySeq: function() { + return Range(0, this.size); + }, + + last: function() { + return this.get(-1); + }, + + skipWhile: function(predicate, context) { + return reify(this, skipWhileFactory(this, predicate, context, false)); + }, + + zip: function(/*, ...iterables */) { + var iterables = [this].concat(arrCopy(arguments)); + return reify(this, zipWithFactory(this, defaultZipper, iterables)); + }, + + zipWith: function(zipper/*, ...iterables */) { + var iterables = arrCopy(arguments); + iterables[0] = this; + return reify(this, zipWithFactory(this, zipper, iterables)); + } + + }); + + IndexedIterable.prototype[IS_INDEXED_SENTINEL] = true; + IndexedIterable.prototype[IS_ORDERED_SENTINEL] = true; + + + + mixin(SetIterable, { + + // ### ES6 Collection methods (ES6 Array and Map) + + get: function(value, notSetValue) { + return this.has(value) ? value : notSetValue; + }, + + includes: function(value) { + return this.has(value); + }, + + + // ### More sequential methods + + keySeq: function() { + return this.valueSeq(); + } + + }); + + SetIterable.prototype.has = IterablePrototype.includes; + SetIterable.prototype.contains = SetIterable.prototype.includes; + + + // Mixin subclasses + + mixin(KeyedSeq, KeyedIterable.prototype); + mixin(IndexedSeq, IndexedIterable.prototype); + mixin(SetSeq, SetIterable.prototype); + + mixin(KeyedCollection, KeyedIterable.prototype); + mixin(IndexedCollection, IndexedIterable.prototype); + mixin(SetCollection, SetIterable.prototype); + + + // #pragma Helper functions + + function keyMapper(v, k) { + return k; + } + + function entryMapper(v, k) { + return [k, v]; + } + + function not(predicate) { + return function() { + return !predicate.apply(this, arguments); + } + } + + function neg(predicate) { + return function() { + return -predicate.apply(this, arguments); + } + } + + function quoteString(value) { + return typeof value === 'string' ? JSON.stringify(value) : String(value); + } + + function defaultZipper() { + return arrCopy(arguments); + } + + function defaultNegComparator(a, b) { + return a < b ? 1 : a > b ? -1 : 0; + } + + function hashIterable(iterable) { + if (iterable.size === Infinity) { + return 0; + } + var ordered = isOrdered(iterable); + var keyed = isKeyed(iterable); + var h = ordered ? 1 : 0; + var size = iterable.__iterate( + keyed ? + ordered ? + function(v, k) { h = 31 * h + hashMerge(hash(v), hash(k)) | 0; } : + function(v, k) { h = h + hashMerge(hash(v), hash(k)) | 0; } : + ordered ? + function(v ) { h = 31 * h + hash(v) | 0; } : + function(v ) { h = h + hash(v) | 0; } + ); + return murmurHashOfSize(size, h); + } + + function murmurHashOfSize(size, h) { + h = imul(h, 0xCC9E2D51); + h = imul(h << 15 | h >>> -15, 0x1B873593); + h = imul(h << 13 | h >>> -13, 5); + h = (h + 0xE6546B64 | 0) ^ size; + h = imul(h ^ h >>> 16, 0x85EBCA6B); + h = imul(h ^ h >>> 13, 0xC2B2AE35); + h = smi(h ^ h >>> 16); + return h; + } + + function hashMerge(a, b) { + return a ^ b + 0x9E3779B9 + (a << 6) + (a >> 2) | 0; // int + } + + var Immutable = { + + Iterable: Iterable, + + Seq: Seq, + Collection: Collection, + Map: Map, + OrderedMap: OrderedMap, + List: List, + Stack: Stack, + Set: Set, + OrderedSet: OrderedSet, + + Record: Record, + Range: Range, + Repeat: Repeat, + + is: is, + fromJS: fromJS + + }; + + return Immutable; + + })); + +/***/ }, +/* 230 */ +/***/ function(module, exports, __webpack_require__) { + + var Immutable = __webpack_require__(229); + + // When our app state is fully types, we should be able to get rid of + // this function. This is only temporarily necessary to support + // converting typed objects to immutable.js, which usually happens in + // reducers. + function fromJS(value) { + if (Array.isArray(value)) { + return Immutable.Seq(value).map(fromJS).toList(); + } + if (value && value.constructor.meta) { + // This adds support for tcomb objects which are native JS objects + // but are not "plain", so the above checks fail. Since they + // behave the same we can use the same constructors, but we need + // special checks for them. + var kind = value.constructor.meta.kind; + if (kind === "struct") { + return Immutable.Seq(value).map(fromJS).toMap(); + } else if (kind === "list") { + return Immutable.Seq(value).map(fromJS).toList(); + } + } + + // If it's a primitive type, just return the value. Note `==` check + // for null, which is intentionally used to match either `null` or + // `undefined`. + if (value == null || typeof value !== "object") { + return value; + } + + // Otherwise, treat it like an object. We can't reliably detect if + // it's a plain object because we might be objects from other JS + // contexts so `Object !== Object`. + return Immutable.Seq(value).map(fromJS).toMap(); + } + + module.exports = fromJS; + +/***/ }, +/* 231 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + + var _require = __webpack_require__(19); + + var connect = _require.connect; + + var classnames = __webpack_require__(211); + + var _require2 = __webpack_require__(232); + + var getTabs = _require2.getTabs; + + + __webpack_require__(233); + var dom = React.DOM; + + var ImPropTypes = __webpack_require__(235); + + var githubUrl = "https://github.com/devtools-html/debugger.html/blob/master"; + + function getTabsByBrowser(tabs, browser) { + return tabs.valueSeq().filter(tab => tab.get("browser") == browser); + } + + function firstTimeMessage(title, urlPart) { + return dom.div({ className: "footer-note" }, `First time connecting to ${ title }? Checkout out the `, dom.a({ href: `${ githubUrl }/CONTRIBUTING.md#${ urlPart }` }, "docs"), "."); + } + + var LandingPage = React.createClass({ + propTypes: { + tabs: ImPropTypes.map.isRequired + }, + + displayName: "LandingPage", + + getInitialState() { + return { + selectedPane: "Firefox" + }; + }, + + renderTabs(tabTitle, tabs, paramName) { + if (!tabs || tabs.count() == 0) { + return dom.div({}, ""); + } + + return dom.div({ className: "tab-group" }, dom.ul({ className: "tab-list" }, tabs.valueSeq().map(tab => dom.li({ "className": "tab", + "key": tab.get("id"), + "onClick": () => { + window.location = "/?" + paramName + "=" + tab.get("id"); + } }, dom.div({ className: "tab-title" }, tab.get("title")), dom.div({ className: "tab-url" }, tab.get("url")))))); + }, + + renderFirefoxPanel() { + var targets = getTabsByBrowser(this.props.tabs, "firefox"); + return dom.div({ className: "center" }, this.renderTabs("", targets, "firefox-tab"), firstTimeMessage("Firefox", "firefox")); + }, + + renderChromePanel() { + var targets = getTabsByBrowser(this.props.tabs, "chrome"); + return dom.div({ className: "center" }, this.renderTabs("", targets, "chrome-tab"), firstTimeMessage("Chrome", "chrome")); + }, + + renderNodePanel() { + return dom.div({ className: "center" }, dom.div({ className: "center-message" }, dom.a({ + href: `/?ws=${ document.location.hostname }:9229/node` + }, "Connect to Node")), firstTimeMessage("Node", "nodejs")); + }, + + renderPanel() { + var panels = { + Firefox: this.renderFirefoxPanel, + Chrome: this.renderChromePanel, + Node: this.renderNodePanel + }; + + return dom.div({ + className: "panel" + }, dom.div({ className: "title" }, dom.h2({}, this.state.selectedPane)), panels[this.state.selectedPane]()); + }, + + renderSidebar() { + return dom.div({ + className: "sidebar" + }, dom.h1({}, "Debugger"), dom.ul({}, ["Firefox", "Chrome", "Node"].map(title => dom.li({ + className: classnames({ + selected: title == this.state.selectedPane + }), + key: title, + + onClick: () => this.setState({ selectedPane: title }) + }, dom.a({}, title))))); + }, + + render() { + return dom.div({ + className: "landing-page" + }, this.renderSidebar(), this.renderPanel()); + } + }); + + module.exports = connect(state => ({ tabs: getTabs(state) }))(LandingPage); + +/***/ }, +/* 232 */ +/***/ function(module, exports) { + + function getTabs(state) { + return state.tabs.get("tabs"); + } + + function getSelectedTab(state) { + return state.tabs.get("selectedTab"); + } + + module.exports = { + getTabs, + getSelectedTab + }; + +/***/ }, +/* 233 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 234 */, +/* 235 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * This is a straight rip-off of the React.js ReactPropTypes.js proptype validators, + * modified to make it possible to validate Immutable.js data. + * ImmutableTypes.listOf is patterned after React.PropTypes.arrayOf, but for Immutable.List + * ImmutableTypes.shape is based on React.PropTypes.shape, but for any Immutable.Iterable + */ + "use strict"; + + var Immutable = __webpack_require__(229); + + var ANONYMOUS = "<<anonymous>>"; + + var ImmutablePropTypes = { + listOf: createListOfTypeChecker, + mapOf: createMapOfTypeChecker, + orderedMapOf: createOrderedMapOfTypeChecker, + setOf: createSetOfTypeChecker, + orderedSetOf: createOrderedSetOfTypeChecker, + stackOf: createStackOfTypeChecker, + iterableOf: createIterableOfTypeChecker, + recordOf: createRecordOfTypeChecker, + shape: createShapeChecker, + contains: createShapeChecker, + mapContains: createMapContainsChecker, + // Primitive Types + list: createImmutableTypeChecker("List", Immutable.List.isList), + map: createImmutableTypeChecker("Map", Immutable.Map.isMap), + orderedMap: createImmutableTypeChecker("OrderedMap", Immutable.OrderedMap.isOrderedMap), + set: createImmutableTypeChecker("Set", Immutable.Set.isSet), + orderedSet: createImmutableTypeChecker("OrderedSet", Immutable.OrderedSet.isOrderedSet), + stack: createImmutableTypeChecker("Stack", Immutable.Stack.isStack), + seq: createImmutableTypeChecker("Seq", Immutable.Seq.isSeq), + record: createImmutableTypeChecker("Record", function (isRecord) { + return isRecord instanceof Immutable.Record; + }), + iterable: createImmutableTypeChecker("Iterable", Immutable.Iterable.isIterable) + }; + + function getPropType(propValue) { + var propType = typeof propValue; + if (Array.isArray(propValue)) { + return "array"; + } + if (propValue instanceof RegExp) { + // Old webkits (at least until Android 4.0) return 'function' rather than + // 'object' for typeof a RegExp. We'll normalize this here so that /bla/ + // passes PropTypes.object. + return "object"; + } + if (propValue instanceof Immutable.Iterable) { + return "Immutable." + propValue.toSource().split(" ")[0]; + } + return propType; + } + + function createChainableTypeChecker(validate) { + function checkType(isRequired, props, propName, componentName, location, propFullName) { + propFullName = propFullName || propName; + componentName = componentName || ANONYMOUS; + if (props[propName] == null) { + var locationName = location; + if (isRequired) { + return new Error("Required " + locationName + " `" + propFullName + "` was not specified in " + ("`" + componentName + "`.")); + } + } else { + return validate(props, propName, componentName, location, propFullName); + } + } + + var chainedCheckType = checkType.bind(null, false); + chainedCheckType.isRequired = checkType.bind(null, true); + + return chainedCheckType; + } + + function createImmutableTypeChecker(immutableClassName, immutableClassTypeValidator) { + function validate(props, propName, componentName, location, propFullName) { + var propValue = props[propName]; + if (!immutableClassTypeValidator(propValue)) { + var propType = getPropType(propValue); + return new Error("Invalid " + location + " `" + propFullName + "` of type `" + propType + "` " + ("supplied to `" + componentName + "`, expected `" + immutableClassName + "`.")); + } + return null; + } + return createChainableTypeChecker(validate); + } + + function createIterableTypeChecker(typeChecker, immutableClassName, immutableClassTypeValidator) { + + function validate(props, propName, componentName, location, propFullName) { + var propValue = props[propName]; + if (!immutableClassTypeValidator(propValue)) { + var locationName = location; + var propType = getPropType(propValue); + return new Error("Invalid " + locationName + " `" + propFullName + "` of type " + ("`" + propType + "` supplied to `" + componentName + "`, expected an Immutable.js " + immutableClassName + ".")); + } + + if (typeof typeChecker !== "function") { + return new Error("Invalid typeChecker supplied to `" + componentName + "` " + ("for propType `" + propFullName + "`, expected a function.")); + } + + var propValues = propValue.toArray(); + for (var i = 0, len = propValues.length; i < len; i++) { + var error = typeChecker(propValues, i, componentName, location, "" + propFullName + "[" + i + "]"); + if (error instanceof Error) { + return error; + } + } + } + return createChainableTypeChecker(validate); + } + + function createListOfTypeChecker(typeChecker) { + return createIterableTypeChecker(typeChecker, "List", Immutable.List.isList); + } + + function createMapOfTypeChecker(typeChecker) { + return createIterableTypeChecker(typeChecker, "Map", Immutable.Map.isMap); + } + + function createOrderedMapOfTypeChecker(typeChecker) { + return createIterableTypeChecker(typeChecker, "OrderedMap", Immutable.OrderedMap.isOrderedMap); + } + + function createSetOfTypeChecker(typeChecker) { + return createIterableTypeChecker(typeChecker, "Set", Immutable.Set.isSet); + } + + function createOrderedSetOfTypeChecker(typeChecker) { + return createIterableTypeChecker(typeChecker, "OrderedSet", Immutable.OrderedSet.isOrderedSet); + } + + function createStackOfTypeChecker(typeChecker) { + return createIterableTypeChecker(typeChecker, "Stack", Immutable.Stack.isStack); + } + + function createIterableOfTypeChecker(typeChecker) { + return createIterableTypeChecker(typeChecker, "Iterable", Immutable.Iterable.isIterable); + } + + function createRecordOfTypeChecker(recordKeys) { + function validate(props, propName, componentName, location, propFullName) { + var propValue = props[propName]; + if (!(propValue instanceof Immutable.Record)) { + var propType = getPropType(propValue); + var locationName = location; + return new Error("Invalid " + locationName + " `" + propFullName + "` of type `" + propType + "` " + ("supplied to `" + componentName + "`, expected an Immutable.js Record.")); + } + for (var key in recordKeys) { + var checker = recordKeys[key]; + if (!checker) { + continue; + } + var mutablePropValue = propValue.toObject(); + var error = checker(mutablePropValue, key, componentName, location, "" + propFullName + "." + key); + if (error) { + return error; + } + } + } + return createChainableTypeChecker(validate); + } + + // there is some irony in the fact that shapeTypes is a standard hash and not an immutable collection + function createShapeTypeChecker(shapeTypes) { + var immutableClassName = arguments[1] === undefined ? "Iterable" : arguments[1]; + var immutableClassTypeValidator = arguments[2] === undefined ? Immutable.Iterable.isIterable : arguments[2]; + + function validate(props, propName, componentName, location, propFullName) { + var propValue = props[propName]; + if (!immutableClassTypeValidator(propValue)) { + var propType = getPropType(propValue); + var locationName = location; + return new Error("Invalid " + locationName + " `" + propFullName + "` of type `" + propType + "` " + ("supplied to `" + componentName + "`, expected an Immutable.js " + immutableClassName + ".")); + } + var mutablePropValue = propValue.toObject(); + for (var key in shapeTypes) { + var checker = shapeTypes[key]; + if (!checker) { + continue; + } + var error = checker(mutablePropValue, key, componentName, location, "" + propFullName + "." + key); + if (error) { + return error; + } + } + } + return createChainableTypeChecker(validate); + } + + function createShapeChecker(shapeTypes) { + return createShapeTypeChecker(shapeTypes); + } + + function createMapContainsChecker(shapeTypes) { + return createShapeTypeChecker(shapeTypes, "Map", Immutable.Map.isMap); + } + + module.exports = ImmutablePropTypes; + +/***/ }, +/* 236 */ +/***/ function(module, exports, __webpack_require__) { + + + var tabs = __webpack_require__(237); + + module.exports = Object.assign({}, tabs); + +/***/ }, +/* 237 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + /* global window */ + + /** + * Redux actions for the pause state + * @module actions/tabs + */ + + var constants = __webpack_require__(228); + + /** + * @typedef {Object} TabAction + * @memberof actions/tabs + * @static + * @property {number} type The type of Action + * @property {number} value The payload of the Action + */ + + /** + * @memberof actions/tabs + * @static + * @param {Array} tabs + * @returns {TabAction} with type constants.ADD_TABS and tabs as value + */ + function newTabs(tabs) { + return { + type: constants.ADD_TABS, + value: tabs + }; + } + + /** + * @memberof actions/tabs + * @static + * @param {String} $0.id Unique ID of the tab to select + * @returns {TabAction} + */ + function selectTab(_ref) { + var id = _ref.id; + + return { + type: constants.SELECT_TAB, + id: id + }; + } + + module.exports = { + newTabs, + selectTab + }; + +/***/ }, +/* 238 */ +/***/ function(module, exports, __webpack_require__) { + + + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + /* global window */ + + /** + * Redux store utils + * @module utils/create-store + */ + + var _require = __webpack_require__(3); + + var createStore = _require.createStore; + var applyMiddleware = _require.applyMiddleware; + + var _require2 = __webpack_require__(239); + + var waitUntilService = _require2.waitUntilService; + + var _require3 = __webpack_require__(240); + + var log = _require3.log; + + var _require4 = __webpack_require__(241); + + var history = _require4.history; + + var _require5 = __webpack_require__(242); + + var promise = _require5.promise; + + var _require6 = __webpack_require__(248); + + var thunk = _require6.thunk; + + /** + * @memberof utils/create-store + * @static + */ + + /** + * This creates a dispatcher with all the standard middleware in place + * that all code requires. It can also be optionally configured in + * various ways, such as logging and recording. + * + * @param {object} opts: + * - log: log all dispatched actions to console + * - history: an array to store every action in. Should only be + * used in tests. + * - middleware: array of middleware to be included in the redux store + * @memberof utils/create-store + * @static + */ + var configureStore = function () { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + var middleware = [thunk(opts.makeThunkArgs), promise, + + // Order is important: services must go last as they always + // operate on "already transformed" actions. Actions going through + // them shouldn't have any special fields like promises, they + // should just be normal JSON objects. + waitUntilService]; + + if (opts.history) { + middleware.push(history(opts.history)); + } + + if (opts.middleware) { + opts.middleware.forEach(fn => middleware.push(fn)); + } + + if (opts.log) { + middleware.push(log); + } + + // Hook in the redux devtools browser extension if it exists + var devtoolsExt = typeof window === "object" && window.devToolsExtension ? window.devToolsExtension() : f => f; + + return applyMiddleware.apply(undefined, middleware)(devtoolsExt(createStore)); + }; + + module.exports = configureStore; + +/***/ }, +/* 239 */ +/***/ function(module, exports) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + /** + * A middleware which acts like a service, because it is stateful + * and "long-running" in the background. It provides the ability + * for actions to install a function to be run once when a specific + * condition is met by an action coming through the system. Think of + * it as a thunk that blocks until the condition is met. Example: + * + * ```js + * const services = { WAIT_UNTIL: require('wait-service').NAME }; + * + * { type: services.WAIT_UNTIL, + * predicate: action => action.type === constants.ADD_ITEM, + * run: (dispatch, getState, action) => { + * // Do anything here. You only need to accept the arguments + * // if you need them. `action` is the action that satisfied + * // the predicate. + * } + * } + * ``` + */ + var NAME = exports.NAME = "@@service/waitUntil"; + + function waitUntilService(_ref) { + var dispatch = _ref.dispatch; + var getState = _ref.getState; + + var pending = []; + + function checkPending(action) { + var readyRequests = []; + var stillPending = []; + + // Find the pending requests whose predicates are satisfied with + // this action. Wait to run the requests until after we update the + // pending queue because the request handler may synchronously + // dispatch again and run this service (that use case is + // completely valid). + for (var request of pending) { + if (request.predicate(action)) { + readyRequests.push(request); + } else { + stillPending.push(request); + } + } + + pending = stillPending; + for (var _request of readyRequests) { + _request.run(dispatch, getState, action); + } + } + + return next => action => { + if (action.type === NAME) { + pending.push(action); + return null; + } + var result = next(action); + checkPending(action); + return result; + }; + } + exports.waitUntilService = waitUntilService; + +/***/ }, +/* 240 */ +/***/ function(module, exports) { + + /** + * A middleware that logs all actions coming through the system + * to the console. + */ + function log(_ref) { + var dispatch = _ref.dispatch; + var getState = _ref.getState; + + return next => action => { + var actionText = JSON.stringify(action, null, 2); + var truncatedActionText = actionText.slice(0, 1000) + "..."; + console.log(`[DISPATCH ${ action.type }]`, action, truncatedActionText); + next(action); + }; + } + + exports.log = log; + +/***/ }, +/* 241 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var _require = __webpack_require__(89); + + var isDevelopment = _require.isDevelopment; + + /** + * A middleware that stores every action coming through the store in the passed + * in logging object. Should only be used for tests, as it collects all + * action information, which will cause memory bloat. + */ + + exports.history = function () { + var log = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + return (_ref) => { + var dispatch = _ref.dispatch; + var getState = _ref.getState; + + if (isDevelopment()) { + console.warn("Using history middleware stores all actions in state for " + "testing and devtools is not currently running in test " + "mode. Be sure this is intentional."); + } + return next => action => { + log.push(action); + next(action); + }; + }; + }; + +/***/ }, +/* 242 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var defer = __webpack_require__(243); + + var _require = __webpack_require__(244); + + var entries = _require.entries; + var toObject = _require.toObject; + + var _require2 = __webpack_require__(246); + + var executeSoon = _require2.executeSoon; + + + var PROMISE = exports.PROMISE = "@@dispatch/promise"; + var seqIdVal = 1; + + function seqIdGen() { + return seqIdVal++; + } + + function promiseMiddleware(_ref) { + var dispatch = _ref.dispatch; + var getState = _ref.getState; + + return next => action => { + if (!(PROMISE in action)) { + return next(action); + } + + var promiseInst = action[PROMISE]; + var seqId = seqIdGen().toString(); + + // Create a new action that doesn't have the promise field and has + // the `seqId` field that represents the sequence id + action = Object.assign(toObject(entries(action).filter(pair => pair[0] !== PROMISE)), { seqId }); + + dispatch(Object.assign({}, action, { status: "start" })); + + // Return the promise so action creators can still compose if they + // want to. + var deferred = defer(); + promiseInst.then(value => { + executeSoon(() => { + dispatch(Object.assign({}, action, { + status: "done", + value: value + })); + deferred.resolve(value); + }); + }, error => { + executeSoon(() => { + dispatch(Object.assign({}, action, { + status: "error", + error: error.message || error + })); + deferred.reject(error); + }); + }); + return deferred.promise; + }; + } + + exports.promise = promiseMiddleware; + +/***/ }, +/* 243 */ +/***/ function(module, exports) { + + + + function defer() { + var resolve = void 0; + var reject = void 0; + var promise = new Promise(function (innerResolve, innerReject) { + resolve = innerResolve; + reject = innerReject; + }); + return { + resolve: resolve, + reject: reject, + promise: promise + }; + } /* flow */ + + module.exports = defer; + +/***/ }, +/* 244 */ +/***/ function(module, exports, __webpack_require__) { + + var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + + function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + + /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + /** + * Utils for utils, by utils + * @module utils/utils + */ + + var co = __webpack_require__(245); + + /** + * @memberof utils/utils + * @static + */ + function asPaused(client, func) { + if (client.state != "paused") { + return co(function* () { + yield client.interrupt(); + var result = void 0; + + try { + result = yield func(); + } catch (e) { + // Try to put the debugger back in a working state by resuming + // it + yield client.resume(); + throw e; + } + + yield client.resume(); + return result; + }); + } + return func(); + } + + /** + * @memberof utils/utils + * @static + */ + function handleError(err) { + console.log("ERROR: ", err); + } + + /** + * @memberof utils/utils + * @static + */ + function promisify(context, method) { + for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { + args[_key - 2] = arguments[_key]; + } + + return new Promise((resolve, reject) => { + args.push(response => { + if (response.error) { + reject(response); + } else { + resolve(response); + } + }); + method.apply(context, args); + }); + } + + /** + * @memberof utils/utils + * @static + */ + function truncateStr(str, size) { + if (str.length > size) { + return str.slice(0, size) + "..."; + } + return str; + } + + /** + * @memberof utils/utils + * @static + */ + function endTruncateStr(str, size) { + if (str.length > size) { + return "..." + str.slice(str.length - size); + } + return str; + } + + var msgId = 1; + /** + * @memberof utils/utils + * @static + */ + function workerTask(worker, method) { + return function () { + for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + return new Promise((resolve, reject) => { + var id = msgId++; + worker.postMessage({ id, method, args }); + + var listener = (_ref) => { + var result = _ref.data; + + if (result.id !== id) { + return; + } + + worker.removeEventListener("message", listener); + if (result.error) { + reject(result.error); + } else { + resolve(result.response); + } + }; + + worker.addEventListener("message", listener); + }); + }; + } + + /** + * Interleaves two arrays element by element, returning the combined array, like + * a zip. In the case of arrays with different sizes, undefined values will be + * interleaved at the end along with the extra values of the larger array. + * + * @param Array a + * @param Array b + * @returns Array + * The combined array, in the form [a1, b1, a2, b2, ...] + * @memberof utils/utils + * @static + */ + function zip(a, b) { + if (!b) { + return a; + } + if (!a) { + return b; + } + var pairs = []; + for (var i = 0, aLength = a.length, bLength = b.length; i < aLength || i < bLength; i++) { + pairs.push([a[i], b[i]]); + } + return pairs; + } + + /** + * Converts an object into an array with 2-element arrays as key/value + * pairs of the object. `{ foo: 1, bar: 2}` would become + * `[[foo, 1], [bar 2]]` (order not guaranteed); + * + * @returns array + * @memberof utils/utils + * @static + */ + function entries(obj) { + return Object.keys(obj).map(k => [k, obj[k]]); + } + + /** + * @memberof utils/utils + * @static + */ + function mapObject(obj, iteratee) { + return toObject(entries(obj).map((_ref2) => { + var _ref3 = _slicedToArray(_ref2, 2); + + var key = _ref3[0]; + var value = _ref3[1]; + + return [key, iteratee(key, value)]; + })); + } + + /** + * Takes an array of 2-element arrays as key/values pairs and + * constructs an object using them. + * @memberof utils/utils + * @static + */ + function toObject(arr) { + var obj = {}; + for (var pair of arr) { + obj[pair[0]] = pair[1]; + } + return obj; + } + + /** + * Composes the given functions into a single function, which will + * apply the results of each function right-to-left, starting with + * applying the given arguments to the right-most function. + * `compose(foo, bar, baz)` === `args => foo(bar(baz(args)` + * + * @param ...function funcs + * @returns function + * @memberof utils/utils + * @static + */ + function compose() { + for (var _len3 = arguments.length, funcs = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + funcs[_key3] = arguments[_key3]; + } + + return function () { + for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { + args[_key4] = arguments[_key4]; + } + + var initialValue = funcs[funcs.length - 1].apply(null, args); + var leftFuncs = funcs.slice(0, -1); + return leftFuncs.reduceRight((composed, f) => f(composed), initialValue); + }; + } + + /** + * @memberof utils/utils + * @static + */ + function updateObj(obj, fields) { + return Object.assign({}, obj, fields); + } + + /** + * @memberof utils/utils + * @static + */ + function throttle(func, ms) { + var timeout = void 0, + _this = void 0; + return function () { + for (var _len5 = arguments.length, args = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { + args[_key5] = arguments[_key5]; + } + + _this = this; + if (!timeout) { + timeout = setTimeout(() => { + func.apply.apply(func, [_this].concat(_toConsumableArray(args))); + timeout = null; + }, ms); + } + }; + } + + module.exports = { + asPaused, + handleError, + promisify, + truncateStr, + endTruncateStr, + workerTask, + zip, + entries, + toObject, + mapObject, + compose, + updateObj, + throttle + }; + +/***/ }, +/* 245 */ +/***/ function(module, exports) { + + + /** + * slice() reference. + */ + + var slice = Array.prototype.slice; + + /** + * Expose `co`. + */ + + module.exports = co['default'] = co.co = co; + + /** + * Wrap the given generator `fn` into a + * function that returns a promise. + * This is a separate function so that + * every `co()` call doesn't create a new, + * unnecessary closure. + * + * @param {GeneratorFunction} fn + * @return {Function} + * @api public + */ + + co.wrap = function (fn) { + createPromise.__generatorFunction__ = fn; + return createPromise; + function createPromise() { + return co.call(this, fn.apply(this, arguments)); + } + }; + + /** + * Execute the generator function or a generator + * and return a promise. + * + * @param {Function} fn + * @return {Promise} + * @api public + */ + + function co(gen) { + var ctx = this; + var args = slice.call(arguments, 1) + + // we wrap everything in a promise to avoid promise chaining, + // which leads to memory leak errors. + // see https://github.com/tj/co/issues/180 + return new Promise(function(resolve, reject) { + if (typeof gen === 'function') gen = gen.apply(ctx, args); + if (!gen || typeof gen.next !== 'function') return resolve(gen); + + onFulfilled(); + + /** + * @param {Mixed} res + * @return {Promise} + * @api private + */ + + function onFulfilled(res) { + var ret; + try { + ret = gen.next(res); + } catch (e) { + return reject(e); + } + next(ret); + } + + /** + * @param {Error} err + * @return {Promise} + * @api private + */ + + function onRejected(err) { + var ret; + try { + ret = gen.throw(err); + } catch (e) { + return reject(e); + } + next(ret); + } + + /** + * Get the next value in the generator, + * return a promise. + * + * @param {Object} ret + * @return {Promise} + * @api private + */ + + function next(ret) { + if (ret.done) return resolve(ret.value); + var value = toPromise.call(ctx, ret.value); + if (value && isPromise(value)) return value.then(onFulfilled, onRejected); + return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, ' + + 'but the following object was passed: "' + String(ret.value) + '"')); + } + }); + } + + /** + * Convert a `yield`ed value into a promise. + * + * @param {Mixed} obj + * @return {Promise} + * @api private + */ + + function toPromise(obj) { + if (!obj) return obj; + if (isPromise(obj)) return obj; + if (isGeneratorFunction(obj) || isGenerator(obj)) return co.call(this, obj); + if ('function' == typeof obj) return thunkToPromise.call(this, obj); + if (Array.isArray(obj)) return arrayToPromise.call(this, obj); + if (isObject(obj)) return objectToPromise.call(this, obj); + return obj; + } + + /** + * Convert a thunk to a promise. + * + * @param {Function} + * @return {Promise} + * @api private + */ + + function thunkToPromise(fn) { + var ctx = this; + return new Promise(function (resolve, reject) { + fn.call(ctx, function (err, res) { + if (err) return reject(err); + if (arguments.length > 2) res = slice.call(arguments, 1); + resolve(res); + }); + }); + } + + /** + * Convert an array of "yieldables" to a promise. + * Uses `Promise.all()` internally. + * + * @param {Array} obj + * @return {Promise} + * @api private + */ + + function arrayToPromise(obj) { + return Promise.all(obj.map(toPromise, this)); + } + + /** + * Convert an object of "yieldables" to a promise. + * Uses `Promise.all()` internally. + * + * @param {Object} obj + * @return {Promise} + * @api private + */ + + function objectToPromise(obj){ + var results = new obj.constructor(); + var keys = Object.keys(obj); + var promises = []; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var promise = toPromise.call(this, obj[key]); + if (promise && isPromise(promise)) defer(promise, key); + else results[key] = obj[key]; + } + return Promise.all(promises).then(function () { + return results; + }); + + function defer(promise, key) { + // predefine the key in the result + results[key] = undefined; + promises.push(promise.then(function (res) { + results[key] = res; + })); + } + } + + /** + * Check if `obj` is a promise. + * + * @param {Object} obj + * @return {Boolean} + * @api private + */ + + function isPromise(obj) { + return 'function' == typeof obj.then; + } + + /** + * Check if `obj` is a generator. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private + */ + + function isGenerator(obj) { + return 'function' == typeof obj.next && 'function' == typeof obj.throw; + } + + /** + * Check if `obj` is a generator function. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private + */ + function isGeneratorFunction(obj) { + var constructor = obj.constructor; + if (!constructor) return false; + if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true; + return isGenerator(constructor.prototype); + } + + /** + * Check for plain object. + * + * @param {Mixed} val + * @return {Boolean} + * @api private + */ + + function isObject(val) { + return Object == val.constructor; + } + + +/***/ }, +/* 246 */ +/***/ function(module, exports, __webpack_require__) { + + var assert = __webpack_require__(247); + + function reportException(who, exception) { + var msg = who + " threw an exception: "; + console.error(msg, exception); + } + + function executeSoon(fn) { + setTimeout(fn, 0); + } + + module.exports = { + reportException, + executeSoon, + assert + }; + +/***/ }, +/* 247 */ +/***/ function(module, exports) { + + function assert(condition, message) { + if (!condition) { + throw new Error("Assertion failure: " + message); + } + } + + module.exports = assert; + +/***/ }, +/* 248 */ +/***/ function(module, exports) { + + + /** + * A middleware that allows thunks (functions) to be dispatched. If + * it's a thunk, it is called with an argument that contains + * `dispatch`, `getState`, and any additional args passed in via the + * middleware constructure. This allows the action to create multiple + * actions (most likely asynchronously). + */ + function thunk(makeArgs) { + return (_ref) => { + var dispatch = _ref.dispatch; + var getState = _ref.getState; + + var args = { dispatch, getState }; + + return next => action => { + return typeof action === "function" ? action(makeArgs ? makeArgs(args, getState()) : args) : next(action); + }; + }; + } + exports.thunk = thunk; + +/***/ }, +/* 249 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var eventListeners = __webpack_require__(250); + var sources = __webpack_require__(252); + var breakpoints = __webpack_require__(255); + var asyncRequests = __webpack_require__(256); + var pause = __webpack_require__(257); + var ui = __webpack_require__(258); + + module.exports = { + eventListeners, + sources: sources.update, + breakpoints: breakpoints.update, + pause: pause.update, + asyncRequests, + ui: ui.update + }; + +/***/ }, +/* 250 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var constants = __webpack_require__(251); + + var initialState = { + activeEventNames: [], + listeners: [], + fetchingListeners: false + }; + + function update() { + var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState; + var action = arguments[1]; + var emit = arguments[2]; + + switch (action.type) { + case constants.UPDATE_EVENT_BREAKPOINTS: + state.activeEventNames = action.eventNames; + emit("activeEventNames", state.activeEventNames); + break; + case constants.FETCH_EVENT_LISTENERS: + if (action.status === "begin") { + state.fetchingListeners = true; + } else if (action.status === "done") { + state.fetchingListeners = false; + state.listeners = action.listeners; + emit("event-listeners", state.listeners); + } + break; + case constants.NAVIGATE: + return initialState; + } + + return state; + } + + module.exports = update; + +/***/ }, +/* 251 */ +/***/ function(module, exports) { + + + + /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + exports.UPDATE_EVENT_BREAKPOINTS = "UPDATE_EVENT_BREAKPOINTS"; + exports.FETCH_EVENT_LISTENERS = "FETCH_EVENT_LISTENERS"; + + exports.TOGGLE_PRETTY_PRINT = "TOGGLE_PRETTY_PRINT"; + exports.BLACKBOX = "BLACKBOX"; + + exports.ADD_BREAKPOINT = "ADD_BREAKPOINT"; + exports.REMOVE_BREAKPOINT = "REMOVE_BREAKPOINT"; + exports.ENABLE_BREAKPOINT = "ENABLE_BREAKPOINT"; + exports.DISABLE_BREAKPOINT = "DISABLE_BREAKPOINT"; + exports.SET_BREAKPOINT_CONDITION = "SET_BREAKPOINT_CONDITION"; + exports.TOGGLE_BREAKPOINTS = "TOGGLE_BREAKPOINTS"; + + exports.ADD_SOURCE = "ADD_SOURCE"; + exports.ADD_SOURCES = "ADD_SOURCES"; + exports.LOAD_SOURCE_TEXT = "LOAD_SOURCE_TEXT"; + exports.SELECT_SOURCE = "SELECT_SOURCE"; + exports.SELECT_SOURCE_URL = "SELECT_SOURCE_URL"; + exports.CLOSE_TAB = "CLOSE_TAB"; + exports.NAVIGATE = "NAVIGATE"; + exports.RELOAD = "RELOAD"; + + exports.ADD_TABS = "ADD_TABS"; + exports.SELECT_TAB = "SELECT_TAB"; + + exports.BREAK_ON_NEXT = "BREAK_ON_NEXT"; + exports.RESUME = "RESUME"; + exports.PAUSED = "PAUSED"; + exports.PAUSE_ON_EXCEPTIONS = "PAUSE_ON_EXCEPTIONS"; + exports.COMMAND = "COMMAND"; + exports.SELECT_FRAME = "SELECT_FRAME"; + exports.LOAD_OBJECT_PROPERTIES = "LOAD_OBJECT_PROPERTIES"; + exports.ADD_EXPRESSION = "ADD_EXPRESSION"; + exports.EVALUATE_EXPRESSION = "EVALUATE_EXPRESSION"; + exports.UPDATE_EXPRESSION = "UPDATE_EXPRESSION"; + exports.DELETE_EXPRESSION = "DELETE_EXPRESSION"; + + exports.TOGGLE_FILE_SEARCH = "TOGGLE_FILE_SEARCH"; + +/***/ }, +/* 252 */ +/***/ function(module, exports, __webpack_require__) { + + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + /** + * Sources reducer + * @module reducers/sources + */ + + var fromJS = __webpack_require__(253); + var I = __webpack_require__(229); + var makeRecord = __webpack_require__(254); + + var State = makeRecord({ + sources: I.Map(), + selectedLocation: undefined, + pendingSelectedLocation: undefined, + sourcesText: I.Map(), + tabs: I.List([]) + }); + + function update() { + var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : State(); + var action = arguments[1]; + + switch (action.type) { + case "ADD_SOURCE": + { + var _source = action.source; + return state.mergeIn(["sources", action.source.id], _source); + } + + case "SELECT_SOURCE": + return state.set("selectedLocation", { + sourceId: action.source.id, + line: action.line + }).set("pendingSelectedLocation", null).merge({ + tabs: updateTabList(state, fromJS(action.source), action.tabIndex) + }); + + case "SELECT_SOURCE_URL": + return state.set("pendingSelectedLocation", { + url: action.url, + line: action.line + }); + + case "CLOSE_TAB": + return state.merge({ tabs: removeSourceFromTabList(state, action.id) }).set("selectedLocation", { + sourceId: getNewSelectedSourceId(state, action.id) + }); + + case "LOAD_SOURCE_TEXT": + return _updateText(state, action); + + case "BLACKBOX": + if (action.status === "done") { + return state.setIn(["sources", action.source.id, "isBlackBoxed"], action.value.isBlackBoxed); + } + break; + + case "TOGGLE_PRETTY_PRINT": + return _updateText(state, action); + + case "NAVIGATE": + var source = getSelectedSource({ sources: state }); + var _url = source && source.get("url"); + return State().set("pendingSelectedLocation", { url: _url }); + } + + return state; + } + + // TODO: Action is coerced to `any` unfortunately because how we type + // asynchronous actions is wrong. The `value` may be null for the + // "start" and "error" states but we don't type it like that. We need + // to rethink how we type async actions. + function _updateText(state, action) { + var source = action.source; + var sourceText = action.value; + + if (action.status === "start") { + // Merge this in, don't set it. That way the previous value is + // still stored here, and we can retrieve it if whatever we're + // doing fails. + return state.mergeIn(["sourcesText", source.id], { + loading: true + }); + } + + if (action.status === "error") { + return state.setIn(["sourcesText", source.id], I.Map({ + error: action.error + })); + } + + return state.setIn(["sourcesText", source.id], I.Map({ + text: sourceText.text, + contentType: sourceText.contentType + })); + } + + function removeSourceFromTabList(state, id) { + return state.tabs.filter(tab => tab.get("id") != id); + } + + /** + * Adds the new source to the tab list if it is not already there + * @memberof reducers/sources + * @static + */ + function updateTabList(state, source, tabIndex) { + var tabs = state.get("tabs"); + var sourceIndex = tabs.indexOf(source); + var includesSource = !!tabs.find(t => t.get("id") == source.get("id")); + + if (includesSource) { + if (tabIndex != undefined) { + return tabs.delete(sourceIndex).insert(tabIndex, source); + } + + return tabs; + } + + return tabs.insert(0, source); + } + + /** + * Gets the next tab to select when a tab closes. + * @memberof reducers/sources + * @static + */ + function getNewSelectedSourceId(state, id) { + var tabs = state.get("tabs"); + var selectedSource = getSelectedSource({ sources: state }); + + if (!selectedSource) { + return undefined; + } else if (selectedSource.get("id") != id) { + // If we're not closing the selected tab return the selected tab + return selectedSource.get("id"); + } + + var tabIndex = tabs.findIndex(tab => tab.get("id") == id); + var numTabs = tabs.count(); + + if (numTabs == 1) { + return undefined; + } + + // if we're closing the last tab, select the penultimate tab + if (tabIndex + 1 == numTabs) { + return tabs.get(tabIndex - 1).get("id"); + } + + // return the next tab + return tabs.get(tabIndex + 1).get("id"); + } + + // Selectors + + // Unfortunately, it's really hard to make these functions accept just + // the state that we care about and still type it with Flow. The + // problem is that we want to re-export all selectors from a single + // module for the UI, and all of those selectors should take the + // top-level app state, so we'd have to "wrap" them to automatically + // pick off the piece of state we're interested in. It's impossible + // (right now) to type those wrapped functions. + + + function getSource(state, id) { + return state.sources.sources.get(id); + } + + function getSourceByURL(state, url) { + return state.sources.sources.find(source => source.get("url") == url); + } + + function getSourceById(state, id) { + return state.sources.sources.find(source => source.get("id") == id); + } + + function getSources(state) { + return state.sources.sources; + } + + function getSourceText(state, id) { + return state.sources.sourcesText.get(id); + } + + function getSourceTabs(state) { + return state.sources.tabs; + } + + function getSelectedSource(state) { + if (state.sources.selectedLocation) { + return getSource(state, state.sources.selectedLocation.sourceId); + } + return undefined; + } + + function getSelectedLocation(state) { + return state.sources.selectedLocation; + } + + function getPendingSelectedLocation(state) { + return state.sources.pendingSelectedLocation; + } + + function getPrettySource(state, id) { + var source = getSource(state, id); + if (!source) { + return; + } + + return getSourceByURL(state, source.get("url") + ":formatted"); + } + + module.exports = { + State, + update, + getSource, + getSourceByURL, + getSourceById, + getSources, + getSourceText, + getSourceTabs, + getSelectedSource, + getSelectedLocation, + getPendingSelectedLocation, + getPrettySource + }; + +/***/ }, +/* 253 */ +/***/ function(module, exports, __webpack_require__) { + + + + /** + * Immutable JS conversion utils + * @deprecated + * @module utils/fromJS + */ + + var Immutable = __webpack_require__(229); + + /** + * When our app state is fully typed, we should be able to get rid of + * this function. This is only temporarily necessary to support + * converting typed objects to immutable.js, which usually happens in + * reducers. + * + * @memberof utils/fromJS + * @static + */ + function fromJS(value) { + if (Array.isArray(value)) { + return Immutable.Seq(value).map(fromJS).toList(); + } + if (value && value.constructor.meta) { + // This adds support for tcomb objects which are native JS objects + // but are not "plain", so the above checks fail. Since they + // behave the same we can use the same constructors, but we need + // special checks for them. + var kind = value.constructor.meta.kind; + if (kind === "struct") { + return Immutable.Seq(value).map(fromJS).toMap(); + } else if (kind === "list") { + return Immutable.Seq(value).map(fromJS).toList(); + } + } + + // If it's a primitive type, just return the value. Note `==` check + // for null, which is intentionally used to match either `null` or + // `undefined`. + if (value == null || typeof value !== "object") { + return value; + } + + // Otherwise, treat it like an object. We can't reliably detect if + // it's a plain object because we might be objects from other JS + // contexts so `Object !== Object`. + return Immutable.Seq(value).map(fromJS).toMap(); + } + + module.exports = fromJS; + +/***/ }, +/* 254 */ +/***/ function(module, exports, __webpack_require__) { + + + + /** + * When Flow 0.29 is released (very soon), we can use this Record type + * instead of the builtin immutable.js Record type. This is better + * because all the fields are actually typed, unlike the builtin one. + * This depends on a performance fix that will go out in 0.29 though; + * @module utils/makeRecord + */ + + var I = __webpack_require__(229); + + /** + * @memberof utils/makeRecord + * @static + */ + + + /** + * Make an immutable record type + * + * @param spec - the keys and their default values + * @return a state record factory function + * @memberof utils/makeRecord + * @static + */ + function makeRecord(spec) { + return I.Record(spec); + } + + module.exports = makeRecord; + +/***/ }, +/* 255 */ +/***/ function(module, exports, __webpack_require__) { + + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + /** + * Breakpoints reducer + * @module reducers/breakpoints + */ + + var fromJS = __webpack_require__(253); + + var _require = __webpack_require__(244); + + var updateObj = _require.updateObj; + + var I = __webpack_require__(229); + var makeRecord = __webpack_require__(254); + + var State = makeRecord({ + breakpoints: I.Map(), + breakpointsDisabled: false + }); + + // Return the first argument that is a string, or null if nothing is a + // string. + function firstString() { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + for (var arg of args) { + if (typeof arg === "string") { + return arg; + } + } + return null; + } + + function locationMoved(location, newLocation) { + return location.line !== newLocation.line || location.column != null && location.column !== newLocation.column; + } + + function makeLocationId(location) { + return location.sourceId + ":" + location.line.toString(); + } + + function update() { + var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : State(); + var action = arguments[1]; + + switch (action.type) { + case "ADD_BREAKPOINT": + { + var id = makeLocationId(action.breakpoint.location); + + if (action.status === "start") { + var bp = state.breakpoints.get(id) || action.breakpoint; + + return state.setIn(["breakpoints", id], updateObj(bp, { + disabled: false, + loading: true, + // We want to do an OR here, but we can't because we need + // empty strings to be truthy, i.e. an empty string is a valid + // condition. + condition: firstString(action.condition, bp.condition) + })); + } else if (action.status === "done") { + var _action$value = action.value; + var breakpointId = _action$value.id; + var text = _action$value.text; + + var location = action.breakpoint.location; + var actualLocation = action.value.actualLocation; + + // If the breakpoint moved, update the map + + if (locationMoved(location, actualLocation)) { + state = state.deleteIn(["breakpoints", id]); + + var movedId = makeLocationId(actualLocation); + var currentBp = state.breakpoints.get(movedId) || fromJS(action.breakpoint); + var newBp = updateObj(currentBp, { location: actualLocation }); + state = state.setIn(["breakpoints", movedId], newBp); + location = actualLocation; + } + + var locationId = makeLocationId(location); + var _bp = state.breakpoints.get(locationId); + return state.setIn(["breakpoints", locationId], updateObj(_bp, { + id: breakpointId, + disabled: false, + loading: false, + text: text + })); + } else if (action.status === "error") { + // Remove the optimistic update + return state.deleteIn(["breakpoints", id]); + } + break; + } + + case "REMOVE_BREAKPOINT": + { + if (action.status === "done") { + var _id = makeLocationId(action.breakpoint.location); + + if (action.disabled) { + var _bp2 = state.breakpoints.get(_id); + return state.setIn(["breakpoints", _id], updateObj(_bp2, { + loading: false, disabled: true + })); + } + + return state.deleteIn(["breakpoints", _id]); + } + break; + } + + case "TOGGLE_BREAKPOINTS": + { + if (action.status === "start") { + return state.set("breakpointsDisabled", action.shouldDisableBreakpoints); + } + break; + } + + case "SET_BREAKPOINT_CONDITION": + { + var _id2 = makeLocationId(action.breakpoint.location); + + if (action.status === "start") { + var _bp3 = state.breakpoints.get(_id2); + return state.setIn(["breakpoints", _id2], updateObj(_bp3, { + loading: true, + condition: action.condition + })); + } else if (action.status === "done") { + var _bp4 = state.breakpoints.get(_id2); + return state.setIn(["breakpoints", _id2], updateObj(_bp4, { + id: action.value.id, + loading: false + })); + } else if (action.status === "error") { + return state.deleteIn(["breakpoints", _id2]); + } + + break; + }} + + return state; + } + + // Selectors + + function getBreakpoint(state, location) { + return state.breakpoints.breakpoints.get(makeLocationId(location)); + } + + function getBreakpoints(state) { + return state.breakpoints.breakpoints; + } + + function getBreakpointsForSource(state, sourceId) { + return state.breakpoints.breakpoints.filter(bp => { + return bp.location.sourceId === sourceId; + }); + } + + function getBreakpointsDisabled(state) { + return state.breakpoints.get("breakpointsDisabled"); + } + + function getBreakpointsLoading(state) { + var breakpoints = getBreakpoints(state); + var isLoading = !!breakpoints.valueSeq().filter(bp => bp.loading).first(); + + return breakpoints.size > 0 && isLoading; + } + + module.exports = { + State, + update, + makeLocationId, + getBreakpoint, + getBreakpoints, + getBreakpointsForSource, + getBreakpointsDisabled, + getBreakpointsLoading + }; + +/***/ }, +/* 256 */ +/***/ function(module, exports, __webpack_require__) { + + function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var constants = __webpack_require__(251); + var initialState = []; + + function update() { + var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState; + var action = arguments[1]; + var seqId = action.seqId; + + + if (action.type === constants.NAVIGATE) { + return initialState; + } else if (seqId) { + var newState = void 0; + if (action.status === "start") { + newState = [].concat(_toConsumableArray(state), [seqId]); + } else if (action.status === "error" || action.status === "done") { + newState = state.filter(id => id !== seqId); + } + + return newState; + } + + return state; + } + + module.exports = update; + +/***/ }, +/* 257 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + var constants = __webpack_require__(251); + var fromJS = __webpack_require__(253); + + var initialState = fromJS({ + pause: null, + isWaitingOnBreak: false, + frames: null, + selectedFrameId: null, + loadedObjects: {}, + shouldPauseOnExceptions: false, + shouldIgnoreCaughtExceptions: false, + expressions: [] + }); + + function update() { + var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState; + var action = arguments[1]; + var emit = arguments[2]; + + switch (action.type) { + case constants.PAUSED: + { + var selectedFrameId = action.selectedFrameId; + var frames = action.frames; + var pauseInfo = action.pauseInfo; + + pauseInfo.isInterrupted = pauseInfo.why.type === "interrupted"; + + return state.merge({ + isWaitingOnBreak: false, + pause: fromJS(pauseInfo), + selectedFrameId, + frames + }); + } + + case constants.RESUME: + return state.merge({ + pause: null, + frames: null, + selectedFrameId: null, + loadedObjects: {} + }); + + case constants.TOGGLE_PRETTY_PRINT: + if (action.status == "done") { + var _frames = action.value.frames; + var pause = state.get("pause"); + if (pause) { + pause = pause.set("frame", fromJS(_frames[0])); + } + + return state.merge({ pause, frames: _frames }); + } + + break; + case constants.BREAK_ON_NEXT: + return state.set("isWaitingOnBreak", true); + + case constants.LOADED_FRAMES: + if (action.status == "done") { + return state.set("frames", action.value.frames); + } + + break; + case constants.SELECT_FRAME: + return state.set("selectedFrameId", action.frame.id); + + case constants.LOAD_OBJECT_PROPERTIES: + if (action.status === "done") { + var ownProperties = action.value.ownProperties; + var prototype = action.value.prototype; + + return state.setIn(["loadedObjects", action.objectId], { ownProperties, prototype }); + } + break; + + case constants.NAVIGATE: + return initialState; + + case constants.PAUSE_ON_EXCEPTIONS: + var shouldPauseOnExceptions = action.shouldPauseOnExceptions; + var shouldIgnoreCaughtExceptions = action.shouldIgnoreCaughtExceptions; + + return state.merge({ + shouldPauseOnExceptions, + shouldIgnoreCaughtExceptions + }); + + case constants.ADD_EXPRESSION: + return state.setIn(["expressions", action.id], { id: action.id, + input: action.input, + value: action.value, + updating: false }); + + case constants.EVALUATE_EXPRESSION: + if (action.status === "done") { + return state.mergeIn(["expressions", action.id], { id: action.id, + input: action.input, + value: action.value, + updating: false }); + } + break; + + case constants.UPDATE_EXPRESSION: + return state.mergeIn(["expressions", action.id], { id: action.id, + input: action.input, + updating: true }); + + case constants.DELETE_EXPRESSION: + return state.deleteIn(["expressions", action.id]); + } + + return state; + } + + function getPause(state) { + return state.pause.get("pause"); + } + + function getLoadedObjects(state) { + return state.pause.get("loadedObjects"); + } + + function getExpressions(state) { + return state.pause.get("expressions"); + } + + function getIsWaitingOnBreak(state) { + return state.pause.get("isWaitingOnBreak"); + } + + function getShouldPauseOnExceptions(state) { + return state.pause.get("shouldPauseOnExceptions"); + } + + function getShouldIgnoreCaughtExceptions(state) { + return state.pause.get("shouldIgnoreCaughtExceptions"); + } + + function getFrames(state) { + return state.pause.get("frames"); + } + + function getSelectedFrame(state) { + var selectedFrameId = state.pause.get("selectedFrameId"); + var frames = state.pause.get("frames"); + return frames && frames.find(frame => frame.id == selectedFrameId); + } + + module.exports = { + initialState, + update, + getPause, + getLoadedObjects, + getExpressions, + getIsWaitingOnBreak, + getShouldPauseOnExceptions, + getShouldIgnoreCaughtExceptions, + getFrames, + getSelectedFrame + }; + +/***/ }, +/* 258 */ +/***/ function(module, exports, __webpack_require__) { + + + + /** + * UI reducer + * @module reducers/ui + */ + + var constants = __webpack_require__(251); + var makeRecord = __webpack_require__(254); + + var State = makeRecord({ + searchOn: false + }); + + function update() { + var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : State(); + var action = arguments[1]; + + switch (action.type) { + case constants.TOGGLE_FILE_SEARCH: + { + return state.set("searchOn", action.searchOn); + } + default: + { + return state; + } + } + } + + // NOTE: we'd like to have the app state fully typed + // https://github.com/devtools-html/debugger.html/blob/master/public/js/reducers/sources.js#L179-L185 + + + function getFileSearchState(state) { + return state.ui.get("searchOn"); + } + + module.exports = { + State, + update, + getFileSearchState + }; + +/***/ }, +/* 259 */ +/***/ function(module, exports, __webpack_require__) { + + var sources = __webpack_require__(252); + var pause = __webpack_require__(257); + var breakpoints = __webpack_require__(255); + var ui = __webpack_require__(258); + + /** + * @param object - location + */ + + module.exports = { + getSource: sources.getSource, + getSourceByURL: sources.getSourceByURL, + getSourceById: sources.getSourceById, + getSources: sources.getSources, + getSourceText: sources.getSourceText, + getSourceTabs: sources.getSourceTabs, + getSelectedSource: sources.getSelectedSource, + getSelectedLocation: sources.getSelectedLocation, + getPendingSelectedLocation: sources.getPendingSelectedLocation, + getPrettySource: sources.getPrettySource, + + getBreakpoint: breakpoints.getBreakpoint, + getBreakpoints: breakpoints.getBreakpoints, + getBreakpointsForSource: breakpoints.getBreakpointsForSource, + getBreakpointsDisabled: breakpoints.getBreakpointsDisabled, + getBreakpointsLoading: breakpoints.getBreakpointsLoading, + + getPause: pause.getPause, + getLoadedObjects: pause.getLoadedObjects, + getExpressions: pause.getExpressions, + getExpressionInputVisibility: pause.getExpressionInputVisibility, + getIsWaitingOnBreak: pause.getIsWaitingOnBreak, + getShouldPauseOnExceptions: pause.getShouldPauseOnExceptions, + getShouldIgnoreCaughtExceptions: pause.getShouldIgnoreCaughtExceptions, + getFrames: pause.getFrames, + getSelectedFrame: pause.getSelectedFrame, + + getFileSearchState: ui.getFileSearchState + }; + +/***/ }, +/* 260 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + var createFactory = React.createFactory; + + var _require = __webpack_require__(19); + + var connect = _require.connect; + + var _require2 = __webpack_require__(3); + + var bindActionCreators = _require2.bindActionCreators; + + var _require3 = __webpack_require__(261); + + var cmdString = _require3.cmdString; + + var actions = __webpack_require__(262); + + var _require4 = __webpack_require__(259); + + var getSources = _require4.getSources; + var getSelectedSource = _require4.getSelectedSource; + + var _require5 = __webpack_require__(28); + + var KeyShortcuts = _require5.KeyShortcuts; + + var shortcuts = new KeyShortcuts({ window }); + + __webpack_require__(283); + __webpack_require__(286); + __webpack_require__(288); + __webpack_require__(290); + + var _require6 = __webpack_require__(30); + + var SplitBox = _require6.SplitBox; + + SplitBox = createFactory(SplitBox); + + var SourceSearch = createFactory(__webpack_require__(292)); + var Sources = createFactory(__webpack_require__(339)); + var Editor = createFactory(__webpack_require__(400)); + var RightSidebar = createFactory(__webpack_require__(416)); + var SourceTabs = createFactory(__webpack_require__(452)); + + var App = React.createClass({ + propTypes: { + sources: PropTypes.object, + selectSource: PropTypes.func, + selectedSource: PropTypes.object + }, + + displayName: "App", + + getChildContext() { + return { shortcuts }; + }, + + renderWelcomeBox() { + return dom.div({ className: "welcomebox" }, L10N.getFormatStr("welcome.search", cmdString() + "+P")); + }, + + renderCenterPane() { + return dom.div({ className: "center-pane" }, dom.div({ className: "editor-container" }, SourceTabs(), Editor(), !this.props.selectedSource ? this.renderWelcomeBox() : null, SourceSearch())); + }, + + render: function () { + return dom.div({ className: "debugger" }, SplitBox({ + style: { width: "100vw" }, + initialSize: "300px", + minSize: 10, + maxSize: "50%", + splitterSize: 1, + startPanel: Sources({ sources: this.props.sources }), + endPanel: SplitBox({ + initialSize: "300px", + minSize: 10, + maxSize: "80%", + splitterSize: 1, + endPanelControl: true, + startPanel: this.renderCenterPane(this.props), + endPanel: RightSidebar() + }) + })); + } + }); + + App.childContextTypes = { + shortcuts: PropTypes.object + }; + + module.exports = connect(state => ({ sources: getSources(state), + selectedSource: getSelectedSource(state) + }), dispatch => bindActionCreators(actions, dispatch))(App); + +/***/ }, +/* 261 */ +/***/ function(module, exports, __webpack_require__) { + + + + /** + * Utils for keyboard command strings + * @module utils/text + */ + + var _require = __webpack_require__(30); + + var appinfo = _require.Services.appinfo; + + /** + * @memberof utils/text + * @static + */ + + function cmdString() { + return appinfo.OS === "Darwin" ? "⌘" : "Ctrl"; + } + + module.exports = { + cmdString + }; + +/***/ }, +/* 262 */ +/***/ function(module, exports, __webpack_require__) { + + var breakpoints = __webpack_require__(263); + var eventListeners = __webpack_require__(271); + var sources = __webpack_require__(273); + var pause = __webpack_require__(280); + var navigation = __webpack_require__(281); + var ui = __webpack_require__(282); + + module.exports = Object.assign(navigation, breakpoints, eventListeners, sources, pause, ui); + +/***/ }, +/* 263 */ +/***/ function(module, exports, __webpack_require__) { + + var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + + function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + /** + * Redux actions for breakpoints + * @module actions/breakpoints + */ + + var constants = __webpack_require__(251); + + var _require = __webpack_require__(242); + + var PROMISE = _require.PROMISE; + + var _require2 = __webpack_require__(259); + + var getBreakpoint = _require2.getBreakpoint; + var getBreakpoints = _require2.getBreakpoints; + var getSource = _require2.getSource; + + var _require3 = __webpack_require__(264); + + var getOriginalLocation = _require3.getOriginalLocation; + var getGeneratedLocation = _require3.getGeneratedLocation; + var isOriginalId = _require3.isOriginalId; + + + function _breakpointExists(state, location) { + var currentBp = getBreakpoint(state, location); + return currentBp && !currentBp.disabled; + } + + function _getOrCreateBreakpoint(state, location, condition) { + return getBreakpoint(state, location) || { location, condition, text: "" }; + } + + /** + * Enabling a breakpoint calls {@link addBreakpoint} + * which will reuse the existing breakpoint information that is stored. + * + * @memberof actions/breakpoints + * @static + */ + function enableBreakpoint(location) { + return addBreakpoint(location); + } + + /** + * Add a new or enable an existing breakpoint + * + * @memberof actions/breakpoints + * @static + * @param {String} $1.condition Conditional breakpoint condition value + * @param {Function} $1.getTextForLine Get the text to represent the line + */ + function addBreakpoint(location) { + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var condition = _ref.condition; + var getTextForLine = _ref.getTextForLine; + + return (_ref2) => { + var dispatch = _ref2.dispatch; + var getState = _ref2.getState; + var client = _ref2.client; + + if (_breakpointExists(getState(), location)) { + return Promise.resolve(); + } + + var bp = _getOrCreateBreakpoint(getState(), location, condition); + + return dispatch({ + type: constants.ADD_BREAKPOINT, + breakpoint: bp, + condition: condition, + [PROMISE]: _asyncToGenerator(function* () { + if (isOriginalId(bp.location.sourceId)) { + var source = getSource(getState(), bp.location.sourceId); + location = yield getGeneratedLocation(bp.location, source.toJS()); + } + + var _ref4 = yield client.setBreakpoint(location, bp.condition, isOriginalId(bp.location.sourceId)); + + var id = _ref4.id; + var actualLocation = _ref4.actualLocation; + + + actualLocation = yield getOriginalLocation(actualLocation); + + // If this breakpoint is being re-enabled, it already has a + // text snippet. + var text = bp.text; + if (!text) { + text = getTextForLine ? getTextForLine(actualLocation.line) : ""; + } + + return { id, actualLocation, text }; + })() + }); + }; + } + + /** + * Disable a single breakpoint + * + * @memberof actions/breakpoints + * @static + */ + function disableBreakpoint(location) { + return _removeOrDisableBreakpoint(location, true); + } + + /** + * Remove a single breakpoint + * + * @memberof actions/breakpoints + * @static + */ + function removeBreakpoint(location) { + return _removeOrDisableBreakpoint(location); + } + + function _removeOrDisableBreakpoint(location, isDisabled) { + return (_ref5) => { + var dispatch = _ref5.dispatch; + var getState = _ref5.getState; + var client = _ref5.client; + + var bp = getBreakpoint(getState(), location); + if (!bp) { + throw new Error("attempt to remove breakpoint that does not exist"); + } + if (bp.loading) { + // TODO(jwl): make this wait until the breakpoint is saved if it + // is still loading + throw new Error("attempt to remove unsaved breakpoint"); + } + + var action = { + type: constants.REMOVE_BREAKPOINT, + breakpoint: bp, + disabled: isDisabled + }; + + // If the breakpoint is already disabled, we don't need to remove + // it from the server. We just need to dispatch an action + // simulating a successful server request to remove it, and it + // will be removed completely from the state. + if (!bp.disabled) { + return dispatch(Object.assign({}, action, { + [PROMISE]: client.removeBreakpoint(bp.id) + })); + } + return dispatch(Object.assign({}, action, { status: "done" })); + }; + } + + /** + * Toggle All Breakpoints + * + * @memberof actions/breakpoints + * @static + */ + function toggleAllBreakpoints(shouldDisableBreakpoints) { + return (_ref6) => { + var dispatch = _ref6.dispatch; + var getState = _ref6.getState; + + var breakpoints = getBreakpoints(getState()); + return dispatch({ + type: constants.TOGGLE_BREAKPOINTS, + shouldDisableBreakpoints, + [PROMISE]: _asyncToGenerator(function* () { + for (var _ref8 of breakpoints) { + var _ref9 = _slicedToArray(_ref8, 2); + + var breakpoint = _ref9[1]; + + if (shouldDisableBreakpoints) { + yield dispatch(disableBreakpoint(breakpoint.location)); + } else { + yield dispatch(enableBreakpoint(breakpoint.location)); + } + } + })() + }); + }; + } + + /** + * Update the condition of a breakpoint. + * + * @throws {Error} "not implemented" + * @memberof actions/breakpoints + * @static + * @param {Location} location + * @see DebuggerController.Breakpoints.addBreakpoint + * @param {string} condition + * The condition to set on the breakpoint + */ + function setBreakpointCondition(location) { + var _ref10 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var condition = _ref10.condition; + var getTextForLine = _ref10.getTextForLine; + + // location: Location, condition: string, { getTextForLine }) { + return (_ref11) => { + var dispatch = _ref11.dispatch; + var getState = _ref11.getState; + var client = _ref11.client; + + var bp = getBreakpoint(getState(), location); + if (!bp) { + return dispatch(addBreakpoint(location, { condition, getTextForLine })); + } + + if (bp.loading) { + // TODO(jwl): when this function is called, make sure the action + // creator waits for the breakpoint to exist + throw new Error("breakpoint must be saved"); + } + + return dispatch({ + type: constants.SET_BREAKPOINT_CONDITION, + breakpoint: bp, + condition: condition, + [PROMISE]: client.setBreakpointCondition(bp.id, location, condition, isOriginalId(bp.location.sourceId)) + }); + }; + } + + module.exports = { + enableBreakpoint, + addBreakpoint, + disableBreakpoint, + removeBreakpoint, + toggleAllBreakpoints, + setBreakpointCondition + }; + +/***/ }, +/* 264 */ +/***/ function(module, exports, __webpack_require__) { + + var _require = __webpack_require__(89); + + var getValue = _require.getValue; + var isEnabled = _require.isEnabled; + + var _require2 = __webpack_require__(244); + + var workerTask = _require2.workerTask; + + var _require3 = __webpack_require__(265); + + var originalToGeneratedId = _require3.originalToGeneratedId; + var generatedToOriginalId = _require3.generatedToOriginalId; + var isGeneratedId = _require3.isGeneratedId; + var isOriginalId = _require3.isOriginalId; + + var _require4 = __webpack_require__(270); + + var prefs = _require4.prefs; + + + var sourceMapWorker = void 0; + function restartWorker() { + if (sourceMapWorker) { + sourceMapWorker.terminate(); + } + sourceMapWorker = new Worker(getValue("baseWorkerURL") + "source-map-worker.js"); + + if (isEnabled("sourceMaps")) { + sourceMapWorker.postMessage({ id: 0, method: "enableSourceMaps" }); + } + } + restartWorker(); + + function destroyWorker() { + if (sourceMapWorker) { + sourceMapWorker.terminate(); + sourceMapWorker = null; + } + } + + function shouldSourceMap() { + return isEnabled("sourceMaps") && prefs.clientSourceMapsEnabled; + } + + var getOriginalURLs = workerTask(sourceMapWorker, "getOriginalURLs"); + var getGeneratedLocation = workerTask(sourceMapWorker, "getGeneratedLocation"); + var getOriginalLocation = workerTask(sourceMapWorker, "getOriginalLocation"); + var getOriginalSourceText = workerTask(sourceMapWorker, "getOriginalSourceText"); + var applySourceMap = workerTask(sourceMapWorker, "applySourceMap"); + var clearSourceMaps = workerTask(sourceMapWorker, "clearSourceMaps"); + + module.exports = { + originalToGeneratedId, + generatedToOriginalId, + isGeneratedId, + isOriginalId, + + getOriginalURLs, + getGeneratedLocation, + getOriginalLocation, + getOriginalSourceText, + applySourceMap, + clearSourceMaps, + destroyWorker, + shouldSourceMap + }; + +/***/ }, +/* 265 */ +/***/ function(module, exports, __webpack_require__) { + + var md5 = __webpack_require__(266); + + function originalToGeneratedId(originalId) { + var match = originalId.match(/(.*)\/originalSource/); + return match ? match[1] : ""; + } + + function generatedToOriginalId(generatedId, url) { + return generatedId + "/originalSource-" + md5(url); + } + + function isOriginalId(id) { + return !!id.match(/\/originalSource/); + } + + function isGeneratedId(id) { + return !isOriginalId(id); + } + + module.exports = { + originalToGeneratedId, generatedToOriginalId, isOriginalId, isGeneratedId + }; + +/***/ }, +/* 266 */ +/***/ function(module, exports, __webpack_require__) { + + (function(){
+ var crypt = __webpack_require__(267),
+ utf8 = __webpack_require__(268).utf8,
+ isBuffer = __webpack_require__(269),
+ bin = __webpack_require__(268).bin,
+
+ // The core
+ md5 = function (message, options) {
+ // Convert to byte array
+ if (message.constructor == String)
+ if (options && options.encoding === 'binary')
+ message = bin.stringToBytes(message);
+ else
+ message = utf8.stringToBytes(message);
+ else if (isBuffer(message))
+ message = Array.prototype.slice.call(message, 0);
+ else if (!Array.isArray(message))
+ message = message.toString();
+ // else, assume byte array already
+
+ var m = crypt.bytesToWords(message),
+ l = message.length * 8,
+ a = 1732584193,
+ b = -271733879,
+ c = -1732584194,
+ d = 271733878;
+
+ // Swap endian
+ for (var i = 0; i < m.length; i++) {
+ m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF |
+ ((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00;
+ }
+
+ // Padding
+ m[l >>> 5] |= 0x80 << (l % 32);
+ m[(((l + 64) >>> 9) << 4) + 14] = l;
+
+ // Method shortcuts
+ var FF = md5._ff,
+ GG = md5._gg,
+ HH = md5._hh,
+ II = md5._ii;
+
+ for (var i = 0; i < m.length; i += 16) {
+
+ var aa = a,
+ bb = b,
+ cc = c,
+ dd = d;
+
+ a = FF(a, b, c, d, m[i+ 0], 7, -680876936);
+ d = FF(d, a, b, c, m[i+ 1], 12, -389564586);
+ c = FF(c, d, a, b, m[i+ 2], 17, 606105819);
+ b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);
+ a = FF(a, b, c, d, m[i+ 4], 7, -176418897);
+ d = FF(d, a, b, c, m[i+ 5], 12, 1200080426);
+ c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);
+ b = FF(b, c, d, a, m[i+ 7], 22, -45705983);
+ a = FF(a, b, c, d, m[i+ 8], 7, 1770035416);
+ d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);
+ c = FF(c, d, a, b, m[i+10], 17, -42063);
+ b = FF(b, c, d, a, m[i+11], 22, -1990404162);
+ a = FF(a, b, c, d, m[i+12], 7, 1804603682);
+ d = FF(d, a, b, c, m[i+13], 12, -40341101);
+ c = FF(c, d, a, b, m[i+14], 17, -1502002290);
+ b = FF(b, c, d, a, m[i+15], 22, 1236535329);
+
+ a = GG(a, b, c, d, m[i+ 1], 5, -165796510);
+ d = GG(d, a, b, c, m[i+ 6], 9, -1069501632);
+ c = GG(c, d, a, b, m[i+11], 14, 643717713);
+ b = GG(b, c, d, a, m[i+ 0], 20, -373897302);
+ a = GG(a, b, c, d, m[i+ 5], 5, -701558691);
+ d = GG(d, a, b, c, m[i+10], 9, 38016083);
+ c = GG(c, d, a, b, m[i+15], 14, -660478335);
+ b = GG(b, c, d, a, m[i+ 4], 20, -405537848);
+ a = GG(a, b, c, d, m[i+ 9], 5, 568446438);
+ d = GG(d, a, b, c, m[i+14], 9, -1019803690);
+ c = GG(c, d, a, b, m[i+ 3], 14, -187363961);
+ b = GG(b, c, d, a, m[i+ 8], 20, 1163531501);
+ a = GG(a, b, c, d, m[i+13], 5, -1444681467);
+ d = GG(d, a, b, c, m[i+ 2], 9, -51403784);
+ c = GG(c, d, a, b, m[i+ 7], 14, 1735328473);
+ b = GG(b, c, d, a, m[i+12], 20, -1926607734);
+
+ a = HH(a, b, c, d, m[i+ 5], 4, -378558);
+ d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);
+ c = HH(c, d, a, b, m[i+11], 16, 1839030562);
+ b = HH(b, c, d, a, m[i+14], 23, -35309556);
+ a = HH(a, b, c, d, m[i+ 1], 4, -1530992060);
+ d = HH(d, a, b, c, m[i+ 4], 11, 1272893353);
+ c = HH(c, d, a, b, m[i+ 7], 16, -155497632);
+ b = HH(b, c, d, a, m[i+10], 23, -1094730640);
+ a = HH(a, b, c, d, m[i+13], 4, 681279174);
+ d = HH(d, a, b, c, m[i+ 0], 11, -358537222);
+ c = HH(c, d, a, b, m[i+ 3], 16, -722521979);
+ b = HH(b, c, d, a, m[i+ 6], 23, 76029189);
+ a = HH(a, b, c, d, m[i+ 9], 4, -640364487);
+ d = HH(d, a, b, c, m[i+12], 11, -421815835);
+ c = HH(c, d, a, b, m[i+15], 16, 530742520);
+ b = HH(b, c, d, a, m[i+ 2], 23, -995338651);
+
+ a = II(a, b, c, d, m[i+ 0], 6, -198630844);
+ d = II(d, a, b, c, m[i+ 7], 10, 1126891415);
+ c = II(c, d, a, b, m[i+14], 15, -1416354905);
+ b = II(b, c, d, a, m[i+ 5], 21, -57434055);
+ a = II(a, b, c, d, m[i+12], 6, 1700485571);
+ d = II(d, a, b, c, m[i+ 3], 10, -1894986606);
+ c = II(c, d, a, b, m[i+10], 15, -1051523);
+ b = II(b, c, d, a, m[i+ 1], 21, -2054922799);
+ a = II(a, b, c, d, m[i+ 8], 6, 1873313359);
+ d = II(d, a, b, c, m[i+15], 10, -30611744);
+ c = II(c, d, a, b, m[i+ 6], 15, -1560198380);
+ b = II(b, c, d, a, m[i+13], 21, 1309151649);
+ a = II(a, b, c, d, m[i+ 4], 6, -145523070);
+ d = II(d, a, b, c, m[i+11], 10, -1120210379);
+ c = II(c, d, a, b, m[i+ 2], 15, 718787259);
+ b = II(b, c, d, a, m[i+ 9], 21, -343485551);
+
+ a = (a + aa) >>> 0;
+ b = (b + bb) >>> 0;
+ c = (c + cc) >>> 0;
+ d = (d + dd) >>> 0;
+ }
+
+ return crypt.endian([a, b, c, d]);
+ };
+
+ // Auxiliary functions
+ md5._ff = function (a, b, c, d, x, s, t) {
+ var n = a + (b & c | ~b & d) + (x >>> 0) + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ };
+ md5._gg = function (a, b, c, d, x, s, t) {
+ var n = a + (b & d | c & ~d) + (x >>> 0) + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ };
+ md5._hh = function (a, b, c, d, x, s, t) {
+ var n = a + (b ^ c ^ d) + (x >>> 0) + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ };
+ md5._ii = function (a, b, c, d, x, s, t) {
+ var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ };
+
+ // Package private blocksize
+ md5._blocksize = 16;
+ md5._digestsize = 16;
+
+ module.exports = function (message, options) {
+ if (message === undefined || message === null)
+ throw new Error('Illegal argument ' + message);
+
+ var digestbytes = crypt.wordsToBytes(md5(message, options));
+ return options && options.asBytes ? digestbytes :
+ options && options.asString ? bin.bytesToString(digestbytes) :
+ crypt.bytesToHex(digestbytes);
+ };
+
+ })();
+ + +/***/ }, +/* 267 */ +/***/ function(module, exports) { + + (function() { + var base64map + = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', + + crypt = { + // Bit-wise rotation left + rotl: function(n, b) { + return (n << b) | (n >>> (32 - b)); + }, + + // Bit-wise rotation right + rotr: function(n, b) { + return (n << (32 - b)) | (n >>> b); + }, + + // Swap big-endian to little-endian and vice versa + endian: function(n) { + // If number given, swap endian + if (n.constructor == Number) { + return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00; + } + + // Else, assume array and swap all items + for (var i = 0; i < n.length; i++) + n[i] = crypt.endian(n[i]); + return n; + }, + + // Generate an array of any length of random bytes + randomBytes: function(n) { + for (var bytes = []; n > 0; n--) + bytes.push(Math.floor(Math.random() * 256)); + return bytes; + }, + + // Convert a byte array to big-endian 32-bit words + bytesToWords: function(bytes) { + for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8) + words[b >>> 5] |= bytes[i] << (24 - b % 32); + return words; + }, + + // Convert big-endian 32-bit words to a byte array + wordsToBytes: function(words) { + for (var bytes = [], b = 0; b < words.length * 32; b += 8) + bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); + return bytes; + }, + + // Convert a byte array to a hex string + bytesToHex: function(bytes) { + for (var hex = [], i = 0; i < bytes.length; i++) { + hex.push((bytes[i] >>> 4).toString(16)); + hex.push((bytes[i] & 0xF).toString(16)); + } + return hex.join(''); + }, + + // Convert a hex string to a byte array + hexToBytes: function(hex) { + for (var bytes = [], c = 0; c < hex.length; c += 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; + }, + + // Convert a byte array to a base-64 string + bytesToBase64: function(bytes) { + for (var base64 = [], i = 0; i < bytes.length; i += 3) { + var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; + for (var j = 0; j < 4; j++) + if (i * 8 + j * 6 <= bytes.length * 8) + base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F)); + else + base64.push('='); + } + return base64.join(''); + }, + + // Convert a base-64 string to a byte array + base64ToBytes: function(base64) { + // Remove non-base-64 characters + base64 = base64.replace(/[^A-Z0-9+\/]/ig, ''); + + for (var bytes = [], i = 0, imod4 = 0; i < base64.length; + imod4 = ++i % 4) { + if (imod4 == 0) continue; + bytes.push(((base64map.indexOf(base64.charAt(i - 1)) + & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) + | (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2))); + } + return bytes; + } + }; + + module.exports = crypt; + })(); + + +/***/ }, +/* 268 */ +/***/ function(module, exports) { + + var charenc = { + // UTF-8 encoding + utf8: { + // Convert a string to a byte array + stringToBytes: function(str) { + return charenc.bin.stringToBytes(unescape(encodeURIComponent(str))); + }, + + // Convert a byte array to a string + bytesToString: function(bytes) { + return decodeURIComponent(escape(charenc.bin.bytesToString(bytes))); + } + }, + + // Binary encoding + bin: { + // Convert a string to a byte array + stringToBytes: function(str) { + for (var bytes = [], i = 0; i < str.length; i++) + bytes.push(str.charCodeAt(i) & 0xFF); + return bytes; + }, + + // Convert a byte array to a string + bytesToString: function(bytes) { + for (var str = [], i = 0; i < bytes.length; i++) + str.push(String.fromCharCode(bytes[i])); + return str.join(''); + } + } + }; + + module.exports = charenc; + + +/***/ }, +/* 269 */ +/***/ function(module, exports) { + + /*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> + * @license MIT + */ + + // The _isBuffer check is for Safari 5-7 support, because it's missing + // Object.prototype.constructor. Remove this eventually + module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) + } + + function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) + } + + // For Node v0.10 support. Remove this eventually. + function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) + } + + +/***/ }, +/* 270 */ +/***/ function(module, exports, __webpack_require__) { + + var { PrefsHelper } = __webpack_require__(28); + const { Services: { pref }} = __webpack_require__(30); + const { isDevelopment } = __webpack_require__(89); + + if (isDevelopment()) { + pref("devtools.debugger.client-source-maps-enabled", true); + } + + const prefs = new PrefsHelper("devtools", { + clientSourceMapsEnabled: ["Bool", "debugger.client-source-maps-enabled"], + }); + + module.exports = { prefs }; + + +/***/ }, +/* 271 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + /* global window gThreadClient setNamedTimeout services EVENTS */ + /* eslint no-shadow: 0 */ + + /** + * Redux actions for the event listeners state + * @module actions/event-listeners + */ + + var constants = __webpack_require__(251); + + var _require = __webpack_require__(244); + + var asPaused = _require.asPaused; + + var _require2 = __webpack_require__(246); + + var reportException = _require2.reportException; + + var _require3 = __webpack_require__(272); + + var Task = _require3.Task; + + // delay is in ms + + var FETCH_EVENT_LISTENERS_DELAY = 200; + + /** + * @memberof actions/event-listeners + * @static + */ + function fetchEventListeners() { + return (dispatch, getState) => { + // Make sure we"re not sending a batch of closely repeated requests. + // This can easily happen whenever new sources are fetched. + setNamedTimeout("event-listeners-fetch", FETCH_EVENT_LISTENERS_DELAY, () => { + // In case there is still a request of listeners going on (it + // takes several RDP round trips right now), make sure we wait + // on a currently running request + if (getState().eventListeners.fetchingListeners) { + dispatch({ + type: services.WAIT_UNTIL, + predicate: action => action.type === constants.FETCH_EVENT_LISTENERS && action.status === "done", + run: dispatch => dispatch(fetchEventListeners()) + }); + return; + } + + dispatch({ + type: constants.FETCH_EVENT_LISTENERS, + status: "begin" + }); + + asPaused(gThreadClient, _getListeners).then(listeners => { + // Notify that event listeners were fetched and shown in the view, + // and callback to resume the active thread if necessary. + window.emit(EVENTS.EVENT_LISTENERS_FETCHED); + + dispatch({ + type: constants.FETCH_EVENT_LISTENERS, + status: "done", + listeners: listeners + }); + }); + }); + }; + } + + var _getListeners = Task.async(function* () { + var response = yield gThreadClient.eventListeners(); + + // Make sure all the listeners are sorted by the event type, since + // they"re not guaranteed to be clustered together. + response.listeners.sort((a, b) => a.type > b.type ? 1 : -1); + + // Add all the listeners in the debugger view event linsteners container. + var fetchedDefinitions = new Map(); + var listeners = []; + for (var listener of response.listeners) { + var definitionSite = void 0; + if (fetchedDefinitions.has(listener.function.actor)) { + definitionSite = fetchedDefinitions.get(listener.function.actor); + } else if (listener.function.class == "Function") { + definitionSite = yield _getDefinitionSite(listener.function); + if (!definitionSite) { + // We don"t know where this listener comes from so don"t show it in + // the UI as breaking on it doesn"t work (bug 942899). + continue; + } + + fetchedDefinitions.set(listener.function.actor, definitionSite); + } + listener.function.url = definitionSite; + listeners.push(listener); + } + fetchedDefinitions.clear(); + + return listeners; + }); + + var _getDefinitionSite = Task.async(function* (func) { + var grip = gThreadClient.pauseGrip(func); + var response = void 0; + + try { + response = yield grip.getDefinitionSite(); + } catch (e) { + // Don't make this error fatal, it would break the entire events pane. + reportException("_getDefinitionSite", e); + return null; + } + + return response.source.url; + }); + + /** + * @memberof actions/event-listeners + * @static + * @param {string} eventNames + */ + function updateEventBreakpoints(eventNames) { + return dispatch => { + setNamedTimeout("event-breakpoints-update", 0, () => { + gThreadClient.pauseOnDOMEvents(eventNames, function () { + // Notify that event breakpoints were added/removed on the server. + window.emit(EVENTS.EVENT_BREAKPOINTS_UPDATED); + + dispatch({ + type: constants.UPDATE_EVENT_BREAKPOINTS, + eventNames: eventNames + }); + }); + }); + }; + } + + module.exports = { updateEventBreakpoints, fetchEventListeners }; + +/***/ }, +/* 272 */ +/***/ function(module, exports) { + + /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + + /** + * This object provides the public module functions. + */ + var Task = { + // XXX: Not sure if this works in all cases... + async: function (task) { + return function () { + return Task.spawn(task, this, arguments); + }; + }, + + /** + * Creates and starts a new task. + * @param task A generator function + * @return A promise, resolved when the task terminates + */ + spawn: function (task, scope, args) { + return new Promise(function (resolve, reject) { + var iterator = task.apply(scope, args); + + var callNext = lastValue => { + var iteration = iterator.next(lastValue); + Promise.resolve(iteration.value).then(value => { + if (iteration.done) { + resolve(value); + } else { + callNext(value); + } + }).catch(error => { + reject(error); + iterator.throw(error); + }); + }; + + callNext(undefined); + }); + } + }; + + module.exports = { Task }; + +/***/ }, +/* 273 */ +/***/ function(module, exports, __webpack_require__) { + + var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + + function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + /** + * Redux actions for the sources state + * @module actions/sources + */ + + var defer = __webpack_require__(243); + + var _require = __webpack_require__(242); + + var PROMISE = _require.PROMISE; + + var assert = __webpack_require__(247); + + var _require2 = __webpack_require__(274); + + var updateFrameLocations = _require2.updateFrameLocations; + + var _require3 = __webpack_require__(264); + + var getOriginalURLs = _require3.getOriginalURLs; + var getOriginalSourceText = _require3.getOriginalSourceText; + var generatedToOriginalId = _require3.generatedToOriginalId; + var isOriginalId = _require3.isOriginalId; + var isGeneratedId = _require3.isGeneratedId; + var applySourceMap = _require3.applySourceMap; + var shouldSourceMap = _require3.shouldSourceMap; + + var _require4 = __webpack_require__(276); + + var prettyPrint = _require4.prettyPrint; + + + var constants = __webpack_require__(251); + + var _require5 = __webpack_require__(89); + + var isEnabled = _require5.isEnabled; + + var _require6 = __webpack_require__(279); + + var removeDocument = _require6.removeDocument; + + var _require7 = __webpack_require__(259); + + var getSource = _require7.getSource; + var getSourceByURL = _require7.getSourceByURL; + var getSourceText = _require7.getSourceText; + var getPendingSelectedLocation = _require7.getPendingSelectedLocation; + var getFrames = _require7.getFrames; + + + /** + * Handler for the debugger client's unsolicited newSource notification. + * @memberof actions/sources + * @static + */ + function newSource(source) { + return (_ref) => { + var dispatch = _ref.dispatch; + var getState = _ref.getState; + + if (shouldSourceMap()) { + dispatch(loadSourceMap(source)); + } + + dispatch({ + type: constants.ADD_SOURCE, + source + }); + + // If a request has been made to show this source, go ahead and + // select it. + var pendingLocation = getPendingSelectedLocation(getState()); + if (pendingLocation && pendingLocation.url === source.url) { + dispatch(selectSource(source.id, { line: pendingLocation.line })); + } + }; + } + + function newSources(sources) { + return (_ref2) => { + var dispatch = _ref2.dispatch; + var getState = _ref2.getState; + + sources.filter(source => !getSource(getState(), source.id)).forEach(source => dispatch(newSource(source))); + }; + } + + /** + * @memberof actions/sources + * @static + */ + function loadSourceMap(generatedSource) { + return (() => { + var _ref3 = _asyncToGenerator(function* (_ref4) { + var dispatch = _ref4.dispatch; + var getState = _ref4.getState; + + var urls = yield getOriginalURLs(generatedSource); + if (!urls) { + // If this source doesn't have a sourcemap, do nothing. + return; + } + + var originalSources = urls.map(function (originalUrl) { + return { + url: originalUrl, + id: generatedToOriginalId(generatedSource.id, originalUrl), + isPrettyPrinted: false + }; + }); + + originalSources.forEach(function (s) { + return dispatch(newSource(s)); + }); + }); + + return function (_x) { + return _ref3.apply(this, arguments); + }; + })(); + } + + /** + * Deterministically select a source that has a given URL. This will + * work regardless of the connection status or if the source exists + * yet. This exists mostly for external things to interact with the + * debugger. + * + * @memberof actions/sources + * @static + */ + function selectSourceURL(url) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + return (_ref5) => { + var dispatch = _ref5.dispatch; + var getState = _ref5.getState; + + var source = getSourceByURL(getState(), url); + if (source) { + dispatch(selectSource(source.get("id"), options)); + } else { + dispatch({ + type: constants.SELECT_SOURCE_URL, + url: url, + tabIndex: options.tabIndex, + line: options.line + }); + } + }; + } + + /** + * @memberof actions/sources + * @static + */ + function selectSource(id) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + return (_ref6) => { + var dispatch = _ref6.dispatch; + var getState = _ref6.getState; + var client = _ref6.client; + + if (!client) { + // No connection, do nothing. This happens when the debugger is + // shut down too fast and it tries to display a default source. + return; + } + + var source = getSource(getState(), id).toJS(); + + // Make sure to start a request to load the source text. + dispatch(loadSourceText(source)); + + dispatch({ type: constants.TOGGLE_FILE_SEARCH, searchOn: false }); + + dispatch({ + type: constants.SELECT_SOURCE, + source: source, + tabIndex: options.tabIndex, + line: options.line + }); + }; + } + + /** + * @memberof actions/sources + * @static + */ + function closeTab(id) { + removeDocument(id); + return { + type: constants.CLOSE_TAB, + id: id + }; + } + + /** + * Toggle the pretty printing of a source's text. All subsequent calls to + * |getText| will return the pretty-toggled text. Nothing will happen for + * non-javascript files. + * + * @memberof actions/sources + * @static + * @param string id The source form from the RDP. + * @returns Promise + * A promise that resolves to [aSource, prettyText] or rejects to + * [aSource, error]. + */ + function togglePrettyPrint(sourceId) { + return (_ref7) => { + var dispatch = _ref7.dispatch; + var getState = _ref7.getState; + var client = _ref7.client; + + var source = getSource(getState(), sourceId).toJS(); + var sourceText = getSourceText(getState(), sourceId).toJS(); + + if (!isEnabled("prettyPrint") || sourceText.loading) { + return {}; + } + + assert(isGeneratedId(sourceId), "Pretty-printing only allowed on generated sources"); + + var url = source.url + ":formatted"; + var id = generatedToOriginalId(source.id, url); + var originalSource = { url, id, isPrettyPrinted: false }; + dispatch({ + type: constants.ADD_SOURCE, + source: originalSource + }); + + return dispatch({ + type: constants.TOGGLE_PRETTY_PRINT, + source: originalSource, + [PROMISE]: _asyncToGenerator(function* () { + var _ref9 = yield prettyPrint({ + source, sourceText, url + }); + + var code = _ref9.code; + var mappings = _ref9.mappings; + + yield applySourceMap(source.id, url, code, mappings); + + var frames = yield updateFrameLocations(getFrames(getState())); + dispatch(selectSource(originalSource.id)); + + return { + text: code, + contentType: "text/javascript", + frames + }; + })() + }); + }; + } + + /** + * @memberof actions/sources + * @static + */ + function loadSourceText(source) { + return (_ref10) => { + var dispatch = _ref10.dispatch; + var getState = _ref10.getState; + var client = _ref10.client; + + // Fetch the source text only once. + var textInfo = getSourceText(getState(), source.id); + if (textInfo) { + // It's already loaded or is loading + return Promise.resolve(textInfo); + } + + return dispatch({ + type: constants.LOAD_SOURCE_TEXT, + source: source, + [PROMISE]: _asyncToGenerator(function* () { + if (isOriginalId(source.id)) { + return yield getOriginalSourceText(source); + } + + var response = yield client.sourceContents(source.id); + return { + text: response.source, + contentType: response.contentType || "text/javascript" + }; + + // Automatically pretty print if enabled and the test is + // detected to be "minified" + // if (Prefs.autoPrettyPrint && + // !source.isPrettyPrinted && + // SourceUtils.isMinified(source.id, response.source)) { + // dispatch(togglePrettyPrint(source)); + // } + })() + }); + }; + } + + // delay is in ms + var FETCH_SOURCE_RESPONSE_DELAY = 200; + + /** + * Starts fetching all the sources, silently. + * + * @memberof actions/sources + * @static + * @param array actors + * The urls for the sources to fetch. If fetching a source's text + * takes too long, it will be discarded. + * @returns {Promise} + * A promise that is resolved after source texts have been fetched. + */ + function getTextForSources(actors) { + return (_ref12) => { + var dispatch = _ref12.dispatch; + var getState = _ref12.getState; + + var deferred = defer(); + var pending = new Set(actors); + + var fetched = []; + + // Can't use promise.all, because if one fetch operation is rejected, then + // everything is considered rejected, thus no other subsequent source will + // be getting fetched. We don't want that. Something like Q's allSettled + // would work like a charm here. + + // Try to fetch as many sources as possible. + + var _loop = function (actor) { + var source = getSource(getState(), actor); + dispatch(loadSourceText(source)).then((_ref21) => { + var text = _ref21.text; + var contentType = _ref21.contentType; + + onFetch([source, text, contentType]); + }, err => { + onError(source, err); + }); + }; + + for (var actor of actors) { + _loop(actor); + } + + setTimeout(onTimeout, FETCH_SOURCE_RESPONSE_DELAY); + + /* Called if fetching a source takes too long. */ + function onTimeout() { + pending = new Set(); + maybeFinish(); + } + + /* Called if fetching a source finishes successfully. */ + function onFetch(_ref13) { + var _ref14 = _slicedToArray(_ref13, 3); + + var aSource = _ref14[0]; + var aText = _ref14[1]; + var aContentType = _ref14[2]; + + // If fetching the source has previously timed out, discard it this time. + if (!pending.has(aSource.actor)) { + return; + } + pending.delete(aSource.actor); + fetched.push([aSource.actor, aText, aContentType]); + maybeFinish(); + } + + /* Called if fetching a source failed because of an error. */ + function onError(_ref15) { + var _ref16 = _slicedToArray(_ref15, 2); + + var aSource = _ref16[0]; + var aError = _ref16[1]; + + pending.delete(aSource.actor); + maybeFinish(); + } + + /* Called every time something interesting + * happens while fetching sources. + */ + function maybeFinish() { + if (pending.size == 0) { + // Sort the fetched sources alphabetically by their url. + if (deferred) { + deferred.resolve(fetched.sort((_ref17, _ref18) => { + var _ref20 = _slicedToArray(_ref17, 1); + + var aFirst = _ref20[0]; + + var _ref19 = _slicedToArray(_ref18, 1); + + var aSecond = _ref19[0]; + return aFirst > aSecond ? -1 : 1; + })); + } + } + } + + return deferred.promise; + }; + } + + module.exports = { + newSource, + newSources, + selectSource, + selectSourceURL, + closeTab, + togglePrettyPrint, + loadSourceText, + getTextForSources + }; + +/***/ }, +/* 274 */ +/***/ function(module, exports, __webpack_require__) { + + var _require = __webpack_require__(275); + + var Frame = _require.Frame; + + var _require2 = __webpack_require__(264); + + var getOriginalLocation = _require2.getOriginalLocation; + + + function updateFrameLocations(frames) { + if (!frames) { + return Promise.resolve(frames); + } + return Promise.all(frames.map(frame => { + return getOriginalLocation(frame.location).then(loc => { + return Frame.update(frame, { + $merge: { location: loc } + }); + }); + })); + } + + module.exports = { + updateFrameLocations + }; + +/***/ }, +/* 275 */ +/***/ function(module, exports, __webpack_require__) { + + var t = __webpack_require__(146); + + var Location = t.struct({ + sourceId: t.String, + line: t.Number, + column: t.union([t.Number, t.Nil]) + }, "Location"); + + var Frame = t.struct({ + id: t.String, + displayName: t.String, + location: Location, + this: t.union([t.Object, t.Nil]), + scope: t.union([t.Object, t.Nil]) + }, "Frame"); + + module.exports = { + Frame + }; + +/***/ }, +/* 276 */ +/***/ function(module, exports, __webpack_require__) { + + var prettyPrint = (() => { + var _ref = _asyncToGenerator(function* (_ref2) { + var source = _ref2.source; + var sourceText = _ref2.sourceText; + var url = _ref2.url; + + var contentType = sourceText ? sourceText.contentType : null; + var indent = 2; + + assert(isJavaScript(source.url, contentType), "Can't prettify non-javascript files."); + + return yield _prettyPrint({ + url, + indent, + source: sourceText.text + }); + }); + + return function prettyPrint(_x) { + return _ref.apply(this, arguments); + }; + })(); + + function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + + var _require = __webpack_require__(89); + + var getValue = _require.getValue; + + var _require2 = __webpack_require__(244); + + var workerTask = _require2.workerTask; + + var _require3 = __webpack_require__(277); + + var isJavaScript = _require3.isJavaScript; + + var assert = __webpack_require__(247); + + var prettyPrintWorker = new Worker(getValue("baseWorkerURL") + "pretty-print-worker.js"); + + function destroyWorker() { + prettyPrintWorker.terminate(); + prettyPrintWorker = null; + } + + var _prettyPrint = workerTask(prettyPrintWorker, "prettyPrint"); + + module.exports = { + prettyPrint, + destroyWorker + }; + +/***/ }, +/* 277 */ +/***/ function(module, exports, __webpack_require__) { + + + + /** + * Utils for working with Source URLs + * @module utils/source + */ + + var _require = __webpack_require__(244); + + var endTruncateStr = _require.endTruncateStr; + + var _require2 = __webpack_require__(278); + + var basename = _require2.basename; + + + /** + * Trims the query part or reference identifier of a url string, if necessary. + * + * @memberof utils/source + * @static + */ + function trimUrlQuery(url) { + var length = url.length; + var q1 = url.indexOf("?"); + var q2 = url.indexOf("&"); + var q3 = url.indexOf("#"); + var q = Math.min(q1 != -1 ? q1 : length, q2 != -1 ? q2 : length, q3 != -1 ? q3 : length); + + return url.slice(0, q); + } + + /** + * Returns true if the specified url and/or content type are specific to + * javascript files. + * + * @return boolean + * True if the source is likely javascript. + * + * @memberof utils/source + * @static + */ + function isJavaScript(url) { + var contentType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + return url && /\.(jsm|js)?$/.test(trimUrlQuery(url)) || contentType.includes("javascript"); + } + + /** + * @memberof utils/source + * @static + */ + function isPretty(source) { + return source.url ? /formatted$/.test(source.url) : false; + } + + /** + * Show a source url's filename. + * If the source does not have a url, use the source id. + * + * @memberof utils/source + * @static + */ + function getFilename(source) { + var url = source.url; + var id = source.id; + + if (!url) { + var sourceId = id.split("/")[1]; + return `SOURCE${ sourceId }`; + } + + var name = basename(source.url || "") || "(index)"; + return endTruncateStr(name, 50); + } + + module.exports = { + isJavaScript, + isPretty, + getFilename + }; + +/***/ }, +/* 278 */ +/***/ function(module, exports) { + + function basename(path) { + return path.split("/").pop(); + } + + function dirname(path) { + var idx = path.lastIndexOf("/"); + return path.slice(0, idx); + } + + function isURL(str) { + return str.indexOf("://") !== -1; + } + + function isAbsolute(str) { + return str[0] === "/"; + } + + function join(base, dir) { + return base + "/" + dir; + } + + module.exports = { + basename, dirname, isURL, isAbsolute, join + }; + +/***/ }, +/* 279 */ +/***/ function(module, exports) { + + var sourceDocs = {}; + + function getDocument(key) { + return sourceDocs[key]; + } + + function setDocument(key, doc) { + sourceDocs[key] = doc; + } + + function removeDocument(key) { + delete sourceDocs[key]; + } + + function clearDocuments() { + sourceDocs = {}; + } + + module.exports = { + getDocument, + setDocument, + removeDocument, + clearDocuments + }; + +/***/ }, +/* 280 */ +/***/ function(module, exports, __webpack_require__) { + + function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + + var constants = __webpack_require__(251); + + var _require = __webpack_require__(273); + + var selectSource = _require.selectSource; + + var _require2 = __webpack_require__(242); + + var PROMISE = _require2.PROMISE; + + var _require3 = __webpack_require__(259); + + var getExpressions = _require3.getExpressions; + var getSelectedFrame = _require3.getSelectedFrame; + + var _require4 = __webpack_require__(274); + + var updateFrameLocations = _require4.updateFrameLocations; + + /** + * Redux actions for the pause state + * @module actions/pause + */ + + /** + * Debugger has just resumed + * + * @memberof actions/pause + * @static + */ + + function resumed() { + return (_ref) => { + var dispatch = _ref.dispatch; + var client = _ref.client; + + return dispatch({ + type: constants.RESUME, + value: undefined + }); + }; + } + + /** + * Debugger has just paused + * + * @param {object} pauseInfo + * @memberof actions/pause + * @static + */ + function paused(pauseInfo) { + return (() => { + var _ref2 = _asyncToGenerator(function* (_ref3) { + var dispatch = _ref3.dispatch; + var getState = _ref3.getState; + var client = _ref3.client; + var frames = pauseInfo.frames; + var why = pauseInfo.why; + + frames = yield updateFrameLocations(frames); + var frame = frames[0]; + + dispatch({ + type: constants.PAUSED, + pauseInfo: { why, frame }, + frames: frames, + selectedFrameId: frame.id + }); + + dispatch(evaluateExpressions()); + + dispatch(selectSource(frame.location.sourceId, { line: frame.location.line })); + }); + + return function (_x) { + return _ref2.apply(this, arguments); + }; + })(); + } + + /** + * + * @memberof actions/pause + * @static + */ + function pauseOnExceptions(shouldPauseOnExceptions, shouldIgnoreCaughtExceptions) { + return (_ref4) => { + var dispatch = _ref4.dispatch; + var client = _ref4.client; + + dispatch({ + type: constants.PAUSE_ON_EXCEPTIONS, + shouldPauseOnExceptions, + shouldIgnoreCaughtExceptions, + [PROMISE]: client.pauseOnExceptions(shouldPauseOnExceptions, shouldIgnoreCaughtExceptions) + }); + }; + } + + /** + * Debugger commands like stepOver, stepIn, stepUp + * + * @param string $0.type + * @memberof actions/pause + * @static + */ + function command(_ref5) { + var type = _ref5.type; + + return (_ref6) => { + var dispatch = _ref6.dispatch; + var client = _ref6.client; + + // execute debugger thread command e.g. stepIn, stepOver + client[type](); + + return dispatch({ + type: constants.COMMAND, + value: undefined + }); + }; + } + + /** + * StepIn + * @memberof actions/pause + * @static + * @returns {Function} {@link command} + */ + function stepIn() { + return command({ type: "stepIn" }); + } + + /** + * stepOver + * @memberof actions/pause + * @static + * @returns {Function} {@link command} + */ + function stepOver() { + return command({ type: "stepOver" }); + } + + /** + * stepOut + * @memberof actions/pause + * @static + * @returns {Function} {@link command} + */ + function stepOut() { + return command({ type: "stepOut" }); + } + + /** + * resume + * @memberof actions/pause + * @static + * @returns {Function} {@link command} + */ + function resume() { + return command({ type: "resume" }); + } + + /** + * Debugger breakOnNext command. + * It's different from the comand action because we also want to + * highlight the pause icon. + * + * @memberof actions/pause + * @static + */ + function breakOnNext() { + return (_ref7) => { + var dispatch = _ref7.dispatch; + var client = _ref7.client; + + client.breakOnNext(); + + return dispatch({ + type: constants.BREAK_ON_NEXT, + value: true + }); + }; + } + + /** + * Select a frame + * + * @param frame + * @memberof actions/pause + * @static + */ + function selectFrame(frame) { + return (_ref8) => { + var dispatch = _ref8.dispatch; + + dispatch(selectSource(frame.location.sourceId, { line: frame.location.line })); + dispatch({ + type: constants.SELECT_FRAME, + frame + }); + }; + } + + /** + * Load an object. + * + * @param grip + * TODO: Right now this if Firefox specific and is not implemented + * for Chrome, which is why it takes a grip. + * @memberof actions/pause + * @static + */ + function loadObjectProperties(grip) { + return (_ref9) => { + var dispatch = _ref9.dispatch; + var client = _ref9.client; + + dispatch({ + type: constants.LOAD_OBJECT_PROPERTIES, + objectId: grip.actor, + [PROMISE]: client.getProperties(grip) + }); + }; + } + + /** + * Add expression for debugger to watch + * + * @param {object} expression + * @param {number} expression.id + * @memberof actions/pause + * @static + */ + function addExpression(expression) { + return (_ref10) => { + var dispatch = _ref10.dispatch; + var getState = _ref10.getState; + + var id = expression.id !== undefined ? parseInt(expression.id, 10) : getExpressions(getState()).toSeq().size++; + dispatch({ + type: constants.ADD_EXPRESSION, + id: id, + input: expression.input + }); + dispatch(evaluateExpressions()); + }; + } + + /** + * + * @param {object} expression + * @param {number} expression.id + * @memberof actions/pause + * @static + */ + function updateExpression(expression) { + return (_ref11) => { + var dispatch = _ref11.dispatch; + + dispatch({ + type: constants.UPDATE_EXPRESSION, + id: expression.id, + input: expression.input + }); + }; + } + + /** + * + * @param {object} expression + * @param {number} expression.id + * @memberof actions/pause + * @static + */ + function deleteExpression(expression) { + return (_ref12) => { + var dispatch = _ref12.dispatch; + + dispatch({ + type: constants.DELETE_EXPRESSION, + id: expression.id + }); + }; + } + + /** + * + * @memberof actions/pause + * @static + */ + function evaluateExpressions() { + return (() => { + var _ref13 = _asyncToGenerator(function* (_ref14) { + var dispatch = _ref14.dispatch; + var getState = _ref14.getState; + var client = _ref14.client; + + var selectedFrame = getSelectedFrame(getState()); + if (!selectedFrame) { + return; + } + + var frameId = selectedFrame.id; + + for (var expression of getExpressions(getState())) { + yield dispatch({ + type: constants.EVALUATE_EXPRESSION, + id: expression.id, + input: expression.input, + [PROMISE]: client.evaluate(expression.input, { frameId }) + }); + } + }); + + return function (_x2) { + return _ref13.apply(this, arguments); + }; + })(); + } + + module.exports = { + addExpression, + updateExpression, + deleteExpression, + evaluateExpressions, + resumed, + paused, + pauseOnExceptions, + command, + stepIn, + stepOut, + stepOver, + resume, + breakOnNext, + selectFrame, + loadObjectProperties + }; + +/***/ }, +/* 281 */ +/***/ function(module, exports, __webpack_require__) { + + var constants = __webpack_require__(251); + + var _require = __webpack_require__(264); + + var clearSourceMaps = _require.clearSourceMaps; + + var _require2 = __webpack_require__(279); + + var clearDocuments = _require2.clearDocuments; + + /** + * Redux actions for the navigation state + * @module actions/navigation + */ + + /** + * @memberof actions/navigation + * @static + */ + + function willNavigate() { + clearSourceMaps(); + clearDocuments(); + + return { type: constants.NAVIGATE }; + } + + /** + * @memberof actions/navigation + * @static + */ + function navigated() { + return (_ref) => { + // We need to load all the sources again because they might have + // come from bfcache, so we won't get a `newSource` notification. + // + // TODO: This seems to be buggy on the debugger server side. When + // the page is loaded from bfcache, we still get sources from the + // *previous* page as well. For now, emulate the current debugger + // behavior by not showing sources loaded by bfcache. + // return dispatch(sources.loadSources()); + + var dispatch = _ref.dispatch; + }; + } + + module.exports = { + willNavigate, + navigated + }; + +/***/ }, +/* 282 */ +/***/ function(module, exports, __webpack_require__) { + + var constants = __webpack_require__(251); + + function toggleFileSearch(searchOn) { + return { + type: constants.TOGGLE_FILE_SEARCH, + searchOn + }; + } + + module.exports = { + toggleFileSearch + }; + +/***/ }, +/* 283 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 284 */, +/* 285 */, +/* 286 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 287 */, +/* 288 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 289 */, +/* 290 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 291 */, +/* 292 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + var createFactory = React.createFactory; + + var _require = __webpack_require__(19); + + var connect = _require.connect; + + var _require2 = __webpack_require__(3); + + var bindActionCreators = _require2.bindActionCreators; + + var actions = __webpack_require__(262); + + var _require3 = __webpack_require__(259); + + var getSources = _require3.getSources; + var getSelectedSource = _require3.getSelectedSource; + var getFileSearchState = _require3.getFileSearchState; + + var _require4 = __webpack_require__(244); + + var endTruncateStr = _require4.endTruncateStr; + + var _require5 = __webpack_require__(293); + + var parseURL = _require5.parse; + + var _require6 = __webpack_require__(277); + + var isPretty = _require6.isPretty; + + + __webpack_require__(298); + + var Autocomplete = createFactory(__webpack_require__(300)); + + function searchResults(sources) { + function getSourcePath(source) { + var _parseURL = parseURL(source.get("url")); + + var path = _parseURL.path; + var href = _parseURL.href; + // for URLs like "about:home" the path is null so we pass the full href + + return endTruncateStr(path || href, 50); + } + + return sources.valueSeq().filter(source => !isPretty(source.toJS()) && source.get("url")).map(source => ({ + value: getSourcePath(source), + title: getSourcePath(source).split("/").pop(), + subtitle: getSourcePath(source), + id: source.get("id") + })).toJS(); + } + + var Search = React.createClass({ + propTypes: { + sources: PropTypes.object, + selectSource: PropTypes.func, + selectedSource: PropTypes.object, + toggleFileSearch: PropTypes.func, + searchOn: PropTypes.bool + }, + + contextTypes: { + shortcuts: PropTypes.object + }, + + displayName: "Search", + + getInitialState() { + return { + inputValue: "" + }; + }, + + componentWillUnmount() { + var shortcuts = this.context.shortcuts; + shortcuts.off("CmdOrCtrl+P", this.toggle); + shortcuts.off("Escape", this.onEscape); + }, + + componentDidMount() { + var shortcuts = this.context.shortcuts; + shortcuts.on("CmdOrCtrl+P", this.toggle); + shortcuts.on("Escape", this.onEscape); + }, + + toggle(key, e) { + e.preventDefault(); + this.props.toggleFileSearch(!this.props.searchOn); + }, + + onEscape(shortcut, e) { + if (this.props.searchOn) { + e.preventDefault(); + this.setState({ inputValue: "" }); + this.props.toggleFileSearch(false); + } + }, + + close() { + var inputValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ""; + + this.setState({ inputValue }); + this.props.toggleFileSearch(false); + }, + + render() { + return this.props.searchOn ? dom.div({ className: "search-container" }, Autocomplete({ + selectItem: result => { + this.props.selectSource(result.id); + this.setState({ inputValue: "" }); + this.props.toggleFileSearch(false); + }, + handleClose: this.close, + items: searchResults(this.props.sources), + inputValue: this.state.inputValue + })) : null; + } + + }); + + module.exports = connect(state => ({ + sources: getSources(state), + selectedSource: getSelectedSource(state), + searchOn: getFileSearchState(state) + }), dispatch => bindActionCreators(actions, dispatch))(Search); + +/***/ }, +/* 293 */ +/***/ function(module, exports, __webpack_require__) { + + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + var punycode = __webpack_require__(294); + + exports.parse = urlParse; + exports.resolve = urlResolve; + exports.resolveObject = urlResolveObject; + exports.format = urlFormat; + + exports.Url = Url; + + function Url() { + this.protocol = null; + this.slashes = null; + this.auth = null; + this.host = null; + this.port = null; + this.hostname = null; + this.hash = null; + this.search = null; + this.query = null; + this.pathname = null; + this.path = null; + this.href = null; + } + + // Reference: RFC 3986, RFC 1808, RFC 2396 + + // define these here so at least they only have to be + // compiled once on the first module load. + var protocolPattern = /^([a-z0-9.+-]+:)/i, + portPattern = /:[0-9]*$/, + + // RFC 2396: characters reserved for delimiting URLs. + // We actually just auto-escape these. + delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], + + // RFC 2396: characters not allowed for various reasons. + unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), + + // Allowed by RFCs, but cause of XSS attacks. Always escape these. + autoEscape = ['\''].concat(unwise), + // Characters that are never ever allowed in a hostname. + // Note that any invalid chars are also handled, but these + // are the ones that are *expected* to be seen, so we fast-path + // them. + nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), + hostEndingChars = ['/', '?', '#'], + hostnameMaxLen = 255, + hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, + hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, + // protocols that can allow "unsafe" and "unwise" chars. + unsafeProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that never have a hostname. + hostlessProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that always contain a // bit. + slashedProtocol = { + 'http': true, + 'https': true, + 'ftp': true, + 'gopher': true, + 'file': true, + 'http:': true, + 'https:': true, + 'ftp:': true, + 'gopher:': true, + 'file:': true + }, + querystring = __webpack_require__(295); + + function urlParse(url, parseQueryString, slashesDenoteHost) { + if (url && isObject(url) && url instanceof Url) return url; + + var u = new Url; + u.parse(url, parseQueryString, slashesDenoteHost); + return u; + } + + Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { + if (!isString(url)) { + throw new TypeError("Parameter 'url' must be a string, not " + typeof url); + } + + var rest = url; + + // trim before proceeding. + // This is to support parse stuff like " http://foo.com \n" + rest = rest.trim(); + + var proto = protocolPattern.exec(rest); + if (proto) { + proto = proto[0]; + var lowerProto = proto.toLowerCase(); + this.protocol = lowerProto; + rest = rest.substr(proto.length); + } + + // figure out if it's got a host + // user@server is *always* interpreted as a hostname, and url + // resolution will treat //foo/bar as host=foo,path=bar because that's + // how the browser resolves relative URLs. + if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { + var slashes = rest.substr(0, 2) === '//'; + if (slashes && !(proto && hostlessProtocol[proto])) { + rest = rest.substr(2); + this.slashes = true; + } + } + + if (!hostlessProtocol[proto] && + (slashes || (proto && !slashedProtocol[proto]))) { + + // there's a hostname. + // the first instance of /, ?, ;, or # ends the host. + // + // If there is an @ in the hostname, then non-host chars *are* allowed + // to the left of the last @ sign, unless some host-ending character + // comes *before* the @-sign. + // URLs are obnoxious. + // + // ex: + // http://a@b@c/ => user:a@b host:c + // http://a@b?@c => user:a host:c path:/?@c + + // v0.12 TODO(isaacs): This is not quite how Chrome does things. + // Review our test case against browsers more comprehensively. + + // find the first instance of any hostEndingChars + var hostEnd = -1; + for (var i = 0; i < hostEndingChars.length; i++) { + var hec = rest.indexOf(hostEndingChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + + // at this point, either we have an explicit point where the + // auth portion cannot go past, or the last @ char is the decider. + var auth, atSign; + if (hostEnd === -1) { + // atSign can be anywhere. + atSign = rest.lastIndexOf('@'); + } else { + // atSign must be in auth portion. + // http://a@b/c@d => host:b auth:a path:/c@d + atSign = rest.lastIndexOf('@', hostEnd); + } + + // Now we have a portion which is definitely the auth. + // Pull that off. + if (atSign !== -1) { + auth = rest.slice(0, atSign); + rest = rest.slice(atSign + 1); + this.auth = decodeURIComponent(auth); + } + + // the host is the remaining to the left of the first non-host char + hostEnd = -1; + for (var i = 0; i < nonHostChars.length; i++) { + var hec = rest.indexOf(nonHostChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + // if we still have not hit it, then the entire thing is a host. + if (hostEnd === -1) + hostEnd = rest.length; + + this.host = rest.slice(0, hostEnd); + rest = rest.slice(hostEnd); + + // pull out port. + this.parseHost(); + + // we've indicated that there is a hostname, + // so even if it's empty, it has to be present. + this.hostname = this.hostname || ''; + + // if hostname begins with [ and ends with ] + // assume that it's an IPv6 address. + var ipv6Hostname = this.hostname[0] === '[' && + this.hostname[this.hostname.length - 1] === ']'; + + // validate a little. + if (!ipv6Hostname) { + var hostparts = this.hostname.split(/\./); + for (var i = 0, l = hostparts.length; i < l; i++) { + var part = hostparts[i]; + if (!part) continue; + if (!part.match(hostnamePartPattern)) { + var newpart = ''; + for (var j = 0, k = part.length; j < k; j++) { + if (part.charCodeAt(j) > 127) { + // we replace non-ASCII char with a temporary placeholder + // we need this to make sure size of hostname is not + // broken by replacing non-ASCII by nothing + newpart += 'x'; + } else { + newpart += part[j]; + } + } + // we test again with ASCII char only + if (!newpart.match(hostnamePartPattern)) { + var validParts = hostparts.slice(0, i); + var notHost = hostparts.slice(i + 1); + var bit = part.match(hostnamePartStart); + if (bit) { + validParts.push(bit[1]); + notHost.unshift(bit[2]); + } + if (notHost.length) { + rest = '/' + notHost.join('.') + rest; + } + this.hostname = validParts.join('.'); + break; + } + } + } + } + + if (this.hostname.length > hostnameMaxLen) { + this.hostname = ''; + } else { + // hostnames are always lower case. + this.hostname = this.hostname.toLowerCase(); + } + + if (!ipv6Hostname) { + // IDNA Support: Returns a puny coded representation of "domain". + // It only converts the part of the domain name that + // has non ASCII characters. I.e. it dosent matter if + // you call it with a domain that already is in ASCII. + var domainArray = this.hostname.split('.'); + var newOut = []; + for (var i = 0; i < domainArray.length; ++i) { + var s = domainArray[i]; + newOut.push(s.match(/[^A-Za-z0-9_-]/) ? + 'xn--' + punycode.encode(s) : s); + } + this.hostname = newOut.join('.'); + } + + var p = this.port ? ':' + this.port : ''; + var h = this.hostname || ''; + this.host = h + p; + this.href += this.host; + + // strip [ and ] from the hostname + // the host field still retains them, though + if (ipv6Hostname) { + this.hostname = this.hostname.substr(1, this.hostname.length - 2); + if (rest[0] !== '/') { + rest = '/' + rest; + } + } + } + + // now rest is set to the post-host stuff. + // chop off any delim chars. + if (!unsafeProtocol[lowerProto]) { + + // First, make 100% sure that any "autoEscape" chars get + // escaped, even if encodeURIComponent doesn't think they + // need to be. + for (var i = 0, l = autoEscape.length; i < l; i++) { + var ae = autoEscape[i]; + var esc = encodeURIComponent(ae); + if (esc === ae) { + esc = escape(ae); + } + rest = rest.split(ae).join(esc); + } + } + + + // chop off from the tail first. + var hash = rest.indexOf('#'); + if (hash !== -1) { + // got a fragment string. + this.hash = rest.substr(hash); + rest = rest.slice(0, hash); + } + var qm = rest.indexOf('?'); + if (qm !== -1) { + this.search = rest.substr(qm); + this.query = rest.substr(qm + 1); + if (parseQueryString) { + this.query = querystring.parse(this.query); + } + rest = rest.slice(0, qm); + } else if (parseQueryString) { + // no query string, but parseQueryString still requested + this.search = ''; + this.query = {}; + } + if (rest) this.pathname = rest; + if (slashedProtocol[lowerProto] && + this.hostname && !this.pathname) { + this.pathname = '/'; + } + + //to support http.request + if (this.pathname || this.search) { + var p = this.pathname || ''; + var s = this.search || ''; + this.path = p + s; + } + + // finally, reconstruct the href based on what has been validated. + this.href = this.format(); + return this; + }; + + // format a parsed object into a url string + function urlFormat(obj) { + // ensure it's an object, and not a string url. + // If it's an obj, this is a no-op. + // this way, you can call url_format() on strings + // to clean up potentially wonky urls. + if (isString(obj)) obj = urlParse(obj); + if (!(obj instanceof Url)) return Url.prototype.format.call(obj); + return obj.format(); + } + + Url.prototype.format = function() { + var auth = this.auth || ''; + if (auth) { + auth = encodeURIComponent(auth); + auth = auth.replace(/%3A/i, ':'); + auth += '@'; + } + + var protocol = this.protocol || '', + pathname = this.pathname || '', + hash = this.hash || '', + host = false, + query = ''; + + if (this.host) { + host = auth + this.host; + } else if (this.hostname) { + host = auth + (this.hostname.indexOf(':') === -1 ? + this.hostname : + '[' + this.hostname + ']'); + if (this.port) { + host += ':' + this.port; + } + } + + if (this.query && + isObject(this.query) && + Object.keys(this.query).length) { + query = querystring.stringify(this.query); + } + + var search = this.search || (query && ('?' + query)) || ''; + + if (protocol && protocol.substr(-1) !== ':') protocol += ':'; + + // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. + // unless they had them to begin with. + if (this.slashes || + (!protocol || slashedProtocol[protocol]) && host !== false) { + host = '//' + (host || ''); + if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; + } else if (!host) { + host = ''; + } + + if (hash && hash.charAt(0) !== '#') hash = '#' + hash; + if (search && search.charAt(0) !== '?') search = '?' + search; + + pathname = pathname.replace(/[?#]/g, function(match) { + return encodeURIComponent(match); + }); + search = search.replace('#', '%23'); + + return protocol + host + pathname + search + hash; + }; + + function urlResolve(source, relative) { + return urlParse(source, false, true).resolve(relative); + } + + Url.prototype.resolve = function(relative) { + return this.resolveObject(urlParse(relative, false, true)).format(); + }; + + function urlResolveObject(source, relative) { + if (!source) return relative; + return urlParse(source, false, true).resolveObject(relative); + } + + Url.prototype.resolveObject = function(relative) { + if (isString(relative)) { + var rel = new Url(); + rel.parse(relative, false, true); + relative = rel; + } + + var result = new Url(); + Object.keys(this).forEach(function(k) { + result[k] = this[k]; + }, this); + + // hash is always overridden, no matter what. + // even href="" will remove it. + result.hash = relative.hash; + + // if the relative url is empty, then there's nothing left to do here. + if (relative.href === '') { + result.href = result.format(); + return result; + } + + // hrefs like //foo/bar always cut to the protocol. + if (relative.slashes && !relative.protocol) { + // take everything except the protocol from relative + Object.keys(relative).forEach(function(k) { + if (k !== 'protocol') + result[k] = relative[k]; + }); + + //urlParse appends trailing / to urls like http://www.example.com + if (slashedProtocol[result.protocol] && + result.hostname && !result.pathname) { + result.path = result.pathname = '/'; + } + + result.href = result.format(); + return result; + } + + if (relative.protocol && relative.protocol !== result.protocol) { + // if it's a known url protocol, then changing + // the protocol does weird things + // first, if it's not file:, then we MUST have a host, + // and if there was a path + // to begin with, then we MUST have a path. + // if it is file:, then the host is dropped, + // because that's known to be hostless. + // anything else is assumed to be absolute. + if (!slashedProtocol[relative.protocol]) { + Object.keys(relative).forEach(function(k) { + result[k] = relative[k]; + }); + result.href = result.format(); + return result; + } + + result.protocol = relative.protocol; + if (!relative.host && !hostlessProtocol[relative.protocol]) { + var relPath = (relative.pathname || '').split('/'); + while (relPath.length && !(relative.host = relPath.shift())); + if (!relative.host) relative.host = ''; + if (!relative.hostname) relative.hostname = ''; + if (relPath[0] !== '') relPath.unshift(''); + if (relPath.length < 2) relPath.unshift(''); + result.pathname = relPath.join('/'); + } else { + result.pathname = relative.pathname; + } + result.search = relative.search; + result.query = relative.query; + result.host = relative.host || ''; + result.auth = relative.auth; + result.hostname = relative.hostname || relative.host; + result.port = relative.port; + // to support http.request + if (result.pathname || result.search) { + var p = result.pathname || ''; + var s = result.search || ''; + result.path = p + s; + } + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + } + + var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), + isRelAbs = ( + relative.host || + relative.pathname && relative.pathname.charAt(0) === '/' + ), + mustEndAbs = (isRelAbs || isSourceAbs || + (result.host && relative.pathname)), + removeAllDots = mustEndAbs, + srcPath = result.pathname && result.pathname.split('/') || [], + relPath = relative.pathname && relative.pathname.split('/') || [], + psychotic = result.protocol && !slashedProtocol[result.protocol]; + + // if the url is a non-slashed url, then relative + // links like ../.. should be able + // to crawl up to the hostname, as well. This is strange. + // result.protocol has already been set by now. + // Later on, put the first path part into the host field. + if (psychotic) { + result.hostname = ''; + result.port = null; + if (result.host) { + if (srcPath[0] === '') srcPath[0] = result.host; + else srcPath.unshift(result.host); + } + result.host = ''; + if (relative.protocol) { + relative.hostname = null; + relative.port = null; + if (relative.host) { + if (relPath[0] === '') relPath[0] = relative.host; + else relPath.unshift(relative.host); + } + relative.host = null; + } + mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); + } + + if (isRelAbs) { + // it's absolute. + result.host = (relative.host || relative.host === '') ? + relative.host : result.host; + result.hostname = (relative.hostname || relative.hostname === '') ? + relative.hostname : result.hostname; + result.search = relative.search; + result.query = relative.query; + srcPath = relPath; + // fall through to the dot-handling below. + } else if (relPath.length) { + // it's relative + // throw away the existing file, and take the new path instead. + if (!srcPath) srcPath = []; + srcPath.pop(); + srcPath = srcPath.concat(relPath); + result.search = relative.search; + result.query = relative.query; + } else if (!isNullOrUndefined(relative.search)) { + // just pull out the search. + // like href='?foo'. + // Put this after the other two cases because it simplifies the booleans + if (psychotic) { + result.hostname = result.host = srcPath.shift(); + //occationaly the auth can get stuck only in host + //this especialy happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + result.search = relative.search; + result.query = relative.query; + //to support http.request + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.href = result.format(); + return result; + } + + if (!srcPath.length) { + // no path at all. easy. + // we've already handled the other stuff above. + result.pathname = null; + //to support http.request + if (result.search) { + result.path = '/' + result.search; + } else { + result.path = null; + } + result.href = result.format(); + return result; + } + + // if a url ENDs in . or .., then it must get a trailing slash. + // however, if it ends in anything else non-slashy, + // then it must NOT get a trailing slash. + var last = srcPath.slice(-1)[0]; + var hasTrailingSlash = ( + (result.host || relative.host) && (last === '.' || last === '..') || + last === ''); + + // strip single dots, resolve double dots to parent dir + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = srcPath.length; i >= 0; i--) { + last = srcPath[i]; + if (last == '.') { + srcPath.splice(i, 1); + } else if (last === '..') { + srcPath.splice(i, 1); + up++; + } else if (up) { + srcPath.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (!mustEndAbs && !removeAllDots) { + for (; up--; up) { + srcPath.unshift('..'); + } + } + + if (mustEndAbs && srcPath[0] !== '' && + (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { + srcPath.unshift(''); + } + + if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { + srcPath.push(''); + } + + var isAbsolute = srcPath[0] === '' || + (srcPath[0] && srcPath[0].charAt(0) === '/'); + + // put the host back + if (psychotic) { + result.hostname = result.host = isAbsolute ? '' : + srcPath.length ? srcPath.shift() : ''; + //occationaly the auth can get stuck only in host + //this especialy happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + + mustEndAbs = mustEndAbs || (result.host && srcPath.length); + + if (mustEndAbs && !isAbsolute) { + srcPath.unshift(''); + } + + if (!srcPath.length) { + result.pathname = null; + result.path = null; + } else { + result.pathname = srcPath.join('/'); + } + + //to support request.http + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.auth = relative.auth || result.auth; + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + }; + + Url.prototype.parseHost = function() { + var host = this.host; + var port = portPattern.exec(host); + if (port) { + port = port[0]; + if (port !== ':') { + this.port = port.substr(1); + } + host = host.substr(0, host.length - port.length); + } + if (host) this.hostname = host; + }; + + function isString(arg) { + return typeof arg === "string"; + } + + function isObject(arg) { + return typeof arg === 'object' && arg !== null; + } + + function isNull(arg) { + return arg === null; + } + function isNullOrUndefined(arg) { + return arg == null; + } + + +/***/ }, +/* 294 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */ + ;(function(root) { + + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see <https://mathiasbynens.be/notes/javascript-encoding> + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * http://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>, + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.3.2', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see <https://mathiasbynens.be/notes/javascript-encoding> + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + true + ) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { + return punycode; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { // in Rhino or a web browser + root.punycode = punycode; + } + + }(this)); + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(77)(module), (function() { return this; }()))) + +/***/ }, +/* 295 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.decode = exports.parse = __webpack_require__(296); + exports.encode = exports.stringify = __webpack_require__(297); + + +/***/ }, +/* 296 */ +/***/ function(module, exports) { + + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + 'use strict'; + + // If obj.hasOwnProperty has been overridden, then calling + // obj.hasOwnProperty(prop) will break. + // See: https://github.com/joyent/node/issues/1707 + function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); + } + + module.exports = function(qs, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + var obj = {}; + + if (typeof qs !== 'string' || qs.length === 0) { + return obj; + } + + var regexp = /\+/g; + qs = qs.split(sep); + + var maxKeys = 1000; + if (options && typeof options.maxKeys === 'number') { + maxKeys = options.maxKeys; + } + + var len = qs.length; + // maxKeys <= 0 means that we should not limit keys count + if (maxKeys > 0 && len > maxKeys) { + len = maxKeys; + } + + for (var i = 0; i < len; ++i) { + var x = qs[i].replace(regexp, '%20'), + idx = x.indexOf(eq), + kstr, vstr, k, v; + + if (idx >= 0) { + kstr = x.substr(0, idx); + vstr = x.substr(idx + 1); + } else { + kstr = x; + vstr = ''; + } + + k = decodeURIComponent(kstr); + v = decodeURIComponent(vstr); + + if (!hasOwnProperty(obj, k)) { + obj[k] = v; + } else if (Array.isArray(obj[k])) { + obj[k].push(v); + } else { + obj[k] = [obj[k], v]; + } + } + + return obj; + }; + + +/***/ }, +/* 297 */ +/***/ function(module, exports) { + + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + 'use strict'; + + var stringifyPrimitive = function(v) { + switch (typeof v) { + case 'string': + return v; + + case 'boolean': + return v ? 'true' : 'false'; + + case 'number': + return isFinite(v) ? v : ''; + + default: + return ''; + } + }; + + module.exports = function(obj, sep, eq, name) { + sep = sep || '&'; + eq = eq || '='; + if (obj === null) { + obj = undefined; + } + + if (typeof obj === 'object') { + return Object.keys(obj).map(function(k) { + var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; + if (Array.isArray(obj[k])) { + return obj[k].map(function(v) { + return ks + encodeURIComponent(stringifyPrimitive(v)); + }).join(sep); + } else { + return ks + encodeURIComponent(stringifyPrimitive(obj[k])); + } + }).join(sep); + + } + + if (!name) return ''; + return encodeURIComponent(stringifyPrimitive(name)) + eq + + encodeURIComponent(stringifyPrimitive(obj)); + }; + + +/***/ }, +/* 298 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 299 */, +/* 300 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + var _require = __webpack_require__(301); + + var filter = _require.filter; + + var classnames = __webpack_require__(211); + __webpack_require__(308); + var Svg = __webpack_require__(310); + var CloseButton = __webpack_require__(336); + + var INITIAL_SELECTED_INDEX = 0; + + var Autocomplete = React.createClass({ + propTypes: { + selectItem: PropTypes.func, + items: PropTypes.array, + handleClose: PropTypes.func, + inputValue: PropTypes.string + }, + + displayName: "Autocomplete", + + getInitialState() { + return { + inputValue: this.props.inputValue, + selectedIndex: INITIAL_SELECTED_INDEX + }; + }, + + componentDidMount() { + var endOfInput = this.state.inputValue.length; + this.refs.searchInput.focus(); + this.refs.searchInput.setSelectionRange(endOfInput, endOfInput); + }, + + componentDidUpdate() { + this.scrollList(); + }, + + scrollList() { + var resultsEl = this.refs.results; + if (!resultsEl || resultsEl.children.length === 0) { + return; + } + + var resultsHeight = resultsEl.clientHeight; + var itemHeight = resultsEl.children[0].clientHeight; + var numVisible = resultsHeight / itemHeight; + var positionsToScroll = this.state.selectedIndex - numVisible + 1; + var itemOffset = resultsHeight % itemHeight; + var scroll = positionsToScroll * (itemHeight + 2) + itemOffset; + + resultsEl.scrollTop = Math.max(0, scroll); + }, + + getSearchResults() { + var inputValue = this.state.inputValue; + + if (inputValue == "") { + return []; + } + return filter(this.props.items, this.state.inputValue, { + key: "value" + }); + }, + + onKeyDown(e) { + var searchResults = this.getSearchResults(), + resultCount = searchResults.length; + + if (e.key === "ArrowUp") { + this.setState({ + selectedIndex: Math.max(0, this.state.selectedIndex - 1) + }); + e.preventDefault(); + } else if (e.key === "ArrowDown") { + this.setState({ + selectedIndex: Math.min(resultCount - 1, this.state.selectedIndex + 1) + }); + e.preventDefault(); + } else if (e.key === "Enter") { + if (searchResults.length) { + this.props.selectItem(searchResults[this.state.selectedIndex]); + } else { + this.props.handleClose(this.state.inputValue); + } + e.preventDefault(); + } else if (e.key === "Tab") { + this.props.handleClose(this.state.inputValue); + e.preventDefault(); + } + }, + + renderSearchItem(result, index) { + return dom.li({ + onClick: () => this.props.selectItem(result), + key: result.value, + className: classnames({ + selected: index === this.state.selectedIndex + }) + }, dom.div({ className: "title" }, result.title), dom.div({ className: "subtitle" }, result.subtitle)); + }, + + renderInput() { + return dom.input({ + ref: "searchInput", + value: this.state.inputValue, + onChange: e => this.setState({ + inputValue: e.target.value, + selectedIndex: INITIAL_SELECTED_INDEX + }), + onFocus: e => this.setState({ focused: true }), + onBlur: e => this.setState({ focused: false }), + onKeyDown: this.onKeyDown, + placeholder: L10N.getStr("sourceSearch.search") + }); + }, + + renderResults(results) { + if (results.length) { + return dom.ul({ className: "results", ref: "results" }, results.map(this.renderSearchItem)); + } else if (this.state.inputValue && !results.length) { + return dom.div({ className: "no-result-msg" }, Svg("sad-face"), L10N.getFormatStr("sourceSearch.noResults", this.state.inputValue)); + } + }, + + renderSummary(searchResults) { + if (searchResults && searchResults.length === 0) { + return; + } + + var resultCountSummary = ""; + if (this.state.inputValue) { + resultCountSummary = L10N.getFormatStr("sourceSearch.resultsSummary", searchResults.length, this.state.inputValue); + } + return dom.div({ className: "results-summary" }, resultCountSummary); + }, + + render() { + var searchResults = this.getSearchResults(); + return dom.div({ className: classnames({ + autocomplete: true, + focused: this.state.focused + }) + }, dom.div({ className: "searchinput-container" }, Svg("magnifying-glass"), this.renderInput(), CloseButton({ + buttonClass: "big", + handleClick: this.props.handleClose + })), this.renderSummary(searchResults), this.renderResults(searchResults)); + } + }); + + module.exports = Autocomplete; + +/***/ }, +/* 301 */ +/***/ function(module, exports, __webpack_require__) { + + (function() { + var PathSeparator, filter, legacy_scorer, matcher, prepQueryCache, scorer; + + scorer = __webpack_require__(302); + + legacy_scorer = __webpack_require__(305); + + filter = __webpack_require__(306); + + matcher = __webpack_require__(307); + + PathSeparator = __webpack_require__(303).sep; + + prepQueryCache = null; + + module.exports = { + filter: function(candidates, query, options) { + if (!((query != null ? query.length : void 0) && (candidates != null ? candidates.length : void 0))) { + return []; + } + return filter(candidates, query, options); + }, + prepQuery: function(query) { + return scorer.prepQuery(query); + }, + score: function(string, query, prepQuery, _arg) { + var allowErrors, coreQuery, legacy, queryHasSlashes, score, _ref; + _ref = _arg != null ? _arg : {}, allowErrors = _ref.allowErrors, legacy = _ref.legacy; + if (!((string != null ? string.length : void 0) && (query != null ? query.length : void 0))) { + return 0; + } + if (prepQuery == null) { + prepQuery = prepQueryCache && prepQueryCache.query === query ? prepQueryCache : (prepQueryCache = scorer.prepQuery(query)); + } + if (!legacy) { + score = scorer.score(string, query, prepQuery, !!allowErrors); + } else { + queryHasSlashes = prepQuery.depth > 0; + coreQuery = prepQuery.core; + score = legacy_scorer.score(string, coreQuery, queryHasSlashes); + if (!queryHasSlashes) { + score = legacy_scorer.basenameScore(string, coreQuery, score); + } + } + return score; + }, + match: function(string, query, prepQuery, _arg) { + var allowErrors, baseMatches, matches, query_lw, string_lw, _i, _ref, _results; + allowErrors = (_arg != null ? _arg : {}).allowErrors; + if (!string) { + return []; + } + if (!query) { + return []; + } + if (string === query) { + return (function() { + _results = []; + for (var _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); } + return _results; + }).apply(this); + } + if (prepQuery == null) { + prepQuery = prepQueryCache && prepQueryCache.query === query ? prepQueryCache : (prepQueryCache = scorer.prepQuery(query)); + } + if (!(allowErrors || scorer.isMatch(string, prepQuery.core_lw, prepQuery.core_up))) { + return []; + } + string_lw = string.toLowerCase(); + query_lw = prepQuery.query_lw; + matches = matcher.match(string, string_lw, prepQuery); + if (matches.length === 0) { + return matches; + } + if (string.indexOf(PathSeparator) > -1) { + baseMatches = matcher.basenameMatch(string, string_lw, prepQuery); + matches = matcher.mergeMatches(matches, baseMatches); + } + return matches; + } + }; + + }).call(this); + + +/***/ }, +/* 302 */ +/***/ function(module, exports, __webpack_require__) { + + (function() { + var AcronymResult, PathSeparator, Query, basenameScore, coreChars, countDir, doScore, emptyAcronymResult, file_coeff, isMatch, isSeparator, isWordEnd, isWordStart, miss_coeff, opt_char_re, pos_bonus, scoreAcronyms, scoreCharacter, scoreConsecutives, scoreExact, scoreExactMatch, scorePattern, scorePosition, scoreSize, tau_depth, tau_size, truncatedUpperCase, wm; + + PathSeparator = __webpack_require__(303).sep; + + wm = 150; + + pos_bonus = 20; + + tau_depth = 13; + + tau_size = 85; + + file_coeff = 1.2; + + miss_coeff = 0.75; + + opt_char_re = /[ _\-:\/\\]/g; + + exports.coreChars = coreChars = function(query) { + return query.replace(opt_char_re, ''); + }; + + exports.score = function(string, query, prepQuery, allowErrors) { + var score, string_lw; + if (prepQuery == null) { + prepQuery = new Query(query); + } + if (allowErrors == null) { + allowErrors = false; + } + if (!(allowErrors || isMatch(string, prepQuery.core_lw, prepQuery.core_up))) { + return 0; + } + string_lw = string.toLowerCase(); + score = doScore(string, string_lw, prepQuery); + return Math.ceil(basenameScore(string, string_lw, prepQuery, score)); + }; + + Query = (function() { + function Query(query) { + if (!(query != null ? query.length : void 0)) { + return null; + } + this.query = query; + this.query_lw = query.toLowerCase(); + this.core = coreChars(query); + this.core_lw = this.core.toLowerCase(); + this.core_up = truncatedUpperCase(this.core); + this.depth = countDir(query, query.length); + } + + return Query; + + })(); + + exports.prepQuery = function(query) { + return new Query(query); + }; + + exports.isMatch = isMatch = function(subject, query_lw, query_up) { + var i, j, m, n, qj_lw, qj_up, si; + m = subject.length; + n = query_lw.length; + if (!m || n > m) { + return false; + } + i = -1; + j = -1; + while (++j < n) { + qj_lw = query_lw[j]; + qj_up = query_up[j]; + while (++i < m) { + si = subject[i]; + if (si === qj_lw || si === qj_up) { + break; + } + } + if (i === m) { + return false; + } + } + return true; + }; + + doScore = function(subject, subject_lw, prepQuery) { + var acro, acro_score, align, csc_diag, csc_row, csc_score, i, j, m, miss_budget, miss_left, mm, n, pos, query, query_lw, record_miss, score, score_diag, score_row, score_up, si_lw, start, sz; + query = prepQuery.query; + query_lw = prepQuery.query_lw; + m = subject.length; + n = query.length; + acro = scoreAcronyms(subject, subject_lw, query, query_lw); + acro_score = acro.score; + if (acro.count === n) { + return scoreExact(n, m, acro_score, acro.pos); + } + pos = subject_lw.indexOf(query_lw); + if (pos > -1) { + return scoreExactMatch(subject, subject_lw, query, query_lw, pos, n, m); + } + score_row = new Array(n); + csc_row = new Array(n); + sz = scoreSize(n, m); + miss_budget = Math.ceil(miss_coeff * n) + 5; + miss_left = miss_budget; + j = -1; + while (++j < n) { + score_row[j] = 0; + csc_row[j] = 0; + } + i = subject_lw.indexOf(query_lw[0]); + if (i > -1) { + i--; + } + mm = subject_lw.lastIndexOf(query_lw[n - 1], m); + if (mm > i) { + m = mm + 1; + } + while (++i < m) { + score = 0; + score_diag = 0; + csc_diag = 0; + si_lw = subject_lw[i]; + record_miss = true; + j = -1; + while (++j < n) { + score_up = score_row[j]; + if (score_up > score) { + score = score_up; + } + csc_score = 0; + if (query_lw[j] === si_lw) { + start = isWordStart(i, subject, subject_lw); + csc_score = csc_diag > 0 ? csc_diag : scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start); + align = score_diag + scoreCharacter(i, j, start, acro_score, csc_score); + if (align > score) { + score = align; + miss_left = miss_budget; + } else { + if (record_miss && --miss_left <= 0) { + return score_row[n - 1] * sz; + } + record_miss = false; + } + } + score_diag = score_up; + csc_diag = csc_row[j]; + csc_row[j] = csc_score; + score_row[j] = score; + } + } + return score * sz; + }; + + exports.isWordStart = isWordStart = function(pos, subject, subject_lw) { + var curr_s, prev_s; + if (pos === 0) { + return true; + } + curr_s = subject[pos]; + prev_s = subject[pos - 1]; + return isSeparator(curr_s) || isSeparator(prev_s) || (curr_s !== subject_lw[pos] && prev_s === subject_lw[pos - 1]); + }; + + exports.isWordEnd = isWordEnd = function(pos, subject, subject_lw, len) { + var curr_s, next_s; + if (pos === len - 1) { + return true; + } + curr_s = subject[pos]; + next_s = subject[pos + 1]; + return isSeparator(curr_s) || isSeparator(next_s) || (curr_s === subject_lw[pos] && next_s !== subject_lw[pos + 1]); + }; + + isSeparator = function(c) { + return c === ' ' || c === '.' || c === '-' || c === '_' || c === '/' || c === '\\'; + }; + + scorePosition = function(pos) { + var sc; + if (pos < pos_bonus) { + sc = pos_bonus - pos; + return 100 + sc * sc; + } else { + return Math.max(100 + pos_bonus - pos, 0); + } + }; + + scoreSize = function(n, m) { + return tau_size / (tau_size + Math.abs(m - n)); + }; + + scoreExact = function(n, m, quality, pos) { + return 2 * n * (wm * quality + scorePosition(pos)) * scoreSize(n, m); + }; + + exports.scorePattern = scorePattern = function(count, len, sameCase, start, end) { + var bonus, sz; + sz = count; + bonus = 6; + if (sameCase === count) { + bonus += 2; + } + if (start) { + bonus += 3; + } + if (end) { + bonus += 1; + } + if (count === len) { + if (start) { + if (sameCase === len) { + sz += 2; + } else { + sz += 1; + } + } + if (end) { + bonus += 1; + } + } + return sameCase + sz * (sz + bonus); + }; + + exports.scoreCharacter = scoreCharacter = function(i, j, start, acro_score, csc_score) { + var posBonus; + posBonus = scorePosition(i); + if (start) { + return posBonus + wm * ((acro_score > csc_score ? acro_score : csc_score) + 10); + } + return posBonus + wm * csc_score; + }; + + exports.scoreConsecutives = scoreConsecutives = function(subject, subject_lw, query, query_lw, i, j, start) { + var k, m, mi, n, nj, sameCase, startPos, sz; + m = subject.length; + n = query.length; + mi = m - i; + nj = n - j; + k = mi < nj ? mi : nj; + startPos = i; + sameCase = 0; + sz = 0; + if (query[j] === subject[i]) { + sameCase++; + } + while (++sz < k && query_lw[++j] === subject_lw[++i]) { + if (query[j] === subject[i]) { + sameCase++; + } + } + if (sz === 1) { + return 1 + 2 * sameCase; + } + return scorePattern(sz, n, sameCase, start, isWordEnd(i, subject, subject_lw, m)); + }; + + exports.scoreExactMatch = scoreExactMatch = function(subject, subject_lw, query, query_lw, pos, n, m) { + var end, i, pos2, sameCase, start; + start = isWordStart(pos, subject, subject_lw); + if (!start) { + pos2 = subject_lw.indexOf(query_lw, pos + 1); + if (pos2 > -1) { + start = isWordStart(pos2, subject, subject_lw); + if (start) { + pos = pos2; + } + } + } + i = -1; + sameCase = 0; + while (++i < n) { + if (query[pos + i] === subject[i]) { + sameCase++; + } + } + end = isWordEnd(pos + n - 1, subject, subject_lw, m); + return scoreExact(n, m, scorePattern(n, n, sameCase, start, end), pos); + }; + + AcronymResult = (function() { + function AcronymResult(score, pos, count) { + this.score = score; + this.pos = pos; + this.count = count; + } + + return AcronymResult; + + })(); + + emptyAcronymResult = new AcronymResult(0, 0.1, 0); + + exports.scoreAcronyms = scoreAcronyms = function(subject, subject_lw, query, query_lw) { + var count, i, j, m, n, pos, qj_lw, sameCase, score; + m = subject.length; + n = query.length; + if (!(m > 1 && n > 1)) { + return emptyAcronymResult; + } + count = 0; + pos = 0; + sameCase = 0; + i = -1; + j = -1; + while (++j < n) { + qj_lw = query_lw[j]; + while (++i < m) { + if (qj_lw === subject_lw[i] && isWordStart(i, subject, subject_lw)) { + if (query[j] === subject[i]) { + sameCase++; + } + pos += i; + count++; + break; + } + } + if (i === m) { + break; + } + } + if (count < 2) { + return emptyAcronymResult; + } + score = scorePattern(count, n, sameCase, true, false); + return new AcronymResult(score, pos / count, count); + }; + + basenameScore = function(subject, subject_lw, prepQuery, fullPathScore) { + var alpha, basePathScore, basePos, depth, end; + if (fullPathScore === 0) { + return 0; + } + end = subject.length - 1; + while (subject[end] === PathSeparator) { + end--; + } + basePos = subject.lastIndexOf(PathSeparator, end); + if (basePos === -1) { + return fullPathScore; + } + depth = prepQuery.depth; + while (depth-- > 0) { + basePos = subject.lastIndexOf(PathSeparator, basePos - 1); + if (basePos === -1) { + return fullPathScore; + } + } + basePos++; + end++; + basePathScore = doScore(subject.slice(basePos, end), subject_lw.slice(basePos, end), prepQuery); + alpha = 0.5 * tau_depth / (tau_depth + countDir(subject, end + 1)); + return alpha * basePathScore + (1 - alpha) * fullPathScore * scoreSize(0, file_coeff * (end - basePos)); + }; + + exports.countDir = countDir = function(path, end) { + var count, i; + if (end < 1) { + return 0; + } + count = 0; + i = -1; + while (++i < end && path[i] === PathSeparator) { + continue; + } + while (++i < end) { + if (path[i] === PathSeparator) { + count++; + while (++i < end && path[i] === PathSeparator) { + continue; + } + } + } + return count; + }; + + truncatedUpperCase = function(str) { + var char, upper, _i, _len; + upper = ""; + for (_i = 0, _len = str.length; _i < _len; _i++) { + char = str[_i]; + upper += char.toUpperCase()[0]; + } + return upper; + }; + + }).call(this); + + +/***/ }, +/* 303 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(process) {// Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + // 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 - 1; 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--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; + } + + // Split a filename into [root, dir, basename, ext], unix version + // 'root' is just a slash, or nothing. + var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); + }; + + // path.resolve([from ...], to) + // posix version + exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // 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('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + }; + + // path.normalize(path) + // posix version + exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; + }; + + // posix version + exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; + }; + + // posix version + exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); + }; + + + // path.relative(from, to) + // posix version + exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + 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; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); + }; + + exports.sep = '/'; + exports.delimiter = ':'; + + exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; + }; + + + exports.basename = function(path, ext) { + var f = splitPath(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); + } + return f; + }; + + + exports.extname = function(path) { + return splitPath(path)[3]; + }; + + function filter (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; + } + + // String.prototype.substr - negative index don't work in IE8 + var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } + ; + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(304))) + +/***/ }, +/* 304 */ +/***/ function(module, exports) { + + // shim for using process in browser + var process = module.exports = {}; + + // cached from whatever global is present so that test runners that stub it + // don't break things. But we need to wrap it in a try catch in case it is + // wrapped in strict mode code which doesn't define any globals. It's inside a + // function because try/catches deoptimize in certain engines. + + var cachedSetTimeout; + var cachedClearTimeout; + + function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); + } + function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); + } + (function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } + } ()) + function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + + } + function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + + } + var queue = []; + var draining = false; + var currentQueue; + var queueIndex = -1; + + function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } + } + + function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); + } + + process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } + }; + + // v8 likes predictible objects + function Item(fun, array) { + this.fun = fun; + this.array = array; + } + Item.prototype.run = function () { + this.fun.apply(null, this.array); + }; + process.title = 'browser'; + process.browser = true; + process.env = {}; + process.argv = []; + process.version = ''; // empty string to avoid regexp issues + process.versions = {}; + + function noop() {} + + process.on = noop; + process.addListener = noop; + process.once = noop; + process.off = noop; + process.removeListener = noop; + process.removeAllListeners = noop; + process.emit = noop; + + process.binding = function (name) { + throw new Error('process.binding is not supported'); + }; + + process.cwd = function () { return '/' }; + process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); + }; + process.umask = function() { return 0; }; + + +/***/ }, +/* 305 */ +/***/ function(module, exports, __webpack_require__) { + + (function() { + var PathSeparator, queryIsLastPathSegment; + + PathSeparator = __webpack_require__(303).sep; + + exports.basenameScore = function(string, query, score) { + var base, depth, index, lastCharacter, segmentCount, slashCount; + index = string.length - 1; + while (string[index] === PathSeparator) { + index--; + } + slashCount = 0; + lastCharacter = index; + base = null; + while (index >= 0) { + if (string[index] === PathSeparator) { + slashCount++; + if (base == null) { + base = string.substring(index + 1, lastCharacter + 1); + } + } else if (index === 0) { + if (lastCharacter < string.length - 1) { + if (base == null) { + base = string.substring(0, lastCharacter + 1); + } + } else { + if (base == null) { + base = string; + } + } + } + index--; + } + if (base === string) { + score *= 2; + } else if (base) { + score += exports.score(base, query); + } + segmentCount = slashCount + 1; + depth = Math.max(1, 10 - segmentCount); + score *= depth * 0.01; + return score; + }; + + exports.score = function(string, query) { + var character, characterScore, indexInQuery, indexInString, lowerCaseIndex, minIndex, queryLength, queryScore, stringLength, totalCharacterScore, upperCaseIndex, _ref; + if (string === query) { + return 1; + } + if (queryIsLastPathSegment(string, query)) { + return 1; + } + totalCharacterScore = 0; + queryLength = query.length; + stringLength = string.length; + indexInQuery = 0; + indexInString = 0; + while (indexInQuery < queryLength) { + character = query[indexInQuery++]; + lowerCaseIndex = string.indexOf(character.toLowerCase()); + upperCaseIndex = string.indexOf(character.toUpperCase()); + minIndex = Math.min(lowerCaseIndex, upperCaseIndex); + if (minIndex === -1) { + minIndex = Math.max(lowerCaseIndex, upperCaseIndex); + } + indexInString = minIndex; + if (indexInString === -1) { + return 0; + } + characterScore = 0.1; + if (string[indexInString] === character) { + characterScore += 0.1; + } + if (indexInString === 0 || string[indexInString - 1] === PathSeparator) { + characterScore += 0.8; + } else if ((_ref = string[indexInString - 1]) === '-' || _ref === '_' || _ref === ' ') { + characterScore += 0.7; + } + string = string.substring(indexInString + 1, stringLength); + totalCharacterScore += characterScore; + } + queryScore = totalCharacterScore / queryLength; + return ((queryScore * (queryLength / stringLength)) + queryScore) / 2; + }; + + queryIsLastPathSegment = function(string, query) { + if (string[string.length - query.length - 1] === PathSeparator) { + return string.lastIndexOf(query) === string.length - query.length; + } + }; + + exports.match = function(string, query, stringOffset) { + var character, indexInQuery, indexInString, lowerCaseIndex, matches, minIndex, queryLength, stringLength, upperCaseIndex, _i, _ref, _results; + if (stringOffset == null) { + stringOffset = 0; + } + if (string === query) { + return (function() { + _results = []; + for (var _i = stringOffset, _ref = stringOffset + string.length; stringOffset <= _ref ? _i < _ref : _i > _ref; stringOffset <= _ref ? _i++ : _i--){ _results.push(_i); } + return _results; + }).apply(this); + } + queryLength = query.length; + stringLength = string.length; + indexInQuery = 0; + indexInString = 0; + matches = []; + while (indexInQuery < queryLength) { + character = query[indexInQuery++]; + lowerCaseIndex = string.indexOf(character.toLowerCase()); + upperCaseIndex = string.indexOf(character.toUpperCase()); + minIndex = Math.min(lowerCaseIndex, upperCaseIndex); + if (minIndex === -1) { + minIndex = Math.max(lowerCaseIndex, upperCaseIndex); + } + indexInString = minIndex; + if (indexInString === -1) { + return []; + } + matches.push(stringOffset + indexInString); + stringOffset += indexInString + 1; + string = string.substring(indexInString + 1, stringLength); + } + return matches; + }; + + }).call(this); + + +/***/ }, +/* 306 */ +/***/ function(module, exports, __webpack_require__) { + + (function() { + var PathSeparator, legacy_scorer, pluckCandidates, scorer, sortCandidates; + + scorer = __webpack_require__(302); + + legacy_scorer = __webpack_require__(305); + + pluckCandidates = function(a) { + return a.candidate; + }; + + sortCandidates = function(a, b) { + return b.score - a.score; + }; + + PathSeparator = __webpack_require__(303).sep; + + module.exports = function(candidates, query, _arg) { + var allowErrors, bAllowErrors, bKey, candidate, coreQuery, key, legacy, maxInners, maxResults, prepQuery, queryHasSlashes, score, scoredCandidates, spotLeft, string, _i, _j, _len, _len1, _ref; + _ref = _arg != null ? _arg : {}, key = _ref.key, maxResults = _ref.maxResults, maxInners = _ref.maxInners, allowErrors = _ref.allowErrors, legacy = _ref.legacy; + scoredCandidates = []; + spotLeft = (maxInners != null) && maxInners > 0 ? maxInners : candidates.length; + bAllowErrors = !!allowErrors; + bKey = key != null; + prepQuery = scorer.prepQuery(query); + if (!legacy) { + for (_i = 0, _len = candidates.length; _i < _len; _i++) { + candidate = candidates[_i]; + string = bKey ? candidate[key] : candidate; + if (!string) { + continue; + } + score = scorer.score(string, query, prepQuery, bAllowErrors); + if (score > 0) { + scoredCandidates.push({ + candidate: candidate, + score: score + }); + if (!--spotLeft) { + break; + } + } + } + } else { + queryHasSlashes = prepQuery.depth > 0; + coreQuery = prepQuery.core; + for (_j = 0, _len1 = candidates.length; _j < _len1; _j++) { + candidate = candidates[_j]; + string = key != null ? candidate[key] : candidate; + if (!string) { + continue; + } + score = legacy_scorer.score(string, coreQuery, queryHasSlashes); + if (!queryHasSlashes) { + score = legacy_scorer.basenameScore(string, coreQuery, score); + } + if (score > 0) { + scoredCandidates.push({ + candidate: candidate, + score: score + }); + } + } + } + scoredCandidates.sort(sortCandidates); + candidates = scoredCandidates.map(pluckCandidates); + if (maxResults != null) { + candidates = candidates.slice(0, maxResults); + } + return candidates; + }; + + }).call(this); + + +/***/ }, +/* 307 */ +/***/ function(module, exports, __webpack_require__) { + + (function() { + var PathSeparator, scorer; + + PathSeparator = __webpack_require__(303).sep; + + scorer = __webpack_require__(302); + + exports.basenameMatch = function(subject, subject_lw, prepQuery) { + var basePos, depth, end; + end = subject.length - 1; + while (subject[end] === PathSeparator) { + end--; + } + basePos = subject.lastIndexOf(PathSeparator, end); + if (basePos === -1) { + return []; + } + depth = prepQuery.depth; + while (depth-- > 0) { + basePos = subject.lastIndexOf(PathSeparator, basePos - 1); + if (basePos === -1) { + return []; + } + } + basePos++; + end++; + return exports.match(subject.slice(basePos, end), subject_lw.slice(basePos, end), prepQuery, basePos); + }; + + exports.mergeMatches = function(a, b) { + var ai, bj, i, j, m, n, out; + m = a.length; + n = b.length; + if (n === 0) { + return a.slice(); + } + if (m === 0) { + return b.slice(); + } + i = -1; + j = 0; + bj = b[j]; + out = []; + while (++i < m) { + ai = a[i]; + while (bj <= ai && ++j < n) { + if (bj < ai) { + out.push(bj); + } + bj = b[j]; + } + out.push(ai); + } + while (j < n) { + out.push(b[j++]); + } + return out; + }; + + exports.match = function(subject, subject_lw, prepQuery, offset) { + var DIAGONAL, LEFT, STOP, UP, acro_score, align, backtrack, csc_diag, csc_row, csc_score, i, j, m, matches, move, n, pos, query, query_lw, score, score_diag, score_row, score_up, si_lw, start, trace; + if (offset == null) { + offset = 0; + } + query = prepQuery.query; + query_lw = prepQuery.query_lw; + m = subject.length; + n = query.length; + acro_score = scorer.scoreAcronyms(subject, subject_lw, query, query_lw).score; + score_row = new Array(n); + csc_row = new Array(n); + STOP = 0; + UP = 1; + LEFT = 2; + DIAGONAL = 3; + trace = new Array(m * n); + pos = -1; + j = -1; + while (++j < n) { + score_row[j] = 0; + csc_row[j] = 0; + } + i = -1; + while (++i < m) { + score = 0; + score_up = 0; + csc_diag = 0; + si_lw = subject_lw[i]; + j = -1; + while (++j < n) { + csc_score = 0; + align = 0; + score_diag = score_up; + if (query_lw[j] === si_lw) { + start = scorer.isWordStart(i, subject, subject_lw); + csc_score = csc_diag > 0 ? csc_diag : scorer.scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start); + align = score_diag + scorer.scoreCharacter(i, j, start, acro_score, csc_score); + } + score_up = score_row[j]; + csc_diag = csc_row[j]; + if (score > score_up) { + move = LEFT; + } else { + score = score_up; + move = UP; + } + if (align > score) { + score = align; + move = DIAGONAL; + } else { + csc_score = 0; + } + score_row[j] = score; + csc_row[j] = csc_score; + trace[++pos] = score > 0 ? move : STOP; + } + } + i = m - 1; + j = n - 1; + pos = i * n + j; + backtrack = true; + matches = []; + while (backtrack && i >= 0 && j >= 0) { + switch (trace[pos]) { + case UP: + i--; + pos -= n; + break; + case LEFT: + j--; + pos--; + break; + case DIAGONAL: + matches.push(i + offset); + j--; + i--; + pos -= n + 1; + break; + default: + backtrack = false; + } + } + matches.reverse(); + return matches; + }; + + }).call(this); + + +/***/ }, +/* 308 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 309 */, +/* 310 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * This file maps the SVG React Components in the public/images directory. + */ + var Svg = __webpack_require__(311); + module.exports = Svg; + +/***/ }, +/* 311 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var InlineSVG = __webpack_require__(312); + + var svg = { + "angle-brackets": __webpack_require__(313), + "arrow": __webpack_require__(314), + "blackBox": __webpack_require__(315), + "breakpoint": __webpack_require__(316), + "close": __webpack_require__(317), + "domain": __webpack_require__(318), + "file": __webpack_require__(319), + "folder": __webpack_require__(320), + "globe": __webpack_require__(321), + "magnifying-glass": __webpack_require__(322), + "pause": __webpack_require__(323), + "pause-exceptions": __webpack_require__(324), + "plus": __webpack_require__(325), + "prettyPrint": __webpack_require__(326), + "resume": __webpack_require__(327), + "settings": __webpack_require__(328), + "stepIn": __webpack_require__(329), + "stepOut": __webpack_require__(330), + "stepOver": __webpack_require__(331), + "subSettings": __webpack_require__(332), + "toggleBreakpoints": __webpack_require__(333), + "worker": __webpack_require__(334), + "sad-face": __webpack_require__(335) + }; + + module.exports = function (name, props) { + // eslint-disable-line + if (!svg[name]) { + throw new Error("Unknown SVG: " + name); + } + var className = name; + if (props && props.className) { + className = `${ name } ${ props.className }`; + } + if (name === "subSettings") { + className = ""; + } + props = Object.assign({}, props, { className, src: svg[name] }); + return React.createElement(InlineSVG, props); + }; + +/***/ }, +/* 312 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, '__esModule', { + value: true + }); + + var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + + function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + + var _react = __webpack_require__(2); + + var _react2 = _interopRequireDefault(_react); + + var DOMParser = typeof window !== 'undefined' && window.DOMParser; + var process = process || {}; + process.env = process.env || {}; + var parserAvailable = typeof DOMParser !== 'undefined' && DOMParser.prototype != null && DOMParser.prototype.parseFromString != null; + + if ("production" !== process.env.NODE_ENV && !parserAvailable) { + console.info('<InlineSVG />: `raw` prop works only when `window.DOMParser` exists.'); + } + + function isParsable(src) { + // kinda naive but meh, ain't gonna use full-blown parser for this + return parserAvailable && typeof src === 'string' && src.trim().substr(0, 4) === '<svg'; + } + + // parse SVG string using `DOMParser` + function parseFromSVGString(src) { + var parser = new DOMParser(); + return parser.parseFromString(src, "image/svg+xml"); + } + + // Transform DOM prop/attr names applicable to `<svg>` element but react-limited + function switchSVGAttrToReactProp(propName) { + switch (propName) { + case 'class': + return 'className'; + default: + return propName; + } + } + + var InlineSVG = (function (_React$Component) { + _inherits(InlineSVG, _React$Component); + + _createClass(InlineSVG, null, [{ + key: 'defaultProps', + value: { + element: 'i', + raw: false, + src: '' + }, + enumerable: true + }, { + key: 'propTypes', + value: { + src: _react2['default'].PropTypes.string.isRequired, + element: _react2['default'].PropTypes.string, + raw: _react2['default'].PropTypes.bool + }, + enumerable: true + }]); + + function InlineSVG(props) { + _classCallCheck(this, InlineSVG); + + _get(Object.getPrototypeOf(InlineSVG.prototype), 'constructor', this).call(this, props); + this._extractSVGProps = this._extractSVGProps.bind(this); + } + + // Serialize `Attr` objects in `NamedNodeMap` + + _createClass(InlineSVG, [{ + key: '_serializeAttrs', + value: function _serializeAttrs(map) { + var ret = {}; + var prop = undefined; + for (var i = 0; i < map.length; i++) { + prop = switchSVGAttrToReactProp(map[i].name); + ret[prop] = map[i].value; + } + return ret; + } + + // get <svg /> element props + }, { + key: '_extractSVGProps', + value: function _extractSVGProps(src) { + var map = parseFromSVGString(src).documentElement.attributes; + return map.length > 0 ? this._serializeAttrs(map) : null; + } + + // get content inside <svg> element. + }, { + key: '_stripSVG', + value: function _stripSVG(src) { + return parseFromSVGString(src).documentElement.innerHTML; + } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(_ref) { + var children = _ref.children; + + if ("production" !== process.env.NODE_ENV && children != null) { + console.info('<InlineSVG />: `children` prop will be ignored.'); + } + } + }, { + key: 'render', + value: function render() { + var Element = undefined, + __html = undefined, + svgProps = undefined; + var _props = this.props; + var element = _props.element; + var raw = _props.raw; + var src = _props.src; + + var otherProps = _objectWithoutProperties(_props, ['element', 'raw', 'src']); + + if (raw === true && isParsable(src)) { + Element = 'svg'; + svgProps = this._extractSVGProps(src); + __html = this._stripSVG(src); + } + __html = __html || src; + Element = Element || element; + svgProps = svgProps || {}; + + return _react2['default'].createElement(Element, _extends({}, svgProps, otherProps, { src: null, children: null, + dangerouslySetInnerHTML: { __html: __html } })); + } + }]); + + return InlineSVG; + })(_react2['default'].Component); + + exports['default'] = InlineSVG; + module.exports = exports['default']; + +/***/ }, +/* 313 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"-1 73 16 11\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><g id=\"Shape-Copy-3-+-Shape-Copy-4\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(0.000000, 74.000000)\"><path d=\"M0.749321284,4.16081709 L4.43130681,0.242526751 C4.66815444,-0.00952143591 5.06030999,-0.0211407611 5.30721074,0.216574262 C5.55411149,0.454289284 5.56226116,0.851320812 5.32541353,1.103369 L1.95384971,4.69131519 L5.48809879,8.09407556 C5.73499955,8.33179058 5.74314922,8.72882211 5.50630159,8.9808703 C5.26945396,9.23291849 4.87729841,9.24453781 4.63039766,9.00682279 L0.827097345,5.34502101 C0.749816996,5.31670099 0.677016974,5.27216098 0.613753508,5.21125118 C0.427367989,5.03179997 0.377040713,4.7615583 0.465458792,4.53143559 C0.492371834,4.43667624 0.541703274,4.34676528 0.613628034,4.27022448 C0.654709457,4.22650651 0.70046335,4.19002189 0.749321284,4.16081709 Z\" id=\"Shape-Copy-3\" stroke=\"#FFFFFF\" stroke-width=\"0.05\" fill=\"#DDE1E4\"></path><path d=\"M13.7119065,5.44453032 L9.77062746,9.09174784 C9.51677479,9.3266604 9.12476399,9.31089603 8.89504684,9.05653714 C8.66532968,8.80217826 8.68489539,8.40554539 8.93874806,8.17063283 L12.5546008,4.82456128 L9.26827469,1.18571135 C9.03855754,0.931352463 9.05812324,0.534719593 9.31197591,0.299807038 C9.56582858,0.0648944831 9.95783938,0.0806588502 10.1875565,0.335017737 L13.72891,4.25625178 C13.8013755,4.28980469 13.8684335,4.3382578 13.9254821,4.40142604 C14.0883019,4.58171146 14.1258883,4.83347168 14.0435812,5.04846202 C14.0126705,5.15680232 13.9526426,5.2583679 13.8641331,5.34027361 C13.8174417,5.38348136 13.7660763,5.41820853 13.7119065,5.44453032 Z\" id=\"Shape-Copy-4\" stroke=\"#FFFFFF\" stroke-width=\"0.05\" fill=\"#DDE1E4\"></path></g></svg>" + +/***/ }, +/* 314 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 16 16\"><path d=\"M8 13.4c-.5 0-.9-.2-1.2-.6L.4 5.2C0 4.7-.1 4.3.2 3.7S1 3 1.6 3h12.8c.6 0 1.2.1 1.4.7.3.6.2 1.1-.2 1.6l-6.4 7.6c-.3.4-.7.5-1.2.5z\"></path></svg>" + +/***/ }, +/* 315 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><g fill-rule=\"evenodd\"><circle cx=\"8\" cy=\"8.5\" r=\"1.5\"></circle><path d=\"M15.498 8.28l-.001-.03v-.002-.004l-.002-.018-.004-.031c0-.002 0-.002 0 0l-.004-.035.006.082c-.037-.296-.133-.501-.28-.661-.4-.522-.915-1.042-1.562-1.604-1.36-1.182-2.74-1.975-4.178-2.309a6.544 6.544 0 0 0-2.755-.042c-.78.153-1.565.462-2.369.91C3.252 5.147 2.207 6 1.252 7.035c-.216.233-.36.398-.499.577-.338.437-.338 1 0 1.437.428.552.941 1.072 1.59 1.635 1.359 1.181 2.739 1.975 4.177 2.308.907.21 1.829.223 2.756.043.78-.153 1.564-.462 2.369-.91 1.097-.612 2.141-1.464 3.097-2.499.217-.235.36-.398.498-.578.12-.128.216-.334.248-.554 0 .01 0 .01-.008.04l.013-.079-.001.011.003-.031.001-.017v.005l.001-.02v.008l.002-.03.001-.05-.001-.044v-.004-.004zm-.954.045v.007l.001.004V8.33v.012l-.001.01v-.005-.005l.002-.015-.001.008c-.002.014-.002.014 0 0l-.007.084c.003-.057-.004-.041-.014-.031-.143.182-.27.327-.468.543-.89.963-1.856 1.752-2.86 2.311-.724.404-1.419.677-2.095.81a5.63 5.63 0 0 1-2.374-.036c-1.273-.295-2.523-1.014-3.774-2.101-.604-.525-1.075-1.001-1.457-1.496-.054-.07-.054-.107 0-.177.117-.152.244-.298.442-.512.89-.963 1.856-1.752 2.86-2.311.724-.404 1.419-.678 2.095-.81a5.631 5.631 0 0 1 2.374.036c1.272.295 2.523 1.014 3.774 2.101.603.524 1.074 1 1.457 1.496.035.041.043.057.046.076 0 .01 0 .01.008.043l-.009-.047.003.02-.002-.013v-.008.016c0-.004 0-.004 0 0v-.004z\"></path></g></svg>" + +/***/ }, +/* 316 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 60 12\"><path id=\"base-path\" d=\"M53.9,0H1C0.4,0,0,0.4,0,1v10c0,0.6,0.4,1,1,1h52.9c0.6,0,1.2-0.3,1.5-0.7L60,6l-4.4-5.3C55,0.3,54.5,0,53.9,0z\"></path></svg>" + +/***/ }, +/* 317 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 6 6\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><path d=\"M1.35191454,5.27895256 L5.31214367,1.35518468 C5.50830675,1.16082764 5.50977084,0.844248536 5.3154138,0.648085456 C5.12105677,0.451922377 4.80447766,0.450458288 4.60831458,0.644815324 L0.648085456,4.56858321 C0.451922377,4.76294025 0.450458288,5.07951935 0.644815324,5.27568243 C0.83917236,5.47184551 1.15575146,5.4733096 1.35191454,5.27895256 L1.35191454,5.27895256 Z\" id=\"Line\" stroke=\"none\" fill=\"#696969\" fill-rule=\"evenodd\"></path><path d=\"M5.31214367,4.56858321 L1.35191454,0.644815324 C1.15575146,0.450458288 0.83917236,0.451922377 0.644815324,0.648085456 C0.450458288,0.844248536 0.451922377,1.16082764 0.648085456,1.35518468 L4.60831458,5.27895256 C4.80447766,5.4733096 5.12105677,5.47184551 5.3154138,5.27568243 C5.50977084,5.07951935 5.50830675,4.76294025 5.31214367,4.56858321 L5.31214367,4.56858321 Z\" id=\"Line-Copy-2\" stroke=\"none\" fill=\"#696969\" fill-rule=\"evenodd\"></path></svg>" + +/***/ }, +/* 318 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.05 4.634l-2.144.003-.116.116v1.445l.92.965.492.034.116-.116v-.617L9.13 5.7l.035-.95M12.482 10.38l-1.505-1.462H9.362l-.564.516-.034 1.108.72.768 1.323.034-.117-.116v1.2l.972 1.02.315.034.116-.116v-1.154l.422-.374.034-.927-.117.117h.26l.408-.36V10.5l-.125-.124-.575-.033\"></path><path d=\"M8.47 15.073c-3.088 0-5.6-2.513-5.6-5.602V9.4v-.003c0-.018 0-.018.002-.034l.182-.088.724.587.49.033.497.543-.034.9.317.383h.47l.114.096-.032 1.9.524.553h.105l.025-.338 1.004-.95.054-.474.53-.462v-.888l-.588-.038-1.118-1.155H4.48l-.154-.09V9.01l.155-.1h1.164v-.273l.12-.115.7.033.494-.443.034-.746-.624-.655h-.724v.28l-.11.07H4.64l-.114-.09.025-.64.48-.43v-.244h-.382c-.102 0-.152-.128-.08-.2 1.04-1.01 2.428-1.59 3.903-1.59 1.374 0 2.672.5 3.688 1.39.08.068.03.198-.075.198l-1.144-.034-.81.803.52.523v.16l-.382.388h-.158l-.176-.177v-.16l.076-.074-.252-.252-.37.362.53.53c.072.072.005.194-.096.194l-.752-.005v.844h.783L9.885 8l.16-.143h.16l.62.61v.267l.58.027.003.002V8.76l.18-.03 1.234 1.24.753-.708h.382l.116.108c0 .02.003.016.003.036v.065c0 3.09-2.515 5.603-5.605 5.603M8.47 3C4.904 3 2 5.903 2 9.47c0 3.57 2.903 6.472 6.47 6.472 3.57 0 6.472-2.903 6.472-6.47C14.942 5.9 12.04 3 8.472 3\"></path></svg>" + +/***/ }, +/* 319 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M4 2v12h9V4.775L9.888 2H4zm0-1h5.888c.246 0 .483.09.666.254l3.112 2.774c.212.19.334.462.334.747V14c0 .552-.448 1-1 1H4c-.552 0-1-.448-1-1V2c0-.552.448-1 1-1z\"></path><path d=\"M9 1.5v4c0 .325.306.564.62.485l4-1c.27-.067.432-.338.365-.606-.067-.27-.338-.432-.606-.365l-4 1L10 5.5v-4c0-.276-.224-.5-.5-.5s-.5.224-.5.5z\"></path></svg>" + +/***/ }, +/* 320 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2 5.193v7.652c0 .003-.002 0 .007 0H14v-7.69c0-.003.002 0-.007 0h-7.53v-2.15c0-.002-.004-.005-.01-.005H2.01C2 3 2 3 2 3.005V5.193zm-1 0V3.005C1 2.45 1.444 2 2.01 2h4.442c.558 0 1.01.45 1.01 1.005v1.15h6.53c.557 0 1.008.44 1.008 1v7.69c0 .553-.45 1-1.007 1H2.007c-.556 0-1.007-.44-1.007-1V5.193zM6.08 4.15H2v1h4.46v-1h-.38z\" fill-rule=\"evenodd\"></path></svg>" + +/***/ }, +/* 321 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"14 6 13 12\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><g id=\"world\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(14.000000, 6.000000)\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M6.35076107,0.354 C3.25095418,0.354 0.729,2.87582735 0.729,5.9758879 C0.729,9.07544113 3.25082735,11.5972685 6.35076107,11.5972685 C9.45044113,11.5972685 11.9723953,9.07544113 11.9723953,5.97576107 C11.9723953,2.87582735 9.45044113,0.354 6.35076107,0.354 L6.35076107,0.354 Z M6.35076107,10.8289121 C3.67445071,10.8289121 1.49722956,8.65181776 1.49722956,5.97576107 C1.49722956,5.9443064 1.49900522,5.91335907 1.49976622,5.88215806 L2.20090094,6.4213266 L2.56313696,6.4213266 L2.97268183,6.8306178 L2.97268183,7.68217686 L3.32324919,8.03287105 L3.73926255,8.03287105 L3.73926255,9.79940584 L4.27386509,10.3361645 L4.4591686,10.3361645 L4.4591686,10.000183 L5.37655417,9.08343163 L5.37655417,8.73400577 L5.85585737,8.25203907 L5.85585737,7.37206934 L5.32518666,7.37206934 L4.28439226,6.33140176 L2.82225748,6.33140176 L2.82225748,5.56938704 L3.96286973,5.56938704 L3.96286973,5.23949352 L4.65068695,5.23949352 L5.11477015,4.77667865 L5.11477015,4.03001076 L4.49087694,3.40662489 L3.75359472,3.40662489 L3.75359472,3.78725175 L2.96228149,3.78725175 L2.96228149,3.28385021 L3.42217919,2.82319151 L3.42217919,2.49786399 L2.97001833,2.49786399 C3.84466106,1.64744643 5.03714814,1.12222956 6.35063424,1.12222956 C7.57292716,1.12222956 8.69020207,1.57730759 9.54442463,2.32587797 L8.46164839,2.32587797 L7.680355,3.10666403 L8.21508437,3.64088607 L7.87238068,3.98257509 L7.7165025,3.82669692 L7.85297518,3.68946324 L7.78930484,3.62566607 L7.78943167,3.62566607 L7.56011699,3.39559038 L7.55986332,3.39571722 L7.49758815,3.33318838 L7.01904595,3.78585658 L7.55910232,4.32654712 L6.8069806,4.32198112 L6.8069806,5.25864535 L7.66716433,5.25864535 L7.6723645,4.72112565 L7.81289584,4.57996014 L8.31819988,5.08653251 L8.31819988,5.41921636 L9.00703176,5.41921636 L9.03366676,5.39321553 L9.03430093,5.39194719 L10.195587,6.55259911 L10.8637451,5.88520206 L11.2018828,5.88520206 C11.2023901,5.9153884 11.2041658,5.94532107 11.2041658,5.97563424 C11.2040389,8.65181776 9.0269446,10.8289121 6.35076107,10.8289121 L6.35076107,10.8289121 Z\" id=\"Shape\" stroke=\"#DDE1E5\" stroke-width=\"0.25\" fill=\"#DDE1E5\"></path><polygon id=\"Shape\" stroke=\"#DDE1E5\" stroke-width=\"0.25\" fill=\"#DDE1E5\" points=\"6.50676608 1.61523076 4.52892694 1.61789426 4.52892694 2.95192735 5.34560683 3.76733891 5.72496536 3.76733891 5.72496536 3.1967157 6.50676608 2.41592965\"></polygon><polygon id=\"Shape\" stroke=\"#DDE1E5\" stroke-width=\"0.25\" fill=\"#DDE1E5\" points=\"9.59959714 6.88718547 8.28623788 5.57268471 8.28623788 5.57002121 6.79607294 5.57002121 6.35101474 6.01469891 6.35101474 6.96201714 6.98429362 7.59466185 8.12909136 7.59466185 8.12909136 8.70343893 8.99434843 9.56882283 9.20971144 9.56882283 9.20971144 8.50329592 9.63029081 8.08271655 9.63029081 7.3026915 9.87025949 7.3026915 10.1711082 7.00082814 10.0558167 6.88718547\"></polygon></g></svg>" + +/***/ }, +/* 322 */ +/***/ function(module, exports) { + + module.exports = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\"><path class=\"st0\" d=\"M9 9.3l3.6 3.6\"></path><ellipse fill=\"transparent\" cx=\"5.9\" cy=\"6.2\" rx=\"4.5\" ry=\"4.5\"></ellipse></svg>" + +/***/ }, +/* 323 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><g fill-rule=\"evenodd\"><path d=\"M6.5 12.003l.052-9a.5.5 0 1 0-1-.006l-.052 9a.5.5 0 1 0 1 .006zM13 11.997l-.05-9a.488.488 0 0 0-.477-.497.488.488 0 0 0-.473.503l.05 9a.488.488 0 0 0 .477.497.488.488 0 0 0 .473-.503z\"></path></g></svg>" + +/***/ }, +/* 324 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10.483 13.995H5.517l-3.512-3.512V5.516l3.512-3.512h4.966l3.512 3.512v4.967l-3.512 3.512zm4.37-9.042l-3.807-3.805A.503.503 0 0 0 10.691 1H5.309a.503.503 0 0 0-.356.148L1.147 4.953A.502.502 0 0 0 1 5.308v5.383c0 .134.053.262.147.356l3.806 3.806a.503.503 0 0 0 .356.147h5.382a.503.503 0 0 0 .355-.147l3.806-3.806A.502.502 0 0 0 15 10.69V5.308a.502.502 0 0 0-.147-.355z\"></path><path d=\"M10 10.5a.5.5 0 1 0 1 0v-5a.5.5 0 1 0-1 0v5zM5 10.5a.5.5 0 1 0 1 0v-5a.5.5 0 0 0-1 0v5z\"></path></svg>" + +/***/ }, +/* 325 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.5 8.5V14a.5.5 0 1 1-1 0V8.5H2a.5.5 0 0 1 0-1h5.5V2a.5.5 0 0 1 1 0v5.5H14a.5.5 0 1 1 0 1H8.5z\" fill-rule=\"evenodd\"></path></svg>" + +/***/ }, +/* 326 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M4.525 13.21h-.472c-.574 0-.987-.154-1.24-.463-.253-.31-.38-.882-.38-1.719v-.573c0-.746-.097-1.265-.292-1.557-.196-.293-.51-.44-.945-.44v-.974c.435 0 .75-.146.945-.44.195-.292.293-.811.293-1.556v-.58c0-.833.126-1.404.379-1.712.253-.31.666-.464 1.24-.464h.472v.783h-.179c-.37 0-.628.08-.774.24-.145.159-.218.54-.218 1.141v.383c0 .824-.096 1.432-.287 1.823-.191.39-.516.679-.974.866.458.191.783.482.974.873.191.39.287.998.287 1.823v.382c0 .602.073.982.218 1.142.146.16.404.239.774.239h.18v.783zm9.502-4.752c-.43 0-.744.147-.942.44-.197.292-.296.811-.296 1.557v.573c0 .837-.125 1.41-.376 1.719-.251.309-.664.463-1.237.463h-.478v-.783h.185c.37 0 .628-.08.774-.24.145-.159.218-.539.218-1.14v-.383c0-.825.096-1.433.287-1.823.191-.39.516-.682.974-.873-.458-.187-.783-.476-.974-.866-.191-.391-.287-.999-.287-1.823v-.383c0-.602-.073-.982-.218-1.142-.146-.159-.404-.239-.774-.239h-.185v-.783h.478c.573 0 .986.155 1.237.464.25.308.376.88.376 1.712v.58c0 .673.088 1.174.263 1.503.176.329.5.493.975.493v.974z\" fill-rule=\"evenodd\"></path></svg>" + +/***/ }, +/* 327 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6.925 12.5l7.4-5-7.4-5v10zM6 12.5v-10c0-.785.8-1.264 1.415-.848l7.4 5c.58.392.58 1.304 0 1.696l-7.4 5C6.8 13.764 6 13.285 6 12.5z\" fill-rule=\"evenodd\"></path></svg>" + +/***/ }, +/* 328 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 33 12\"><path id=\"base-path\" d=\"M27.1,0H1C0.4,0,0,0.4,0,1v10c0,0.6,0.4,1,1,1h26.1 c0.6,0,1.2-0.3,1.5-0.7L33,6l-4.4-5.3C28.2,0.3,27.7,0,27.1,0z\"></path></svg>" + +/***/ }, +/* 329 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><g fill-rule=\"evenodd\"><path d=\"M1.5 14.042h4.095a.5.5 0 0 0 0-1H1.5a.5.5 0 1 0 0 1zM7.983 2a.5.5 0 0 1 .517.5v7.483l3.136-3.326a.5.5 0 1 1 .728.686l-4 4.243a.499.499 0 0 1-.73-.004L3.635 7.343a.5.5 0 0 1 .728-.686L7.5 9.983V3H1.536C1.24 3 1 2.776 1 2.5s.24-.5.536-.5h6.447zM10.5 14.042h4.095a.5.5 0 0 0 0-1H10.5a.5.5 0 1 0 0 1z\"></path></g></svg>" + +/***/ }, +/* 330 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><g fill-rule=\"evenodd\"><path d=\"M5 13.5H1a.5.5 0 1 0 0 1h4a.5.5 0 1 0 0-1zM12 13.5H8a.5.5 0 1 0 0 1h4a.5.5 0 1 0 0-1zM6.11 5.012A.427.427 0 0 1 6.21 5h7.083L9.646 1.354a.5.5 0 1 1 .708-.708l4.5 4.5a.498.498 0 0 1 0 .708l-4.5 4.5a.5.5 0 0 1-.708-.708L13.293 6H6.5v5.5a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .61-.488z\"></path></g></svg>" + +/***/ }, +/* 331 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><g fill-rule=\"evenodd\"><path d=\"M13.297 6.912C12.595 4.39 10.167 2.5 7.398 2.5A5.898 5.898 0 0 0 1.5 8.398a.5.5 0 0 0 1 0A4.898 4.898 0 0 1 7.398 3.5c2.75 0 5.102 2.236 5.102 4.898v.004L8.669 7.029a.5.5 0 0 0-.338.942l4.462 1.598a.5.5 0 0 0 .651-.34.506.506 0 0 0 .02-.043l2-5a.5.5 0 1 0-.928-.372l-1.24 3.098z\"></path><circle cx=\"7\" cy=\"12\" r=\"1\"></circle></g></svg>" + +/***/ }, +/* 332 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12.219 7c.345 0 .635.117.869.352.234.234.351.524.351.869 0 .351-.118.652-.356.903-.238.25-.526.376-.864.376-.332 0-.615-.125-.85-.376a1.276 1.276 0 0 1-.351-.903A1.185 1.185 0 0 1 12.218 7zM8.234 7c.345 0 .635.117.87.352.234.234.351.524.351.869 0 .351-.119.652-.356.903-.238.25-.526.376-.865.376-.332 0-.613-.125-.844-.376a1.286 1.286 0 0 1-.347-.903c0-.352.114-.643.342-.874.228-.231.51-.347.85-.347zM4.201 7c.339 0 .627.117.864.352.238.234.357.524.357.869 0 .351-.119.652-.357.903-.237.25-.525.376-.864.376-.338 0-.623-.125-.854-.376A1.286 1.286 0 0 1 3 8.221 1.185 1.185 0 0 1 4.201 7z\" fill-rule=\"evenodd\"></path></svg>" + +/***/ }, +/* 333 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><g fill-rule=\"evenodd\"><path d=\"M3.233 11.25l-.417 1H1.712C.763 12.25 0 11.574 0 10.747V6.503C0 5.675.755 5 1.712 5h4.127l-.417 1H1.597C1.257 6 1 6.225 1 6.503v4.244c0 .277.267.503.597.503h1.636zM7.405 11.27L7 12.306c.865.01 2.212-.024 2.315-.04.112-.016.112-.016.185-.035.075-.02.156-.046.251-.082.152-.056.349-.138.592-.244.415-.182.962-.435 1.612-.744l.138-.066a179.35 179.35 0 0 0 2.255-1.094c1.191-.546 1.191-2.074-.025-2.632l-.737-.34a3547.554 3547.554 0 0 0-3.854-1.78c-.029.11-.065.222-.11.336l-.232.596c.894.408 4.56 2.107 4.56 2.107.458.21.458.596 0 .806L9.197 11.27H7.405zM4.462 14.692l5-12a.5.5 0 1 0-.924-.384l-5 12a.5.5 0 1 0 .924.384z\"></path></g></svg>" + +/***/ }, +/* 334 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path fill-rule=\"evenodd\" d=\"M8.5 8.793L5.854 6.146l-.04-.035L7.5 4.426c.2-.2.3-.4.3-.6 0-.2-.1-.4-.2-.6l-1-1c-.4-.3-.9-.3-1.2 0l-4.1 4.1c-.2.2-.3.4-.3.6 0 .2.1.4.2.6l1 1c.3.3.9.3 1.2 0l1.71-1.71.036.04L7.793 9.5l-3.647 3.646c-.195.196-.195.512 0 .708.196.195.512.195.708 0L8.5 10.207l3.646 3.647c.196.195.512.195.708 0 .195-.196.195-.512 0-.708L9.207 9.5l2.565-2.565L13.3 8.5c.1.1 2.3 1.1 2.7.7.4-.4-.3-2.7-.5-2.9l-1.1-1.1c.1-.1.2-.4.2-.6 0-.2-.1-.4-.2-.6l-.4-.4c-.3-.3-.8-.3-1.1 0l-1.5-1.4c-.2-.2-.3-.2-.5-.2s-.3.1-.5.2L9.2 3.4c-.2.1-.2.2-.2.4s.1.4.2.5l1.874 1.92L8.5 8.792z\"></path></svg>" + +/***/ }, +/* 335 */ +/***/ function(module, exports) { + + module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"#D92215\"><path d=\"M8 14.5c-3.6 0-6.5-2.9-6.5-6.5S4.4 1.5 8 1.5s6.5 2.9 6.5 6.5-2.9 6.5-6.5 6.5zm0-12C5 2.5 2.5 5 2.5 8S5 13.5 8 13.5 13.5 11 13.5 8 11 2.5 8 2.5z\"></path><circle cx=\"5\" cy=\"6\" r=\"1\" transform=\"translate(1 1)\"></circle><circle cx=\"9\" cy=\"6\" r=\"1\" transform=\"translate(1 1)\"></circle><path d=\"M5.5 11c-.1 0-.2 0-.3-.1-.2-.1-.3-.4-.1-.7C6 9 7 8.5 8.1 8.5c1.7.1 2.8 1.7 2.8 1.8.2.2.1.5-.1.7-.2.1-.6 0-.7-.2 0 0-.9-1.3-2-1.3-.7 0-1.4.4-2.1 1.3-.2.2-.4.2-.5.2z\"></path></svg>" + +/***/ }, +/* 336 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + var Svg = __webpack_require__(310); + + __webpack_require__(337); + + function CloseButton(_ref) { + var handleClick = _ref.handleClick; + var buttonClass = _ref.buttonClass; + + return dom.div({ + className: buttonClass ? "close-btn-" + buttonClass : "close-btn", + onClick: handleClick + }, Svg("close")); + } + + CloseButton.propTypes = { + handleClick: PropTypes.func.isRequired + }; + + module.exports = CloseButton; + +/***/ }, +/* 337 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 338 */, +/* 339 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + var ImPropTypes = __webpack_require__(235); + + var _require = __webpack_require__(3); + + var bindActionCreators = _require.bindActionCreators; + + var _require2 = __webpack_require__(19); + + var connect = _require2.connect; + + var _require3 = __webpack_require__(261); + + var cmdString = _require3.cmdString; + + var SourcesTree = React.createFactory(__webpack_require__(340)); + var actions = __webpack_require__(262); + + var _require4 = __webpack_require__(259); + + var getSelectedSource = _require4.getSelectedSource; + var getSources = _require4.getSources; + + + __webpack_require__(398); + + var Sources = React.createClass({ + propTypes: { + sources: ImPropTypes.map.isRequired, + selectSource: PropTypes.func.isRequired + }, + + displayName: "Sources", + + render() { + var _props = this.props; + var sources = _props.sources; + var selectSource = _props.selectSource; + + + return dom.div({ className: "sources-panel" }, dom.div({ className: "sources-header" }, L10N.getStr("sources.header"), dom.span({ className: "sources-header-info" }, L10N.getFormatStr("sources.search", cmdString() + "+P"))), SourcesTree({ sources, selectSource })); + } + }); + + module.exports = connect(state => ({ selectedSource: getSelectedSource(state), + sources: getSources(state) }), dispatch => bindActionCreators(actions, dispatch))(Sources); + +/***/ }, +/* 340 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + var classnames = __webpack_require__(211); + var ImPropTypes = __webpack_require__(235); + + var _require = __webpack_require__(229); + + var Set = _require.Set; + + var _require2 = __webpack_require__(341); + + var nodeHasChildren = _require2.nodeHasChildren; + var createParentMap = _require2.createParentMap; + var addToTree = _require2.addToTree; + var collapseTree = _require2.collapseTree; + var createTree = _require2.createTree; + + var ManagedTree = React.createFactory(__webpack_require__(394)); + var Svg = __webpack_require__(310); + + var _require3 = __webpack_require__(244); + + var throttle = _require3.throttle; + + + var SourcesTree = React.createClass({ + propTypes: { + sources: ImPropTypes.map.isRequired, + selectSource: PropTypes.func.isRequired + }, + + displayName: "SourcesTree", + + getInitialState() { + return createTree(this.props.sources); + }, + + queueUpdate: throttle(function () { + if (!this.isMounted()) { + return; + } + + this.forceUpdate(); + }, 50), + + shouldComponentUpdate() { + this.queueUpdate(); + return false; + }, + + componentWillReceiveProps(nextProps) { + if (nextProps.sources === this.props.sources) { + return; + } + + if (nextProps.sources.size === 0) { + this.setState(createTree(nextProps.sources)); + return; + } + + var next = Set(nextProps.sources.valueSeq()); + var prev = Set(this.props.sources.valueSeq()); + var newSet = next.subtract(prev); + + var uncollapsedTree = this.state.uncollapsedTree; + for (var source of newSet) { + addToTree(uncollapsedTree, source); + } + + // TODO: recreating the tree every time messes with the expanded + // state of ManagedTree, because it depends on item instances + // being the same. The result is that if a source is added at a + // later time, all expanded state is lost. + var sourceTree = newSet.size > 0 ? collapseTree(uncollapsedTree) : this.state.sourceTree; + + this.setState({ uncollapsedTree, + sourceTree, + parentMap: createParentMap(sourceTree) }); + }, + + focusItem(item) { + this.setState({ focusedItem: item }); + }, + + selectItem(item) { + if (!nodeHasChildren(item)) { + this.props.selectSource(item.contents.get("id")); + } + }, + + getIcon(item, depth) { + if (depth === 0) { + return Svg("domain"); + } + + if (!nodeHasChildren(item)) { + return Svg("file"); + } + + return Svg("folder"); + }, + + renderItem(item, depth, focused, _, expanded, _ref) { + var setExpanded = _ref.setExpanded; + + var arrow = Svg("arrow", { + className: classnames({ expanded: expanded, + hidden: !nodeHasChildren(item) }), + onClick: e => { + e.stopPropagation(); + setExpanded(item, !expanded); + } + }); + + var icon = this.getIcon(item, depth); + + return dom.div({ + className: classnames("node", { focused }), + style: { paddingLeft: depth * 15 + "px" }, + key: item.path, + onClick: () => this.selectItem(item), + onDoubleClick: e => setExpanded(item, !expanded) + }, dom.div(null, arrow, icon, item.name)); + }, + + render: function () { + var _state = this.state; + var focusedItem = _state.focusedItem; + var sourceTree = _state.sourceTree; + var parentMap = _state.parentMap; + + const isEmpty = sourceTree.contents.length === 0; + + var tree = ManagedTree({ + key: isEmpty ? "empty" : "full", + getParent: item => { + return parentMap.get(item); + }, + getChildren: item => { + if (nodeHasChildren(item)) { + return item.contents; + } + return []; + }, + getRoots: () => sourceTree.contents, + getKey: (item, i) => item.path, + itemHeight: 30, + autoExpandDepth: 1, + onFocus: this.focusItem, + renderItem: this.renderItem + }); + + return dom.div({ + className: "sources-list", + onKeyDown: e => { + if (e.keyCode === 13 && focusedItem) { + this.selectItem(focusedItem); + } + } + }, tree); + } + }); + + module.exports = SourcesTree; + +/***/ }, +/* 341 */ +/***/ function(module, exports, __webpack_require__) { + + + + /** + * Utils for Sources Tree Component + * @module utils/sources-tree + */ + + var _require = __webpack_require__(293); + + var parse = _require.parse; + + var _require2 = __webpack_require__(246); + + var assert = _require2.assert; + + var _require3 = __webpack_require__(277); + + var isPretty = _require3.isPretty; + + var merge = __webpack_require__(342); + + var IGNORED_URLS = ["debugger eval code", "XStringBundle"]; + + /** + * Temporary Source type to be used only within this module + * TODO: Replace with real Source type definition when refactoring types + * @memberof utils/sources-tree + * @static + */ + + + /** + * TODO: createNode is exported so this type could be useful to other modules + * @memberof utils/sources-tree + * @static + */ + + + /** + * @memberof utils/sources-tree + * @static + */ + function nodeHasChildren(item) { + return Array.isArray(item.contents); + } + + /** + * @memberof utils/sources-tree + * @static + */ + function createNode(name, path, contents) { + return { + name, + path, + contents: contents || null + }; + } + + /** + * @memberof utils/sources-tree + * @static + */ + function createParentMap(tree) { + var map = new WeakMap(); + + function _traverse(subtree) { + if (nodeHasChildren(subtree)) { + for (var child of subtree.contents) { + map.set(child, subtree); + _traverse(child); + } + } + } + + // Don't link each top-level path to the "root" node because the + // user never sees the root + tree.contents.forEach(_traverse); + return map; + } + + /** + * @memberof utils/sources-tree + * @static + */ + function getURL(source) { + var url = source.get("url"); + var def = { path: "", group: "" }; + if (!url) { + return def; + } + + var _parse = parse(url); + + var pathname = _parse.pathname; + var protocol = _parse.protocol; + var host = _parse.host; + var path = _parse.path; + + + switch (protocol) { + case "javascript:": + // Ignore `javascript:` URLs for now + return def; + + case "about:": + // An about page is a special case + return merge(def, { + path: "/", + group: url + }); + + case null: + if (pathname && pathname.startsWith("/")) { + // If it's just a URL like "/foo/bar.js", resolve it to the file + // protocol + return merge(def, { + path: path, + group: "file://" + }); + } else if (host === null) { + // We don't know what group to put this under, and it's a script + // with a weird URL. Just group them all under an anonymous group. + return merge(def, { + path: url, + group: "(no domain)" + }); + } + break; + + case "http:": + case "https:": + return merge(def, { + path: pathname, + group: host + }); + } + + return merge(def, { + path: path, + group: protocol ? protocol + "//" : "" + }); + } + + /** + * @memberof utils/sources-tree + * @static + */ + function addToTree(tree, source) { + var url = getURL(source); + + if (IGNORED_URLS.indexOf(url) != -1 || !source.get("url") || isPretty(source.toJS())) { + return; + } + + url.path = decodeURIComponent(url.path); + + var parts = url.path.split("/").filter(p => p !== ""); + var isDir = parts.length === 0 || parts[parts.length - 1].indexOf(".") === -1; + parts.unshift(url.group); + + var path = ""; + var subtree = tree; + + for (var i = 0; i < parts.length; i++) { + var part = parts[i]; + var isLastPart = i === parts.length - 1; + + // Currently we assume that we are descending into a node with + // children. This will fail if a path has a directory named the + // same as another file, like `foo/bar.js/file.js`. + // + // TODO: Be smarter about this, which we'll probably do when we + // are smarter about folders and collapsing empty ones. + assert(nodeHasChildren(subtree), `${ subtree.name } should have children`); + var children = subtree.contents; + + var index = determineFileSortOrder(children, part, isLastPart); + + if (index >= 0 && children[index].name === part) { + // A node with the same name already exists, simply traverse + // into it. + subtree = children[index]; + } else { + // No node with this name exists, so insert a new one in the + // place that is alphabetically sorted. + var node = createNode(part, path + "/" + part, []); + var where = index === -1 ? children.length : index; + children.splice(where, 0, node); + subtree = children[where]; + } + + // Keep track of the children so we can tag each node with them. + path = path + "/" + part; + } + + // Overwrite the contents of the final node to store the source + // there. + if (isDir) { + subtree.contents.unshift(createNode("(index)", source.get("url"), source)); + } else { + subtree.contents = source; + } + } + + /** + * Look at the nodes in the source tree, and determine the index of where to + * insert a new node. The ordering is index -> folder -> file. + * @memberof utils/sources-tree + * @static + */ + function determineFileSortOrder(nodes, pathPart, isLastPart) { + var partIsDir = !isLastPart || pathPart.indexOf(".") === -1; + + return nodes.findIndex(node => { + var nodeIsDir = nodeHasChildren(node); + + // The index will always be the first thing, so this pathPart will be + // after it. + if (node.name === "(index)") { + return false; + } + + // If both the pathPart and node are the same type, then compare them + // alphabetically. + if (partIsDir === nodeIsDir) { + return node.name.localeCompare(pathPart) >= 0; + } + + // If the pathPart and node differ, then stop here if the pathPart is a + // directory. Keep on searching if the part is a file, as it needs to be + // placed after the directories. + return partIsDir; + }); + } + + /** + * Take an existing source tree, and return a new one with collapsed nodes. + * @memberof utils/sources-tree + * @static + */ + function collapseTree(node) { + var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + + // Node is a folder. + if (nodeHasChildren(node)) { + // Node is not a root/domain node, and only contains 1 item. + if (depth > 1 && node.contents.length === 1) { + var next = node.contents[0]; + // Do not collapse if the next node is a leaf node. + if (nodeHasChildren(next)) { + return collapseTree(createNode(`${ node.name }/${ next.name }`, next.path, next.contents), depth + 1); + } + } + // Map the contents. + return createNode(node.name, node.path, node.contents.map(next => collapseTree(next, depth + 1))); + } + // Node is a leaf, not a folder, do not modify it. + return node; + } + + /** + * @memberof utils/sources-tree + * @static + */ + function createTree(sources) { + var uncollapsedTree = createNode("root", "", []); + for (var source of sources.valueSeq()) { + addToTree(uncollapsedTree, source); + } + var sourceTree = collapseTree(uncollapsedTree); + + return { uncollapsedTree, + sourceTree, + parentMap: createParentMap(sourceTree), + focusedItem: null }; + } + + module.exports = { + createNode, + nodeHasChildren, + createParentMap, + addToTree, + collapseTree, + createTree + }; + +/***/ }, +/* 342 */ +/***/ function(module, exports, __webpack_require__) { + + var baseMerge = __webpack_require__(343), + createAssigner = __webpack_require__(384); + + /** + * This method is like `_.assign` except that it recursively merges own and + * inherited enumerable string keyed properties of source objects into the + * destination object. Source properties that resolve to `undefined` are + * skipped if a destination value exists. Array and plain object properties + * are merged recursively. Other objects and value types are overridden by + * assignment. Source objects are applied from left to right. Subsequent + * sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * var object = { + * 'a': [{ 'b': 2 }, { 'd': 4 }] + * }; + * + * var other = { + * 'a': [{ 'c': 3 }, { 'e': 5 }] + * }; + * + * _.merge(object, other); + * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } + */ + var merge = createAssigner(function(object, source, srcIndex) { + baseMerge(object, source, srcIndex); + }); + + module.exports = merge; + + +/***/ }, +/* 343 */ +/***/ function(module, exports, __webpack_require__) { + + var Stack = __webpack_require__(344), + assignMergeValue = __webpack_require__(350), + baseFor = __webpack_require__(353), + baseMergeDeep = __webpack_require__(355), + isObject = __webpack_require__(106), + keysIn = __webpack_require__(378); + + /** + * The base implementation of `_.merge` without support for multiple sources. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. + * @param {Function} [customizer] The function to customize merged values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor(source, function(srcValue, key) { + if (isObject(srcValue)) { + stack || (stack = new Stack); + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); + } + else { + var newValue = customizer + ? customizer(object[key], srcValue, (key + ''), object, source, stack) + : undefined; + + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); + } + + module.exports = baseMerge; + + +/***/ }, +/* 344 */ +/***/ function(module, exports, __webpack_require__) { + + var ListCache = __webpack_require__(117), + stackClear = __webpack_require__(345), + stackDelete = __webpack_require__(346), + stackGet = __webpack_require__(347), + stackHas = __webpack_require__(348), + stackSet = __webpack_require__(349); + + /** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; + } + + // Add methods to `Stack`. + Stack.prototype.clear = stackClear; + Stack.prototype['delete'] = stackDelete; + Stack.prototype.get = stackGet; + Stack.prototype.has = stackHas; + Stack.prototype.set = stackSet; + + module.exports = Stack; + + +/***/ }, +/* 345 */ +/***/ function(module, exports, __webpack_require__) { + + var ListCache = __webpack_require__(117); + + /** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ + function stackClear() { + this.__data__ = new ListCache; + this.size = 0; + } + + module.exports = stackClear; + + +/***/ }, +/* 346 */ +/***/ function(module, exports) { + + /** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; + } + + module.exports = stackDelete; + + +/***/ }, +/* 347 */ +/***/ function(module, exports) { + + /** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function stackGet(key) { + return this.__data__.get(key); + } + + module.exports = stackGet; + + +/***/ }, +/* 348 */ +/***/ function(module, exports) { + + /** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function stackHas(key) { + return this.__data__.has(key); + } + + module.exports = stackHas; + + +/***/ }, +/* 349 */ +/***/ function(module, exports, __webpack_require__) { + + var ListCache = __webpack_require__(117), + Map = __webpack_require__(125), + MapCache = __webpack_require__(98); + + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + + /** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ + function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; + } + + module.exports = stackSet; + + +/***/ }, +/* 350 */ +/***/ function(module, exports, __webpack_require__) { + + var baseAssignValue = __webpack_require__(351), + eq = __webpack_require__(121); + + /** + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignMergeValue(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + module.exports = assignMergeValue; + + +/***/ }, +/* 351 */ +/***/ function(module, exports, __webpack_require__) { + + var defineProperty = __webpack_require__(352); + + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } + } + + module.exports = baseAssignValue; + + +/***/ }, +/* 352 */ +/***/ function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(103); + + var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} + }()); + + module.exports = defineProperty; + + +/***/ }, +/* 353 */ +/***/ function(module, exports, __webpack_require__) { + + var createBaseFor = __webpack_require__(354); + + /** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseFor = createBaseFor(); + + module.exports = baseFor; + + +/***/ }, +/* 354 */ +/***/ function(module, exports) { + + /** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + + module.exports = createBaseFor; + + +/***/ }, +/* 355 */ +/***/ function(module, exports, __webpack_require__) { + + var assignMergeValue = __webpack_require__(350), + cloneBuffer = __webpack_require__(356), + cloneTypedArray = __webpack_require__(357), + copyArray = __webpack_require__(360), + initCloneObject = __webpack_require__(361), + isArguments = __webpack_require__(364), + isArray = __webpack_require__(94), + isArrayLikeObject = __webpack_require__(366), + isBuffer = __webpack_require__(369), + isFunction = __webpack_require__(105), + isObject = __webpack_require__(106), + isPlainObject = __webpack_require__(5), + isTypedArray = __webpack_require__(371), + toPlainObject = __webpack_require__(375); + + /** + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize assigned values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = object[key], + srcValue = source[key], + stacked = stack.get(srcValue); + + if (stacked) { + assignMergeValue(object, key, stacked); + return; + } + var newValue = customizer + ? customizer(objValue, srcValue, (key + ''), object, source, stack) + : undefined; + + var isCommon = newValue === undefined; + + if (isCommon) { + var isArr = isArray(srcValue), + isBuff = !isArr && isBuffer(srcValue), + isTyped = !isArr && !isBuff && isTypedArray(srcValue); + + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray(objValue)) { + newValue = objValue; + } + else if (isArrayLikeObject(objValue)) { + newValue = copyArray(objValue); + } + else if (isBuff) { + isCommon = false; + newValue = cloneBuffer(srcValue, true); + } + else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray(srcValue, true); + } + else { + newValue = []; + } + } + else if (isPlainObject(srcValue) || isArguments(srcValue)) { + newValue = objValue; + if (isArguments(objValue)) { + newValue = toPlainObject(objValue); + } + else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { + newValue = initCloneObject(srcValue); + } + } + else { + isCommon = false; + } + } + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack['delete'](srcValue); + } + assignMergeValue(object, key, newValue); + } + + module.exports = baseMergeDeep; + + +/***/ }, +/* 356 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(109); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; + + /** Built-in value references. */ + var Buffer = moduleExports ? root.Buffer : undefined, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined; + + /** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ + function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; + } + + module.exports = cloneBuffer; + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(77)(module))) + +/***/ }, +/* 357 */ +/***/ function(module, exports, __webpack_require__) { + + var cloneArrayBuffer = __webpack_require__(358); + + /** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ + function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); + } + + module.exports = cloneTypedArray; + + +/***/ }, +/* 358 */ +/***/ function(module, exports, __webpack_require__) { + + var Uint8Array = __webpack_require__(359); + + /** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); + return result; + } + + module.exports = cloneArrayBuffer; + + +/***/ }, +/* 359 */ +/***/ function(module, exports, __webpack_require__) { + + var root = __webpack_require__(109); + + /** Built-in value references. */ + var Uint8Array = root.Uint8Array; + + module.exports = Uint8Array; + + +/***/ }, +/* 360 */ +/***/ function(module, exports) { + + /** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ + function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + + module.exports = copyArray; + + +/***/ }, +/* 361 */ +/***/ function(module, exports, __webpack_require__) { + + var baseCreate = __webpack_require__(362), + getPrototype = __webpack_require__(6), + isPrototype = __webpack_require__(363); + + /** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; + } + + module.exports = initCloneObject; + + +/***/ }, +/* 362 */ +/***/ function(module, exports, __webpack_require__) { + + var isObject = __webpack_require__(106); + + /** Built-in value references. */ + var objectCreate = Object.create; + + /** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; + }()); + + module.exports = baseCreate; + + +/***/ }, +/* 363 */ +/***/ function(module, exports) { + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ + function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; + } + + module.exports = isPrototype; + + +/***/ }, +/* 364 */ +/***/ function(module, exports, __webpack_require__) { + + var baseIsArguments = __webpack_require__(365), + isObjectLike = __webpack_require__(8); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Built-in value references. */ + var propertyIsEnumerable = objectProto.propertyIsEnumerable; + + /** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); + }; + + module.exports = isArguments; + + +/***/ }, +/* 365 */ +/***/ function(module, exports, __webpack_require__) { + + var isObjectLike = __webpack_require__(8); + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]'; + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var objectToString = objectProto.toString; + + /** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ + function baseIsArguments(value) { + return isObjectLike(value) && objectToString.call(value) == argsTag; + } + + module.exports = baseIsArguments; + + +/***/ }, +/* 366 */ +/***/ function(module, exports, __webpack_require__) { + + var isArrayLike = __webpack_require__(367), + isObjectLike = __webpack_require__(8); + + /** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ + function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); + } + + module.exports = isArrayLikeObject; + + +/***/ }, +/* 367 */ +/***/ function(module, exports, __webpack_require__) { + + var isFunction = __webpack_require__(105), + isLength = __webpack_require__(368); + + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } + + module.exports = isArrayLike; + + +/***/ }, +/* 368 */ +/***/ function(module, exports) { + + /** Used as references for various `Number` constants. */ + var MAX_SAFE_INTEGER = 9007199254740991; + + /** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ + function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + + module.exports = isLength; + + +/***/ }, +/* 369 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(109), + stubFalse = __webpack_require__(370); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; + + /** Built-in value references. */ + var Buffer = moduleExports ? root.Buffer : undefined; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined; + + /** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ + var isBuffer = nativeIsBuffer || stubFalse; + + module.exports = isBuffer; + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(77)(module))) + +/***/ }, +/* 370 */ +/***/ function(module, exports) { + + /** + * This method returns `false`. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `false`. + * @example + * + * _.times(2, _.stubFalse); + * // => [false, false] + */ + function stubFalse() { + return false; + } + + module.exports = stubFalse; + + +/***/ }, +/* 371 */ +/***/ function(module, exports, __webpack_require__) { + + var baseIsTypedArray = __webpack_require__(372), + baseUnary = __webpack_require__(373), + nodeUtil = __webpack_require__(374); + + /* Node.js helper references. */ + var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + + /** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ + var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + + module.exports = isTypedArray; + + +/***/ }, +/* 372 */ +/***/ function(module, exports, __webpack_require__) { + + var isLength = __webpack_require__(368), + isObjectLike = __webpack_require__(8); + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + weakMapTag = '[object WeakMap]'; + + var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + + /** Used to identify `toStringTag` values of typed arrays. */ + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = + typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = + typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = + typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = + typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = + typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = + typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = + typedArrayTags[errorTag] = typedArrayTags[funcTag] = + typedArrayTags[mapTag] = typedArrayTags[numberTag] = + typedArrayTags[objectTag] = typedArrayTags[regexpTag] = + typedArrayTags[setTag] = typedArrayTags[stringTag] = + typedArrayTags[weakMapTag] = false; + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var objectToString = objectProto.toString; + + /** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ + function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[objectToString.call(value)]; + } + + module.exports = baseIsTypedArray; + + +/***/ }, +/* 373 */ +/***/ function(module, exports) { + + /** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ + function baseUnary(func) { + return function(value) { + return func(value); + }; + } + + module.exports = baseUnary; + + +/***/ }, +/* 374 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(module) {var freeGlobal = __webpack_require__(110); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; + + /** Detect free variable `process` from Node.js. */ + var freeProcess = moduleExports && freeGlobal.process; + + /** Used to access faster Node.js helpers. */ + var nodeUtil = (function() { + try { + return freeProcess && freeProcess.binding('util'); + } catch (e) {} + }()); + + module.exports = nodeUtil; + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(77)(module))) + +/***/ }, +/* 375 */ +/***/ function(module, exports, __webpack_require__) { + + var copyObject = __webpack_require__(376), + keysIn = __webpack_require__(378); + + /** + * Converts `value` to a plain object flattening inherited enumerable string + * keyed properties of `value` to own properties of the plain object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {Object} Returns the converted plain object. + * @example + * + * function Foo() { + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.assign({ 'a': 1 }, new Foo); + * // => { 'a': 1, 'b': 2 } + * + * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); + * // => { 'a': 1, 'b': 2, 'c': 3 } + */ + function toPlainObject(value) { + return copyObject(value, keysIn(value)); + } + + module.exports = toPlainObject; + + +/***/ }, +/* 376 */ +/***/ function(module, exports, __webpack_require__) { + + var assignValue = __webpack_require__(377), + baseAssignValue = __webpack_require__(351); + + /** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ + function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; + } + + module.exports = copyObject; + + +/***/ }, +/* 377 */ +/***/ function(module, exports, __webpack_require__) { + + var baseAssignValue = __webpack_require__(351), + eq = __webpack_require__(121); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + module.exports = assignValue; + + +/***/ }, +/* 378 */ +/***/ function(module, exports, __webpack_require__) { + + var arrayLikeKeys = __webpack_require__(379), + baseKeysIn = __webpack_require__(382), + isArrayLike = __webpack_require__(367); + + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ + function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); + } + + module.exports = keysIn; + + +/***/ }, +/* 379 */ +/***/ function(module, exports, __webpack_require__) { + + var baseTimes = __webpack_require__(380), + isArguments = __webpack_require__(364), + isArray = __webpack_require__(94), + isBuffer = __webpack_require__(369), + isIndex = __webpack_require__(381), + isTypedArray = __webpack_require__(371); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ + function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; + } + + module.exports = arrayLikeKeys; + + +/***/ }, +/* 380 */ +/***/ function(module, exports) { + + /** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ + function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; + } + + module.exports = baseTimes; + + +/***/ }, +/* 381 */ +/***/ function(module, exports) { + + /** Used as references for various `Number` constants. */ + var MAX_SAFE_INTEGER = 9007199254740991; + + /** Used to detect unsigned integer values. */ + var reIsUint = /^(?:0|[1-9]\d*)$/; + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + length = length == null ? MAX_SAFE_INTEGER : length; + return !!length && + (typeof value == 'number' || reIsUint.test(value)) && + (value > -1 && value % 1 == 0 && value < length); + } + + module.exports = isIndex; + + +/***/ }, +/* 382 */ +/***/ function(module, exports, __webpack_require__) { + + var isObject = __webpack_require__(106), + isPrototype = __webpack_require__(363), + nativeKeysIn = __webpack_require__(383); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + + module.exports = baseKeysIn; + + +/***/ }, +/* 383 */ +/***/ function(module, exports) { + + /** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; + } + + module.exports = nativeKeysIn; + + +/***/ }, +/* 384 */ +/***/ function(module, exports, __webpack_require__) { + + var baseRest = __webpack_require__(385), + isIterateeCall = __webpack_require__(393); + + /** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + + module.exports = createAssigner; + + +/***/ }, +/* 385 */ +/***/ function(module, exports, __webpack_require__) { + + var identity = __webpack_require__(386), + overRest = __webpack_require__(387), + setToString = __webpack_require__(389); + + /** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ + function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); + } + + module.exports = baseRest; + + +/***/ }, +/* 386 */ +/***/ function(module, exports) { + + /** + * This method returns the first argument it receives. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {*} value Any value. + * @returns {*} Returns `value`. + * @example + * + * var object = { 'a': 1 }; + * + * console.log(_.identity(object) === object); + * // => true + */ + function identity(value) { + return value; + } + + module.exports = identity; + + +/***/ }, +/* 387 */ +/***/ function(module, exports, __webpack_require__) { + + var apply = __webpack_require__(388); + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeMax = Math.max; + + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; + } + + module.exports = overRest; + + +/***/ }, +/* 388 */ +/***/ function(module, exports) { + + /** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ + function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); + } + + module.exports = apply; + + +/***/ }, +/* 389 */ +/***/ function(module, exports, __webpack_require__) { + + var baseSetToString = __webpack_require__(390), + shortOut = __webpack_require__(392); + + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = shortOut(baseSetToString); + + module.exports = setToString; + + +/***/ }, +/* 390 */ +/***/ function(module, exports, __webpack_require__) { + + var constant = __webpack_require__(391), + defineProperty = __webpack_require__(352), + identity = __webpack_require__(386); + + /** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var baseSetToString = !defineProperty ? identity : function(func, string) { + return defineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); + }; + + module.exports = baseSetToString; + + +/***/ }, +/* 391 */ +/***/ function(module, exports) { + + /** + * Creates a function that returns `value`. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Util + * @param {*} value The value to return from the new function. + * @returns {Function} Returns the new constant function. + * @example + * + * var objects = _.times(2, _.constant({ 'a': 1 })); + * + * console.log(objects); + * // => [{ 'a': 1 }, { 'a': 1 }] + * + * console.log(objects[0] === objects[1]); + * // => true + */ + function constant(value) { + return function() { + return value; + }; + } + + module.exports = constant; + + +/***/ }, +/* 392 */ +/***/ function(module, exports) { + + /** Used to detect hot functions by number of calls within a span of milliseconds. */ + var HOT_COUNT = 500, + HOT_SPAN = 16; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeNow = Date.now; + + /** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ + function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; + } + + module.exports = shortOut; + + +/***/ }, +/* 393 */ +/***/ function(module, exports, __webpack_require__) { + + var eq = __webpack_require__(121), + isArrayLike = __webpack_require__(367), + isIndex = __webpack_require__(381), + isObject = __webpack_require__(106); + + /** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; + } + + module.exports = isIterateeCall; + + +/***/ }, +/* 394 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var Tree = React.createFactory(__webpack_require__(395)); + __webpack_require__(396); + + var ManagedTree = React.createClass({ + propTypes: Tree.propTypes, + + displayName: "ManagedTree", + + getInitialState() { + return { + expanded: new Set(), + focusedItem: null + }; + }, + + setExpanded(item, isExpanded) { + var expanded = this.state.expanded; + var key = this.props.getKey(item); + if (isExpanded) { + expanded.add(key); + } else { + expanded.delete(key); + } + this.setState({ expanded }); + + if (isExpanded && this.props.onExpand) { + this.props.onExpand(item); + } else if (!expanded && this.props.onCollapse) { + this.props.onCollapse(item); + } + }, + + focusItem(item) { + if (!this.props.disabledFocus && this.state.focusedItem !== item) { + this.setState({ focusedItem: item }); + + if (this.props.onFocus) { + this.props.onFocus(item); + } + } + }, + + render() { + var _this = this; + + var _state = this.state; + var expanded = _state.expanded; + var focusedItem = _state.focusedItem; + + + var props = Object.assign({}, this.props, { + isExpanded: item => expanded.has(this.props.getKey(item)), + focused: focusedItem, + + onExpand: item => this.setExpanded(item, true), + onCollapse: item => this.setExpanded(item, false), + onFocus: this.focusItem, + + renderItem: function () { + var _props; + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return (_props = _this.props).renderItem.apply(_props, args.concat([{ + setExpanded: _this.setExpanded + }])); + } + }); + + return Tree(props); + } + }); + + module.exports = ManagedTree; + +/***/ }, +/* 395 */ +/***/ function(module, exports, __webpack_require__) { + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + + const { DOM: dom, createClass, createFactory, PropTypes } = __webpack_require__(2); + // const { ViewHelpers } = + // require("resource://devtools/client/shared/widgets/ViewHelpers.jsm"); + // let { VirtualScroll } = require("react-virtualized"); + // VirtualScroll = createFactory(VirtualScroll); + + const AUTO_EXPAND_DEPTH = 0; // depth + + /** + * An arrow that displays whether its node is expanded (▼) or collapsed + * (▶). When its node has no children, it is hidden. + */ + const ArrowExpander = createFactory(createClass({ + displayName: "ArrowExpander", + + shouldComponentUpdate(nextProps, nextState) { + return this.props.item !== nextProps.item + || this.props.visible !== nextProps.visible + || this.props.expanded !== nextProps.expanded; + }, + + render() { + const attrs = { + className: "arrow theme-twisty", + onClick: this.props.expanded + ? () => this.props.onCollapse(this.props.item) + : e => this.props.onExpand(this.props.item, e.altKey) + }; + + if (this.props.expanded) { + attrs.className += " open"; + } + + if (!this.props.visible) { + attrs.style = Object.assign({}, this.props.style || {}, { + visibility: "hidden" + }); + } + + return dom.div(attrs, this.props.children); + } + })); + + const TreeNode = createFactory(createClass({ + displayName: "TreeNode", + + componentDidMount() { + if (this.props.focused) { + this.refs.button.focus(); + } + }, + + componentDidUpdate() { + if (this.props.focused) { + this.refs.button.focus(); + } + }, + + shouldComponentUpdate(nextProps) { + return this.props.item !== nextProps.item || + this.props.focused !== nextProps.focused || + this.props.expanded !== nextProps.expanded; + }, + + render() { + const arrow = ArrowExpander({ + item: this.props.item, + expanded: this.props.expanded, + visible: this.props.hasChildren, + onExpand: this.props.onExpand, + onCollapse: this.props.onCollapse, + }); + + let isOddRow = this.props.index % 2; + return dom.div( + { + className: `tree-node div ${isOddRow ? "tree-node-odd" : ""}`, + onFocus: this.props.onFocus, + onClick: this.props.onFocus, + onBlur: this.props.onBlur, + style: { + padding: 0, + margin: 0 + } + }, + + this.props.renderItem(this.props.item, + this.props.depth, + this.props.focused, + arrow, + this.props.expanded), + + // XXX: OSX won't focus/blur regular elements even if you set tabindex + // unless there is an input/button child. + dom.button(this._buttonAttrs) + ); + }, + + _buttonAttrs: { + ref: "button", + style: { + opacity: 0, + width: "0 !important", + height: "0 !important", + padding: "0 !important", + outline: "none", + MozAppearance: "none", + // XXX: Despite resetting all of the above properties (and margin), the + // button still ends up with ~79px width, so we set a large negative + // margin to completely hide it. + MozMarginStart: "-1000px !important", + } + } + })); + + /** + * Create a function that calls the given function `fn` only once per animation + * frame. + * + * @param {Function} fn + * @returns {Function} + */ + function oncePerAnimationFrame(fn) { + let animationId = null; + let argsToPass = null; + return function(...args) { + argsToPass = args; + if (animationId !== null) { + return; + } + + animationId = requestAnimationFrame(() => { + fn.call(this, ...argsToPass); + animationId = null; + argsToPass = null; + }); + }; + } + + const NUMBER_OF_OFFSCREEN_ITEMS = 1; + + /** + * A generic tree component. See propTypes for the public API. + * + * @see `devtools/client/memory/components/test/mochitest/head.js` for usage + * @see `devtools/client/memory/components/heap.js` for usage + */ + const Tree = module.exports = createClass({ + displayName: "Tree", + + propTypes: { + // Required props + + // A function to get an item's parent, or null if it is a root. + getParent: PropTypes.func.isRequired, + // A function to get an item's children. + getChildren: PropTypes.func.isRequired, + // A function which takes an item and ArrowExpander and returns a + // component. + renderItem: PropTypes.func.isRequired, + // A function which returns the roots of the tree (forest). + getRoots: PropTypes.func.isRequired, + // A function to get a unique key for the given item. + getKey: PropTypes.func.isRequired, + // A function to get whether an item is expanded or not. If an item is not + // expanded, then it must be collapsed. + isExpanded: PropTypes.func.isRequired, + // The height of an item in the tree including margin and padding, in + // pixels. + itemHeight: PropTypes.number.isRequired, + + // Optional props + + // The currently focused item, if any such item exists. + focused: PropTypes.any, + // Handle when a new item is focused. + onFocus: PropTypes.func, + // The depth to which we should automatically expand new items. + autoExpandDepth: PropTypes.number, + // Optional event handlers for when items are expanded or collapsed. + onExpand: PropTypes.func, + onCollapse: PropTypes.func, + }, + + getDefaultProps() { + return { + autoExpandDepth: AUTO_EXPAND_DEPTH, + }; + }, + + getInitialState() { + return { + scroll: 0, + height: window.innerHeight, + seen: new Set(), + }; + }, + + componentDidMount() { + window.addEventListener("resize", this._updateHeight); + this._autoExpand(this.props); + this._updateHeight(); + }, + + componentWillUnmount() { + window.removeEventListener("resize", this._updateHeight); + }, + + componentWillReceiveProps(nextProps) { + this._autoExpand(nextProps); + this._updateHeight(); + }, + + _autoExpand(props) { + if (!props.autoExpandDepth) { + return; + } + + // Automatically expand the first autoExpandDepth levels for new items. Do + // not use the usual DFS infrastructure because we don't want to ignore + // collapsed nodes. + const autoExpand = (item, currentDepth) => { + if (currentDepth >= props.autoExpandDepth || + this.state.seen.has(item)) { + return; + } + + props.onExpand(item); + this.state.seen.add(item); + + const children = props.getChildren(item); + const length = children.length; + for (let i = 0; i < length; i++) { + autoExpand(children[i], currentDepth + 1); + } + }; + + const roots = props.getRoots(); + const length = roots.length; + for (let i = 0; i < length; i++) { + autoExpand(roots[i], 0); + } + }, + + render() { + const traversal = this._dfsFromRoots(); + + // Remove `NUMBER_OF_OFFSCREEN_ITEMS` from `begin` and add `2 * + // NUMBER_OF_OFFSCREEN_ITEMS` to `end` so that the top and bottom of the + // page are filled with the `NUMBER_OF_OFFSCREEN_ITEMS` previous and next + // items respectively, rather than whitespace if the item is not in full + // view. + // const begin = Math.max(((this.state.scroll / this.props.itemHeight) | 0) - NUMBER_OF_OFFSCREEN_ITEMS, 0); + // const end = begin + (2 * NUMBER_OF_OFFSCREEN_ITEMS) + ((this.state.height / this.props.itemHeight) | 0); + // const toRender = traversal; + + // const nodes = [ + // dom.div({ + // key: "top-spacer", + // style: { + // padding: 0, + // margin: 0, + // height: begin * this.props.itemHeight + "px" + // } + // }) + // ]; + + const renderItem = i => { + let { item, depth } = traversal[i]; + return TreeNode({ + key: this.props.getKey(item, i), + index: i, + item: item, + depth: depth, + renderItem: this.props.renderItem, + focused: this.props.focused === item, + expanded: this.props.isExpanded(item), + hasChildren: !!this.props.getChildren(item).length, + onExpand: this._onExpand, + onCollapse: this._onCollapse, + onFocus: () => this._focus(i, item), + }); + }; + + // nodes.push(dom.div({ + // key: "bottom-spacer", + // style: { + // padding: 0, + // margin: 0, + // height: (traversal.length - 1 - end) * this.props.itemHeight + "px" + // } + // })); + + const style = Object.assign({}, this.props.style || {}, { + padding: 0, + margin: 0 + }); + + return dom.div( + { + className: "tree", + ref: "tree", + onKeyDown: this._onKeyDown, + onKeyPress: this._preventArrowKeyScrolling, + onKeyUp: this._preventArrowKeyScrolling, + // onScroll: this._onScroll, + style + }, + // VirtualScroll({ + // width: this.props.width, + // height: this.props.height, + // rowsCount: traversal.length, + // rowHeight: this.props.itemHeight, + // rowRenderer: renderItem + // }) + traversal.map((v, i) => renderItem(i)) + ); + }, + + _preventArrowKeyScrolling(e) { + switch (e.key) { + case "ArrowUp": + case "ArrowDown": + case "ArrowLeft": + case "ArrowRight": + e.preventDefault(); + e.stopPropagation(); + if (e.nativeEvent) { + if (e.nativeEvent.preventDefault) { + e.nativeEvent.preventDefault(); + } + if (e.nativeEvent.stopPropagation) { + e.nativeEvent.stopPropagation(); + } + } + } + }, + + /** + * Updates the state's height based on clientHeight. + */ + _updateHeight() { + this.setState({ + height: this.refs.tree.clientHeight + }); + }, + + /** + * Perform a pre-order depth-first search from item. + */ + _dfs(item, maxDepth = Infinity, traversal = [], _depth = 0) { + traversal.push({ item, depth: _depth }); + + if (!this.props.isExpanded(item)) { + return traversal; + } + + const nextDepth = _depth + 1; + + if (nextDepth > maxDepth) { + return traversal; + } + + const children = this.props.getChildren(item); + const length = children.length; + for (let i = 0; i < length; i++) { + this._dfs(children[i], maxDepth, traversal, nextDepth); + } + + return traversal; + }, + + /** + * Perform a pre-order depth-first search over the whole forest. + */ + _dfsFromRoots(maxDepth = Infinity) { + const traversal = []; + + const roots = this.props.getRoots(); + const length = roots.length; + for (let i = 0; i < length; i++) { + this._dfs(roots[i], maxDepth, traversal); + } + + return traversal; + }, + + /** + * Expands current row. + * + * @param {Object} item + * @param {Boolean} expandAllChildren + */ + _onExpand: oncePerAnimationFrame(function(item, expandAllChildren) { + if (this.props.onExpand) { + this.props.onExpand(item); + + if (expandAllChildren) { + const children = this._dfs(item); + const length = children.length; + for (let i = 0; i < length; i++) { + this.props.onExpand(children[i].item); + } + } + } + }), + + /** + * Collapses current row. + * + * @param {Object} item + */ + _onCollapse: oncePerAnimationFrame(function(item) { + if (this.props.onCollapse) { + this.props.onCollapse(item); + } + }), + + /** + * Sets the passed in item to be the focused item. + * + * @param {Number} index + * The index of the item in a full DFS traversal (ignoring collapsed + * nodes). Ignored if `item` is undefined. + * + * @param {Object|undefined} item + * The item to be focused, or undefined to focus no item. + */ + _focus(index, item) { + if (item !== undefined) { + const itemStartPosition = index * this.props.itemHeight; + const itemEndPosition = (index + 1) * this.props.itemHeight; + + // Note that if the height of the viewport (this.state.height) is less than + // `this.props.itemHeight`, we could accidentally try and scroll both up and + // down in a futile attempt to make both the item's start and end positions + // visible. Instead, give priority to the start of the item by checking its + // position first, and then using an "else if", rather than a separate "if", + // for the end position. + if (this.state.scroll > itemStartPosition) { + this.refs.tree.scrollTop = itemStartPosition; + } else if ((this.state.scroll + this.state.height) < itemEndPosition) { + this.refs.tree.scrollTop = itemEndPosition - this.state.height; + } + } + + if (this.props.onFocus) { + this.props.onFocus(item); + } + }, + + /** + * Sets the state to have no focused item. + */ + _onBlur() { + this._focus(0, undefined); + }, + + /** + * Fired on a scroll within the tree's container, updates + * the stored position of the view port to handle virtual view rendering. + * + * @param {Event} e + */ + _onScroll: oncePerAnimationFrame(function(e) { + this.setState({ + scroll: Math.max(this.refs.tree.scrollTop, 0), + height: this.refs.tree.clientHeight + }); + }), + + /** + * Handles key down events in the tree's container. + * + * @param {Event} e + */ + _onKeyDown(e) { + if (this.props.focused == null) { + return; + } + + // Allow parent nodes to use navigation arrows with modifiers. + if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) { + return; + } + + this._preventArrowKeyScrolling(e); + + switch (e.key) { + case "ArrowUp": + this._focusPrevNode(); + return; + + case "ArrowDown": + this._focusNextNode(); + return; + + case "ArrowLeft": + if (this.props.isExpanded(this.props.focused) + && this.props.getChildren(this.props.focused).length) { + this._onCollapse(this.props.focused); + } else { + this._focusParentNode(); + } + return; + + case "ArrowRight": + if (!this.props.isExpanded(this.props.focused)) { + this._onExpand(this.props.focused); + } else { + this._focusNextNode(); + } + return; + } + }, + + /** + * Sets the previous node relative to the currently focused item, to focused. + */ + _focusPrevNode: oncePerAnimationFrame(function() { + // Start a depth first search and keep going until we reach the currently + // focused node. Focus the previous node in the DFS, if it exists. If it + // doesn't exist, we're at the first node already. + + let prev; + let prevIndex; + + const traversal = this._dfsFromRoots(); + const length = traversal.length; + for (let i = 0; i < length; i++) { + const item = traversal[i].item; + if (item === this.props.focused) { + break; + } + prev = item; + prevIndex = i; + } + + if (prev === undefined) { + return; + } + + this._focus(prevIndex, prev); + }), + + /** + * Handles the down arrow key which will focus either the next child + * or sibling row. + */ + _focusNextNode: oncePerAnimationFrame(function() { + // Start a depth first search and keep going until we reach the currently + // focused node. Focus the next node in the DFS, if it exists. If it + // doesn't exist, we're at the last node already. + + const traversal = this._dfsFromRoots(); + const length = traversal.length; + let i = 0; + + while (i < length) { + if (traversal[i].item === this.props.focused) { + break; + } + i++; + } + + if (i + 1 < traversal.length) { + this._focus(i + 1, traversal[i + 1].item); + } + }), + + /** + * Handles the left arrow key, going back up to the current rows' + * parent row. + */ + _focusParentNode: oncePerAnimationFrame(function() { + const parent = this.props.getParent(this.props.focused); + if (!parent) { + return; + } + + const traversal = this._dfsFromRoots(); + const length = traversal.length; + let parentIndex = 0; + for (; parentIndex < length; parentIndex++) { + if (traversal[parentIndex].item === parent) { + break; + } + } + + this._focus(parentIndex, parent); + }), + }); + + +/***/ }, +/* 396 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 397 */, +/* 398 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 399 */, +/* 400 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + var createFactory = React.createFactory; + + + var ReactDOM = __webpack_require__(16); + var ImPropTypes = __webpack_require__(235); + + var _require = __webpack_require__(3); + + var bindActionCreators = _require.bindActionCreators; + + var _require2 = __webpack_require__(19); + + var connect = _require2.connect; + + var SourceEditor = __webpack_require__(401); + var SourceFooter = createFactory(__webpack_require__(402)); + var EditorSearchBar = createFactory(__webpack_require__(406)); + + var _require3 = __webpack_require__(411); + + var renderConditionalPanel = _require3.renderConditionalPanel; + + var _require4 = __webpack_require__(18); + + var debugGlobal = _require4.debugGlobal; + + var _require5 = __webpack_require__(259); + + var getSourceText = _require5.getSourceText; + var getBreakpointsForSource = _require5.getBreakpointsForSource; + var getSelectedLocation = _require5.getSelectedLocation; + var getSelectedFrame = _require5.getSelectedFrame; + var getSelectedSource = _require5.getSelectedSource; + + var _require6 = __webpack_require__(255); + + var makeLocationId = _require6.makeLocationId; + + var actions = __webpack_require__(262); + var Breakpoint = React.createFactory(__webpack_require__(412)); + + var _require7 = __webpack_require__(279); + + var getDocument = _require7.getDocument; + var setDocument = _require7.setDocument; + + var _require8 = __webpack_require__(403); + + var shouldShowFooter = _require8.shouldShowFooter; + + var _require9 = __webpack_require__(89); + + var isFirefox = _require9.isFirefox; + + var _require10 = __webpack_require__(413); + + var showMenu = _require10.showMenu; + + var _require11 = __webpack_require__(89); + + var isEnabled = _require11.isEnabled; + + + __webpack_require__(414); + + function isTextForSource(sourceText) { + return !sourceText.get("loading") && !sourceText.get("error"); + } + + function breakpointAtLine(breakpoints, line) { + return breakpoints.find(b => { + return b.location.line === line + 1; + }); + } + + function getTextForLine(codeMirror, line) { + return codeMirror.getLine(line - 1).trim(); + } + + /** + * Forces the breakpoint gutter to be the same size as the line + * numbers gutter. Editor CSS will absolutely position the gutter + * beneath the line numbers. This makes it easy to be flexible with + * how we overlay breakpoints. + */ + function resizeBreakpointGutter(editor) { + var gutters = editor.display.gutters; + var lineNumbers = gutters.querySelector(".CodeMirror-linenumbers"); + var breakpoints = gutters.querySelector(".breakpoints"); + breakpoints.style.width = lineNumbers.clientWidth + "px"; + } + + var Editor = React.createClass({ + propTypes: { + breakpoints: ImPropTypes.map.isRequired, + selectedLocation: PropTypes.object, + selectedSource: ImPropTypes.map, + sourceText: PropTypes.object, + addBreakpoint: PropTypes.func, + removeBreakpoint: PropTypes.func, + setBreakpointCondition: PropTypes.func, + selectedFrame: PropTypes.object + }, + + displayName: "Editor", + + onGutterClick(cm, line, gutter, ev) { + // ignore right clicks in the gutter + if (ev.which === 3) { + return; + } + + if (this.isCbPanelOpen()) { + return this.closeConditionalPanel(line); + } + + this.toggleBreakpoint(line); + }, + + onGutterContextMenu(event) { + event.preventDefault(); + var line = this.editor.codeMirror.lineAtHeight(event.clientY); + var bp = breakpointAtLine(this.props.breakpoints, line); + this.showGutterMenu(event, line, bp); + }, + + showConditionalPanel(line) { + if (this.isCbPanelOpen()) { + return; + } + + var _props = this.props; + var sourceId = _props.selectedLocation.sourceId; + var setBreakpointCondition = _props.setBreakpointCondition; + var breakpoints = _props.breakpoints; + + + var bp = breakpointAtLine(breakpoints, line); + var location = { sourceId, line: line + 1 }; + var condition = bp ? bp.condition : ""; + + var setBreakpoint = value => { + setBreakpointCondition(location, { + condition: value, + getTextForLine: l => getTextForLine(this.editor.codeMirror, l) + }); + }; + + var panel = renderConditionalPanel({ + condition, + setBreakpoint, + closePanel: this.closeConditionalPanel + }); + + this.cbPanel = this.editor.codeMirror.addLineWidget(line, panel); + this.cbPanel.node.querySelector("input").focus(); + }, + + closeConditionalPanel() { + this.cbPanel.clear(); + this.cbPanel = null; + }, + + isCbPanelOpen() { + return !!this.cbPanel; + }, + + toggleBreakpoint(line) { + var bp = breakpointAtLine(this.props.breakpoints, line); + + if (bp && bp.loading) { + return; + } + + if (bp) { + this.props.removeBreakpoint({ + sourceId: this.props.selectedLocation.sourceId, + line: line + 1 + }); + } else { + this.props.addBreakpoint({ sourceId: this.props.selectedLocation.sourceId, + line: line + 1 }, + // Pass in a function to get line text because the breakpoint + // may slide and it needs to compute the value at the new + // line. + { getTextForLine: l => getTextForLine(this.editor.codeMirror, l) }); + } + }, + + clearDebugLine(selectedFrame) { + if (selectedFrame) { + var line = selectedFrame.location.line; + this.editor.codeMirror.removeLineClass(line - 1, "line", "debug-line"); + } + }, + + setDebugLine(selectedFrame, selectedLocation) { + if (selectedFrame && selectedLocation && selectedFrame.location.sourceId === selectedLocation.sourceId) { + var line = selectedFrame.location.line; + this.editor.codeMirror.addLineClass(line - 1, "line", "debug-line"); + } + }, + + highlightLine() { + if (!this.pendingJumpLine) { + return; + } + + // If the location has changed and a specific line is requested, + // move to that line and flash it. + var codeMirror = this.editor.codeMirror; + + // Make sure to clean up after ourselves. Not only does this + // cancel any existing animation, but it avoids it from + // happening ever again (in case CodeMirror re-applies the + // class, etc). + if (this.lastJumpLine) { + codeMirror.removeLineClass(this.lastJumpLine - 1, "line", "highlight-line"); + } + + var line = this.pendingJumpLine; + this.editor.alignLine(line); + + // We only want to do the flashing animation if it's not a debug + // line, which has it's own styling. + if (!this.props.selectedFrame || this.props.selectedFrame.location.line !== line) { + this.editor.codeMirror.addLineClass(line - 1, "line", "highlight-line"); + } + + this.lastJumpLine = line; + this.pendingJumpLine = null; + }, + + setText(text) { + if (!text || !this.editor) { + return; + } + + this.editor.setText(text); + }, + + setMode(sourceText) { + var contentType = sourceText.get("contentType"); + + if (contentType.includes("javascript")) { + this.editor.setMode({ name: "javascript" }); + } else if (contentType === "text/wasm") { + this.editor.setMode({ name: "text" }); + } else if (sourceText.get("text").match(/^\s*</)) { + // Use HTML mode for files in which the first non whitespace + // character is `<` regardless of extension. + this.editor.setMode({ name: "htmlmixed" }); + } else { + this.editor.setMode({ name: "text" }); + } + }, + + showGutterMenu(e, line, bp) { + var bpLabel = void 0; + var cbLabel = void 0; + if (!bp) { + bpLabel = L10N.getStr("editor.addBreakpoint"); + cbLabel = L10N.getStr("editor.addConditionalBreakpoint"); + } else { + bpLabel = L10N.getStr("editor.removeBreakpoint"); + cbLabel = L10N.getStr("editor.editBreakpoint"); + } + + var toggleBreakpoint = { + id: "node-menu-breakpoint", + label: bpLabel, + accesskey: "B", + disabled: false, + click: () => { + this.toggleBreakpoint(line); + if (this.isCbPanelOpen()) { + this.closeConditionalPanel(); + } + } + }; + + var conditionalBreakpoint = { + id: "node-menu-conditional-breakpoint", + label: cbLabel, + accesskey: "C", + disabled: false, + click: () => this.showConditionalPanel(line) + }; + + showMenu(e, [toggleBreakpoint, conditionalBreakpoint]); + }, + + componentDidMount() { + this.cbPanel = null; + + this.editor = new SourceEditor({ + mode: "javascript", + readOnly: true, + lineNumbers: true, + theme: "mozilla", + lineWrapping: false, + matchBrackets: true, + showAnnotationRuler: true, + enableCodeFolding: false, + gutters: ["breakpoints"], + value: " ", + extraKeys: {} + }); + + // disables the default search shortcuts + if (isEnabled("editorSearch")) { + this.editor._initShortcuts = () => {}; + } + + this.editor.appendToLocalElement(ReactDOM.findDOMNode(this).querySelector(".editor-mount")); + + this.editor.codeMirror.on("gutterClick", this.onGutterClick); + + if (!isFirefox()) { + this.editor.codeMirror.on("gutterContextMenu", (cm, line, eventName, event) => this.onGutterContextMenu(event)); + } else { + this.editor.codeMirror.getWrapperElement().addEventListener("contextmenu", event => this.onGutterContextMenu(event), false); + } + + resizeBreakpointGutter(this.editor.codeMirror); + debugGlobal("cm", this.editor.codeMirror); + + if (this.props.sourceText) { + this.setText(this.props.sourceText.get("text")); + } + }, + + componentWillUnmount() { + this.editor.destroy(); + this.editor = null; + }, + + componentWillReceiveProps(nextProps) { + // This lifecycle method is responsible for updating the editor + // text. + var sourceText = nextProps.sourceText; + var selectedLocation = nextProps.selectedLocation; + + this.clearDebugLine(this.props.selectedFrame); + + if (!sourceText) { + this.showMessage(""); + } else if (!isTextForSource(sourceText)) { + this.showMessage(sourceText.get("error") || "Loading..."); + } else if (this.props.sourceText !== sourceText) { + this.showSourceText(sourceText, selectedLocation); + } + + this.setDebugLine(nextProps.selectedFrame, selectedLocation); + resizeBreakpointGutter(this.editor.codeMirror); + }, + + showMessage(msg) { + this.editor.replaceDocument(this.editor.createDocument()); + this.setText(msg); + this.editor.setMode({ name: "text" }); + }, + + /** + * Handle getting the source document or creating a new + * document with the correct mode and text. + * + */ + showSourceText(sourceText, selectedLocation) { + var doc = getDocument(selectedLocation.sourceId); + if (doc) { + this.editor.replaceDocument(doc); + return doc; + } + + doc = this.editor.createDocument(); + setDocument(selectedLocation.sourceId, doc); + this.editor.replaceDocument(doc); + + this.setText(sourceText.get("text")); + this.setMode(sourceText); + }, + + componentDidUpdate(prevProps) { + // This is in `componentDidUpdate` so helper functions can expect + // `this.props` to be the current props. This lifecycle method is + // responsible for updating the editor annotations. + var selectedLocation = this.props.selectedLocation; + + // If the location is different and a new line is requested, + // update the pending jump line. Note that if jumping to a line in + // a source where the text hasn't been loaded yet, we will set the + // line here but not jump until rendering the actual source. + + if (prevProps.selectedLocation !== selectedLocation) { + if (selectedLocation && selectedLocation.line != undefined) { + this.pendingJumpLine = selectedLocation.line; + } else { + this.pendingJumpLine = null; + } + } + + // Only update and jump around in real source texts. This will + // keep the jump state around until the real source text is + // loaded. + if (this.props.sourceText && isTextForSource(this.props.sourceText)) { + this.highlightLine(); + } + }, + + renderBreakpoints() { + var _props2 = this.props; + var breakpoints = _props2.breakpoints; + var sourceText = _props2.sourceText; + + var isLoading = sourceText && sourceText.get("loading"); + + if (isLoading) { + return; + } + + return breakpoints.valueSeq().map(bp => { + return Breakpoint({ + key: makeLocationId(bp.location), + breakpoint: bp, + editor: this.editor && this.editor.codeMirror + }); + }); + }, + + editorHeight() { + var selectedSource = this.props.selectedSource; + + + if (!selectedSource || !shouldShowFooter(selectedSource.toJS())) { + return "100%"; + } + + return ""; + }, + + render() { + var sourceText = this.props.sourceText; + + + return dom.div({ className: "editor-wrapper devtools-monospace" }, EditorSearchBar({ + editor: this.editor, + sourceText + }), dom.div({ + className: "editor-mount", + style: { height: this.editorHeight() } + }), this.renderBreakpoints(), SourceFooter({ editor: this.editor })); + } + }); + + module.exports = connect(state => { + var selectedLocation = getSelectedLocation(state); + var sourceId = selectedLocation && selectedLocation.sourceId; + var selectedSource = getSelectedSource(state); + + return { + selectedLocation, + selectedSource, + sourceText: getSourceText(state, sourceId), + breakpoints: getBreakpointsForSource(state, sourceId), + selectedFrame: getSelectedFrame(state) + }; + }, dispatch => bindActionCreators(actions, dispatch))(Editor); + +/***/ }, +/* 401 */ +/***/ function(module, exports) { + + module.exports = devtoolsRequire("devtools/client/sourceeditor/editor"); + +/***/ }, +/* 402 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + var _require = __webpack_require__(19); + + var connect = _require.connect; + + var _require2 = __webpack_require__(3); + + var bindActionCreators = _require2.bindActionCreators; + + var actions = __webpack_require__(262); + + var _require3 = __webpack_require__(259); + + var getSelectedSource = _require3.getSelectedSource; + var getSourceText = _require3.getSourceText; + var getPrettySource = _require3.getPrettySource; + + var Svg = __webpack_require__(310); + var ImPropTypes = __webpack_require__(235); + var classnames = __webpack_require__(211); + + var _require4 = __webpack_require__(277); + + var isPretty = _require4.isPretty; + + var _require5 = __webpack_require__(403); + + var shouldShowFooter = _require5.shouldShowFooter; + var shouldShowPrettyPrint = _require5.shouldShowPrettyPrint; + + + __webpack_require__(404); + + function debugBtn(onClick, type) { + var className = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "active"; + var tooltip = arguments[3]; + + className = `${ type } ${ className }`; + return dom.span({ onClick, className, key: type }, Svg(type, { title: tooltip })); + } + + var SourceFooter = React.createClass({ + propTypes: { + selectedSource: ImPropTypes.map, + togglePrettyPrint: PropTypes.func, + sourceText: ImPropTypes.map, + selectSource: PropTypes.func, + prettySource: ImPropTypes.map, + editor: PropTypes.object + }, + + displayName: "SourceFooter", + + onClickPrettyPrint() { + this.props.togglePrettyPrint(this.props.selectedSource.get("id")); + }, + + prettyPrintButton() { + var _props = this.props; + var selectedSource = _props.selectedSource; + var sourceText = _props.sourceText; + + var sourceLoaded = selectedSource && !sourceText.get("loading"); + + if (!shouldShowPrettyPrint(selectedSource.toJS())) { + return; + } + + return debugBtn(this.onClickPrettyPrint, "prettyPrint", classnames({ + active: sourceLoaded, + pretty: isPretty(selectedSource.toJS()) + }), "Prettify Source"); + }, + + render() { + var selectedSource = this.props.selectedSource; + + + if (!selectedSource || !shouldShowFooter(selectedSource.toJS())) { + return null; + } + + return dom.div({ className: "source-footer" }, dom.div({ className: "command-bar" }, this.prettyPrintButton())); + } + }); + + module.exports = connect(state => { + var selectedSource = getSelectedSource(state); + var selectedId = selectedSource && selectedSource.get("id"); + return { + selectedSource, + sourceText: getSourceText(state, selectedId), + prettySource: getPrettySource(state, selectedId) + }; + }, dispatch => bindActionCreators(actions, dispatch))(SourceFooter); + +/***/ }, +/* 403 */ +/***/ function(module, exports, __webpack_require__) { + + var _require = __webpack_require__(277); + + var isPretty = _require.isPretty; + + var _require2 = __webpack_require__(89); + + var isEnabled = _require2.isEnabled; + + var _require3 = __webpack_require__(264); + + var isOriginalId = _require3.isOriginalId; + + + function shouldShowPrettyPrint(selectedSource) { + if (!isEnabled("prettyPrint")) { + return false; + } + + var _isPretty = isPretty(selectedSource); + var isOriginal = isOriginalId(selectedSource.id); + var hasSourceMap = selectedSource.sourceMapURL; + + if (_isPretty || isOriginal || hasSourceMap) { + return false; + } + + return true; + } + + function shouldShowFooter(selectedSource) { + return shouldShowPrettyPrint(selectedSource); + } + + module.exports = { + shouldShowPrettyPrint, + shouldShowFooter + }; + +/***/ }, +/* 404 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 405 */, +/* 406 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + var _require = __webpack_require__(16); + + var findDOMNode = _require.findDOMNode; + + var Svg = __webpack_require__(310); + + var _require2 = __webpack_require__(407); + + var find = _require2.find; + var findNext = _require2.findNext; + var findPrev = _require2.findPrev; + + var classnames = __webpack_require__(211); + + var _require3 = __webpack_require__(408); + + var debounce = _require3.debounce; + var escapeRegExp = _require3.escapeRegExp; + + var CloseButton = __webpack_require__(336); + + var _require4 = __webpack_require__(89); + + var isEnabled = _require4.isEnabled; + + + __webpack_require__(409); + + function countMatches(query, text) { + var re = new RegExp(escapeRegExp(query), "g"); + var match = text.match(re); + return match ? match.length : 0; + } + + var EditorSearchBar = React.createClass({ + + propTypes: { + editor: PropTypes.object, + sourceText: PropTypes.object + }, + + displayName: "EditorSearchBar", + + getInitialState() { + return { + enabled: false, + query: "", + count: 0, + index: 0 + }; + }, + + contextTypes: { + shortcuts: PropTypes.object + }, + + componentWillUnmount() { + var shortcuts = this.context.shortcuts; + if (isEnabled("editorSearch")) { + shortcuts.off("CmdOrCtrl+F", this.toggleSearch); + shortcuts.off("Escape", this.onEscape); + } + }, + + componentDidMount() { + var shortcuts = this.context.shortcuts; + if (isEnabled("editorSearch")) { + shortcuts.on("CmdOrCtrl+F", this.toggleSearch); + shortcuts.on("Escape", this.onEscape); + } + }, + + componentWillReceiveProps() { + var shortcuts = this.context.shortcuts; + shortcuts.on("CmdOrCtrl+Shift+G", (_, e) => this.traverseResultsPrev(e)); + shortcuts.on("CmdOrCtrl+G", (_, e) => this.traverseResultsNext(e)); + }, + + componentDidUpdate() { + if (this.searchInput()) { + this.searchInput().focus(); + } + }, + + onEscape(shortcut, e) { + this.closeSearch(e); + }, + + closeSearch(e) { + if (this.state.enabled) { + this.setState({ enabled: false }); + e.stopPropagation(); + e.preventDefault(); + } + }, + + toggleSearch(shortcut, e) { + e.stopPropagation(); + e.preventDefault(); + + this.setState({ enabled: !this.state.enabled }); + + if (this.state.enabled) { + var node = this.searchInput(); + if (node) { + node.setSelectionRange(0, node.value.length); + } + } + }, + + searchInput() { + return findDOMNode(this).querySelector("input"); + }, + + onChange(e) { + var query = e.target.value; + + var count = countMatches(query, this.props.sourceText.get("text")); + this.setState({ query, count, index: 0 }); + + this.search(query); + }, + + traverseResultsPrev(e) { + e.stopPropagation(); + e.preventDefault(); + + var ed = this.props.editor; + var ctx = { ed, cm: ed.codeMirror }; + var _state = this.state; + var query = _state.query; + var index = _state.index; + var count = _state.count; + + + findPrev(ctx, query); + var nextIndex = index == 0 ? count - 1 : index - 1; + this.setState({ index: nextIndex }); + }, + + traverseResultsNext(e) { + e.stopPropagation(); + e.preventDefault(); + + var ed = this.props.editor; + var ctx = { ed, cm: ed.codeMirror }; + var _state2 = this.state; + var query = _state2.query; + var index = _state2.index; + var count = _state2.count; + + + findNext(ctx, query); + var nextIndex = index == count - 1 ? 0 : index + 1; + this.setState({ index: nextIndex }); + }, + + onKeyUp(e) { + if (e.key != "Enter") { + return; + } + + if (e.shiftKey) { + this.traverseResultsPrev(e); + } else { + this.traverseResultsNext(e); + } + }, + + search: debounce(function (query) { + var ed = this.props.editor; + var ctx = { ed, cm: ed.codeMirror }; + + find(ctx, query); + }, 100), + + renderSummary() { + var _state3 = this.state; + var count = _state3.count; + var index = _state3.index; + var query = _state3.query; + + + if (query.trim() == "") { + return dom.div({}); + } else if (count == 0) { + return dom.div({ className: "summary" }, L10N.getStr("editor.noResults")); + } + + return dom.div({ className: "summary" }, L10N.getFormatStr("editor.searchResults", index + 1, count)); + }, + + renderSvg() { + var _state4 = this.state; + var count = _state4.count; + var query = _state4.query; + + + if (count == 0 && query.trim() != "") { + return Svg("sad-face"); + } + + return Svg("magnifying-glass"); + }, + + render() { + if (!this.state.enabled) { + return dom.div(); + } + + var _state5 = this.state; + var count = _state5.count; + var query = _state5.query; + + + return dom.div({ className: "search-bar" }, this.renderSvg(), dom.input({ + className: classnames({ + empty: count == 0 && query.trim() != "" + }), + onChange: this.onChange, + onKeyUp: this.onKeyUp, + placeholder: "Search in file...", + value: this.state.query, + spellCheck: false + }), this.renderSummary(), CloseButton({ + handleClick: this.closeSearch, + buttonClass: "big" + })); + } + }); + + module.exports = EditorSearchBar; + +/***/ }, +/* 407 */ +/***/ function(module, exports, __webpack_require__) { + + var _require = __webpack_require__(408); + + var escapeRegExp = _require.escapeRegExp; + /** + * These functions implement search within the debugger. Since + * search in the debugger is different from other components, + * we can't use search.js CodeMirror addon. This is a slightly + * modified version of that addon. Depends on searchcursor.js. + * @module utils/source-search + */ + + /** + * @memberof utils/source-search + * @static + */ + + function SearchState() { + this.posFrom = this.posTo = this.query = null; + this.overlay = null; + } + + /** + * @memberof utils/source-search + * @static + */ + function getSearchState(cm) { + return cm.state.search || (cm.state.search = new SearchState()); + } + + /** + * @memberof utils/source-search + * @static + */ + function getSearchCursor(cm, query, pos) { + // If the query string is all lowercase, do a case insensitive search. + return cm.getSearchCursor(query, pos, typeof query == "string" && query == query.toLowerCase()); + } + + /** + * Ignore doing outline matches for less than 3 whitespaces + * + * @memberof utils/source-search + * @static + */ + function ignoreWhiteSpace(str) { + return (/^\s{0,2}$/.test(str) ? "(?!\s*.*)" : str + ); + } + + /** + * This returns a mode object used by CoeMirror's addOverlay function + * to parse and style tokens in the file. + * The mode object contains a tokenizer function (token) which takes + * a character stream as input, advances it past a token, and returns + * a style for that token. For more details see + * https://codemirror.net/doc/manual.html#modeapi + * + * @memberof utils/source-search + * @static + */ + function searchOverlay(query) { + query = new RegExp(escapeRegExp(ignoreWhiteSpace(query)), "g"); + return { + token: function (stream) { + query.lastIndex = stream.pos; + var match = query.exec(stream.string); + if (match && match.index == stream.pos) { + stream.pos += match[0].length || 1; + return "selecting"; + } else if (match) { + stream.pos = match.index; + } else { + stream.skipToEnd(); + } + } + }; + } + + /** + * @memberof utils/source-search + * @static + */ + function startSearch(cm, state, query) { + cm.removeOverlay(state.overlay); + state.overlay = searchOverlay(query); + cm.addOverlay(state.overlay, { opaque: true }); + } + + /** + * If there's a saved search, selects the next results. + * Otherwise, creates a new search and selects the first + * result. + * + * @memberof utils/source-search + * @static + */ + function doSearch(ctx, rev, query) { + var cm = ctx.cm; + + var state = getSearchState(cm); + + if (state.query) { + searchNext(ctx, rev); + return; + } + + cm.operation(function () { + if (state.query) { + return; + } + startSearch(cm, state, query); + state.query = query; + state.posFrom = state.posTo = { line: 0, ch: 0 }; + searchNext(ctx, rev); + }); + } + + /** + * Selects the next result of a saved search. + * + * @memberof utils/source-search + * @static + */ + function searchNext(ctx, rev) { + var cm = ctx.cm; + var ed = ctx.ed; + + cm.operation(function () { + var state = getSearchState(cm); + var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo); + + if (!cursor.find(rev)) { + cursor = getSearchCursor(cm, state.query, rev ? { line: cm.lastLine(), ch: null } : { line: cm.firstLine(), ch: 0 }); + if (!cursor.find(rev)) { + return; + } + } + + ed.alignLine(cursor.from().line, "center"); + cm.setSelection(cursor.from(), cursor.to()); + state.posFrom = cursor.from(); + state.posTo = cursor.to(); + }); + } + + /** + * Clears the currently saved search. + * + * @memberof utils/source-search + * @static + */ + function clearSearch(cm) { + var state = getSearchState(cm); + + if (!state.query) { + return; + } + cm.removeOverlay(state.overlay); + state.query = null; + } + + /** + * Starts a new search. + * + * @memberof utils/source-search + * @static + */ + function find(ctx, query) { + clearSearch(ctx.cm); + doSearch(ctx, false, query); + } + + /** + * Finds the next item based on the currently saved search. + * + * @memberof utils/source-search + * @static + */ + function findNext(ctx, query) { + doSearch(ctx, false, query); + } + + /** + * Finds the previous item based on the currently saved search. + * + * @memberof utils/source-search + * @static + */ + function findPrev(ctx, query) { + doSearch(ctx, true, query); + } + + module.exports = { find, findNext, findPrev }; + +/***/ }, +/* 408 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(global, module) {/** + * @license + * lodash <https://lodash.com/> + * Copyright jQuery Foundation and other contributors <https://jquery.org/> + * Released under MIT license <https://lodash.com/license> + * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + ;(function() { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** Used as the semantic version number. */ + var VERSION = '4.16.4'; + + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + + /** Error message constants. */ + var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://github.com/es-shims.', + FUNC_ERROR_TEXT = 'Expected a function'; + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** Used as the maximum memoize cache size. */ + var MAX_MEMOIZE_SIZE = 500; + + /** Used as the internal argument placeholder. */ + var PLACEHOLDER = '__lodash_placeholder__'; + + /** Used to compose bitmasks for function metadata. */ + var BIND_FLAG = 1, + BIND_KEY_FLAG = 2, + CURRY_BOUND_FLAG = 4, + CURRY_FLAG = 8, + CURRY_RIGHT_FLAG = 16, + PARTIAL_FLAG = 32, + PARTIAL_RIGHT_FLAG = 64, + ARY_FLAG = 128, + REARG_FLAG = 256, + FLIP_FLAG = 512; + + /** Used to compose bitmasks for comparison styles. */ + var UNORDERED_COMPARE_FLAG = 1, + PARTIAL_COMPARE_FLAG = 2; + + /** Used as default options for `_.truncate`. */ + var DEFAULT_TRUNC_LENGTH = 30, + DEFAULT_TRUNC_OMISSION = '...'; + + /** Used to detect hot functions by number of calls within a span of milliseconds. */ + var HOT_COUNT = 500, + HOT_SPAN = 16; + + /** Used to indicate the type of lazy iteratees. */ + var LAZY_FILTER_FLAG = 1, + LAZY_MAP_FLAG = 2, + LAZY_WHILE_FLAG = 3; + + /** Used as references for various `Number` constants. */ + var INFINITY = 1 / 0, + MAX_SAFE_INTEGER = 9007199254740991, + MAX_INTEGER = 1.7976931348623157e+308, + NAN = 0 / 0; + + /** Used as references for the maximum length and index of an array. */ + var MAX_ARRAY_LENGTH = 4294967295, + MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, + HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + + /** Used to associate wrap methods with their bit flags. */ + var wrapFlags = [ + ['ary', ARY_FLAG], + ['bind', BIND_FLAG], + ['bindKey', BIND_KEY_FLAG], + ['curry', CURRY_FLAG], + ['curryRight', CURRY_RIGHT_FLAG], + ['flip', FLIP_FLAG], + ['partial', PARTIAL_FLAG], + ['partialRight', PARTIAL_RIGHT_FLAG], + ['rearg', REARG_FLAG] + ]; + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + proxyTag = '[object Proxy]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]', + weakMapTag = '[object WeakMap]', + weakSetTag = '[object WeakSet]'; + + var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + + /** Used to match empty string literals in compiled template source. */ + var reEmptyStringLeading = /\b__p \+= '';/g, + reEmptyStringMiddle = /\b(__p \+=) '' \+/g, + reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + + /** Used to match HTML entities and HTML characters. */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, + reUnescapedHtml = /[&<>"']/g, + reHasEscapedHtml = RegExp(reEscapedHtml.source), + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** Used to match template delimiters. */ + var reEscape = /<%-([\s\S]+?)%>/g, + reEvaluate = /<%([\s\S]+?)%>/g, + reInterpolate = /<%=([\s\S]+?)%>/g; + + /** Used to match property names within property paths. */ + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/, + reLeadingDot = /^\./, + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + + /** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ + var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, + reHasRegExpChar = RegExp(reRegExpChar.source); + + /** Used to match leading and trailing whitespace. */ + var reTrim = /^\s+|\s+$/g, + reTrimStart = /^\s+/, + reTrimEnd = /\s+$/; + + /** Used to match wrap detail comments. */ + var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, + reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, + reSplitDetails = /,? & /; + + /** Used to match words composed of alphanumeric characters. */ + var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + + /** Used to match backslashes in property paths. */ + var reEscapeChar = /\\(\\)?/g; + + /** + * Used to match + * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components). + */ + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + + /** Used to match `RegExp` flags from their coerced string values. */ + var reFlags = /\w*$/; + + /** Used to detect bad signed hexadecimal string values. */ + var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + + /** Used to detect binary string values. */ + var reIsBinary = /^0b[01]+$/i; + + /** Used to detect host constructors (Safari). */ + var reIsHostCtor = /^\[object .+?Constructor\]$/; + + /** Used to detect octal string values. */ + var reIsOctal = /^0o[0-7]+$/i; + + /** Used to detect unsigned integer values. */ + var reIsUint = /^(?:0|[1-9]\d*)$/; + + /** Used to match Latin Unicode letters (excluding mathematical operators). */ + var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; + + /** Used to ensure capturing order of template delimiters. */ + var reNoMatch = /($^)/; + + /** Used to match unescaped characters in compiled string literals. */ + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + + /** Used to compose unicode character classes. */ + var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboSymbolsRange = '\\u20d0-\\u20f0', + rsDingbatRange = '\\u2700-\\u27bf', + rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', + rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', + rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', + rsPunctuationRange = '\\u2000-\\u206f', + rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', + rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', + rsVarRange = '\\ufe0e\\ufe0f', + rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; + + /** Used to compose unicode capture groups. */ + var rsApos = "['\u2019]", + rsAstral = '[' + rsAstralRange + ']', + rsBreak = '[' + rsBreakRange + ']', + rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', + rsDigits = '\\d+', + rsDingbat = '[' + rsDingbatRange + ']', + rsLower = '[' + rsLowerRange + ']', + rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsUpper = '[' + rsUpperRange + ']', + rsZWJ = '\\u200d'; + + /** Used to compose unicode regexes. */ + var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')', + rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')', + rsOptLowerContr = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', + rsOptUpperContr = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', + reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + + /** Used to match apostrophes. */ + var reApos = RegExp(rsApos, 'g'); + + /** + * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and + * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). + */ + var reComboMark = RegExp(rsCombo, 'g'); + + /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ + var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + + /** Used to match complex or compound words. */ + var reUnicodeWord = RegExp([ + rsUpper + '?' + rsLower + '+' + rsOptLowerContr + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', + rsUpperMisc + '+' + rsOptUpperContr + '(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')', + rsUpper + '?' + rsLowerMisc + '+' + rsOptLowerContr, + rsUpper + '+' + rsOptUpperContr, + rsDigits, + rsEmoji + ].join('|'), 'g'); + + /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ + var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); + + /** Used to detect strings that need a more robust regexp to match words. */ + var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + + /** Used to assign default `context` object properties. */ + var contextProps = [ + 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', + 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', + 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' + ]; + + /** Used to make template sourceURLs easier to identify. */ + var templateCounter = -1; + + /** Used to identify `toStringTag` values of typed arrays. */ + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = + typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = + typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = + typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = + typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = + typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = + typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = + typedArrayTags[errorTag] = typedArrayTags[funcTag] = + typedArrayTags[mapTag] = typedArrayTags[numberTag] = + typedArrayTags[objectTag] = typedArrayTags[regexpTag] = + typedArrayTags[setTag] = typedArrayTags[stringTag] = + typedArrayTags[weakMapTag] = false; + + /** Used to identify `toStringTag` values supported by `_.clone`. */ + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = + cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = + cloneableTags[boolTag] = cloneableTags[dateTag] = + cloneableTags[float32Tag] = cloneableTags[float64Tag] = + cloneableTags[int8Tag] = cloneableTags[int16Tag] = + cloneableTags[int32Tag] = cloneableTags[mapTag] = + cloneableTags[numberTag] = cloneableTags[objectTag] = + cloneableTags[regexpTag] = cloneableTags[setTag] = + cloneableTags[stringTag] = cloneableTags[symbolTag] = + cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = + cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = + cloneableTags[weakMapTag] = false; + + /** Used to map Latin Unicode letters to basic Latin letters. */ + var deburredLetters = { + // Latin-1 Supplement block. + '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', + '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', + '\xc7': 'C', '\xe7': 'c', + '\xd0': 'D', '\xf0': 'd', + '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', + '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', + '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', + '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', + '\xd1': 'N', '\xf1': 'n', + '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', + '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', + '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', + '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', + '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', + '\xc6': 'Ae', '\xe6': 'ae', + '\xde': 'Th', '\xfe': 'th', + '\xdf': 'ss', + // Latin Extended-A block. + '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', + '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', + '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', + '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', + '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', + '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', + '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', + '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', + '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', + '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', + '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', + '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', + '\u0134': 'J', '\u0135': 'j', + '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', + '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', + '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', + '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', + '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', + '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', + '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', + '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', + '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', + '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', + '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', + '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', + '\u0163': 't', '\u0165': 't', '\u0167': 't', + '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', + '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', + '\u0174': 'W', '\u0175': 'w', + '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', + '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', + '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', + '\u0132': 'IJ', '\u0133': 'ij', + '\u0152': 'Oe', '\u0153': 'oe', + '\u0149': "'n", '\u017f': 's' + }; + + /** Used to map characters to HTML entities. */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + /** Used to map HTML entities to characters. */ + var htmlUnescapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'" + }; + + /** Used to escape characters for inclusion in compiled string literals. */ + var stringEscapes = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + /** Built-in method references without a dependency on `root`. */ + var freeParseFloat = parseFloat, + freeParseInt = parseInt; + + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; + + /** Detect free variable `process` from Node.js. */ + var freeProcess = moduleExports && freeGlobal.process; + + /** Used to access faster Node.js helpers. */ + var nodeUtil = (function() { + try { + return freeProcess && freeProcess.binding('util'); + } catch (e) {} + }()); + + /* Node.js helper references. */ + var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, + nodeIsDate = nodeUtil && nodeUtil.isDate, + nodeIsMap = nodeUtil && nodeUtil.isMap, + nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, + nodeIsSet = nodeUtil && nodeUtil.isSet, + nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + + /*--------------------------------------------------------------------------*/ + + /** + * Adds the key-value `pair` to `map`. + * + * @private + * @param {Object} map The map to modify. + * @param {Array} pair The key-value pair to add. + * @returns {Object} Returns `map`. + */ + function addMapEntry(map, pair) { + // Don't return `map.set` because it's not chainable in IE 11. + map.set(pair[0], pair[1]); + return map; + } + + /** + * Adds `value` to `set`. + * + * @private + * @param {Object} set The set to modify. + * @param {*} value The value to add. + * @returns {Object} Returns `set`. + */ + function addSetEntry(set, value) { + // Don't return `set.add` because it's not chainable in IE 11. + set.add(value); + return set; + } + + /** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ + function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); + } + + /** + * A specialized version of `baseAggregator` for arrays. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function arrayAggregator(array, setter, iteratee, accumulator) { + var index = -1, + length = array ? array.length : 0; + + while (++index < length) { + var value = array[index]; + setter(accumulator, value, iteratee(value), array); + } + return accumulator; + } + + /** + * A specialized version of `_.forEach` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEach(array, iteratee) { + var index = -1, + length = array ? array.length : 0; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.forEachRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEachRight(array, iteratee) { + var length = array ? array.length : 0; + + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.every` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + */ + function arrayEvery(array, predicate) { + var index = -1, + length = array ? array.length : 0; + + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + + /** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function arrayFilter(array, predicate) { + var index = -1, + length = array ? array.length : 0, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * A specialized version of `_.includes` for arrays without support for + * specifying an index to search from. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludes(array, value) { + var length = array ? array.length : 0; + return !!length && baseIndexOf(array, value, 0) > -1; + } + + /** + * This function is like `arrayIncludes` except that it accepts a comparator. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @param {Function} comparator The comparator invoked per element. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludesWith(array, value, comparator) { + var index = -1, + length = array ? array.length : 0; + + while (++index < length) { + if (comparator(value, array[index])) { + return true; + } + } + return false; + } + + /** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function arrayMap(array, iteratee) { + var index = -1, + length = array ? array.length : 0, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + + /** + * A specialized version of `_.reduce` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the first element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduce(array, iteratee, accumulator, initAccum) { + var index = -1, + length = array ? array.length : 0; + + if (initAccum && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + + /** + * A specialized version of `_.reduceRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the last element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduceRight(array, iteratee, accumulator, initAccum) { + var length = array ? array.length : 0; + if (initAccum && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + + /** + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function arraySome(array, predicate) { + var index = -1, + length = array ? array.length : 0; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + + /** + * Gets the size of an ASCII `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + var asciiSize = baseProperty('length'); + + /** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function asciiToArray(string) { + return string.split(''); + } + + /** + * Splits an ASCII `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function asciiWords(string) { + return string.match(reAsciiWord) || []; + } + + /** + * The base implementation of methods like `_.findKey` and `_.findLastKey`, + * without support for iteratee shorthands, which iterates over `collection` + * using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the found element or its key, else `undefined`. + */ + function baseFindKey(collection, predicate, eachFunc) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = key; + return false; + } + }); + return result; + } + + /** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOf(array, value, fromIndex) { + return value === value + ? strictIndexOf(array, value, fromIndex) + : baseFindIndex(array, baseIsNaN, fromIndex); + } + + /** + * This function is like `baseIndexOf` except that it accepts a comparator. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @param {Function} comparator The comparator invoked per element. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOfWith(array, value, fromIndex, comparator) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (comparator(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ + function baseIsNaN(value) { + return value !== value; + } + + /** + * The base implementation of `_.mean` and `_.meanBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the mean. + */ + function baseMean(array, iteratee) { + var length = array ? array.length : 0; + return length ? (baseSum(array, iteratee) / length) : NAN; + } + + /** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.propertyOf` without support for deep paths. + * + * @private + * @param {Object} object The object to query. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyOf(object) { + return function(key) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.reduce` and `_.reduceRight`, without support + * for iteratee shorthands, which iterates over `collection` using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} accumulator The initial value. + * @param {boolean} initAccum Specify using the first or last element of + * `collection` as the initial value. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the accumulated value. + */ + function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initAccum + ? (initAccum = false, value) + : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.sortBy` which uses `comparer` to define the + * sort order of `array` and replaces criteria objects with their corresponding + * values. + * + * @private + * @param {Array} array The array to sort. + * @param {Function} comparer The function to define sort order. + * @returns {Array} Returns `array`. + */ + function baseSortBy(array, comparer) { + var length = array.length; + + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + + /** + * The base implementation of `_.sum` and `_.sumBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the sum. + */ + function baseSum(array, iteratee) { + var result, + index = -1, + length = array.length; + + while (++index < length) { + var current = iteratee(array[index]); + if (current !== undefined) { + result = result === undefined ? current : (result + current); + } + } + return result; + } + + /** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ + function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; + } + + /** + * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array + * of key-value pairs for `object` corresponding to the property names of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the key-value pairs. + */ + function baseToPairs(object, props) { + return arrayMap(props, function(key) { + return [key, object[key]]; + }); + } + + /** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ + function baseUnary(func) { + return function(value) { + return func(value); + }; + } + + /** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ + function baseValues(object, props) { + return arrayMap(props, function(key) { + return object[key]; + }); + } + + /** + * Checks if a `cache` value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function cacheHas(cache, key) { + return cache.has(key); + } + + /** + * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the first unmatched string symbol. + */ + function charsStartIndex(strSymbols, chrSymbols) { + var index = -1, + length = strSymbols.length; + + while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the last unmatched string symbol. + */ + function charsEndIndex(strSymbols, chrSymbols) { + var index = strSymbols.length; + + while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Gets the number of `placeholder` occurrences in `array`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} placeholder The placeholder to search for. + * @returns {number} Returns the placeholder count. + */ + function countHolders(array, placeholder) { + var length = array.length, + result = 0; + + while (length--) { + if (array[length] === placeholder) { + ++result; + } + } + return result; + } + + /** + * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A + * letters to basic Latin letters. + * + * @private + * @param {string} letter The matched letter to deburr. + * @returns {string} Returns the deburred letter. + */ + var deburrLetter = basePropertyOf(deburredLetters); + + /** + * Used by `_.escape` to convert characters to HTML entities. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + var escapeHtmlChar = basePropertyOf(htmlEscapes); + + /** + * Used by `_.template` to escape characters for inclusion in compiled string literals. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + function escapeStringChar(chr) { + return '\\' + stringEscapes[chr]; + } + + /** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function getValue(object, key) { + return object == null ? undefined : object[key]; + } + + /** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ + function hasUnicode(string) { + return reHasUnicode.test(string); + } + + /** + * Checks if `string` contains a word composed of Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a word is found, else `false`. + */ + function hasUnicodeWord(string) { + return reHasUnicodeWord.test(string); + } + + /** + * Converts `iterator` to an array. + * + * @private + * @param {Object} iterator The iterator to convert. + * @returns {Array} Returns the converted array. + */ + function iteratorToArray(iterator) { + var data, + result = []; + + while (!(data = iterator.next()).done) { + result.push(data.value); + } + return result; + } + + /** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ + function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; + } + + /** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } + + /** + * Replaces all `placeholder` elements in `array` with an internal placeholder + * and returns an array of their indexes. + * + * @private + * @param {Array} array The array to modify. + * @param {*} placeholder The placeholder to replace. + * @returns {Array} Returns the new array of placeholder indexes. + */ + function replaceHolders(array, placeholder) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value === placeholder || value === PLACEHOLDER) { + array[index] = PLACEHOLDER; + result[resIndex++] = index; + } + } + return result; + } + + /** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ + function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; + } + + /** + * Converts `set` to its value-value pairs. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the value-value pairs. + */ + function setToPairs(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = [value, value]; + }); + return result; + } + + /** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * A specialized version of `_.lastIndexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictLastIndexOf(array, value, fromIndex) { + var index = fromIndex + 1; + while (index--) { + if (array[index] === value) { + return index; + } + } + return index; + } + + /** + * Gets the number of symbols in `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the string size. + */ + function stringSize(string) { + return hasUnicode(string) + ? unicodeSize(string) + : asciiSize(string); + } + + /** + * Converts `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function stringToArray(string) { + return hasUnicode(string) + ? unicodeToArray(string) + : asciiToArray(string); + } + + /** + * Used by `_.unescape` to convert HTML entities to characters. + * + * @private + * @param {string} chr The matched character to unescape. + * @returns {string} Returns the unescaped character. + */ + var unescapeHtmlChar = basePropertyOf(htmlUnescapes); + + /** + * Gets the size of a Unicode `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + function unicodeSize(string) { + var result = reUnicode.lastIndex = 0; + while (reUnicode.test(string)) { + ++result; + } + return result; + } + + /** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function unicodeToArray(string) { + return string.match(reUnicode) || []; + } + + /** + * Splits a Unicode `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function unicodeWords(string) { + return string.match(reUnicodeWord) || []; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Create a new pristine `lodash` function using the `context` object. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Util + * @param {Object} [context=root] The context object. + * @returns {Function} Returns a new `lodash` function. + * @example + * + * _.mixin({ 'foo': _.constant('foo') }); + * + * var lodash = _.runInContext(); + * lodash.mixin({ 'bar': lodash.constant('bar') }); + * + * _.isFunction(_.foo); + * // => true + * _.isFunction(_.bar); + * // => false + * + * lodash.isFunction(lodash.foo); + * // => false + * lodash.isFunction(lodash.bar); + * // => true + * + * // Create a suped-up `defer` in Node.js. + * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; + */ + var runInContext = (function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + + /** Built-in constructor references. */ + var Array = context.Array, + Date = context.Date, + Error = context.Error, + Function = context.Function, + Math = context.Math, + Object = context.Object, + RegExp = context.RegExp, + String = context.String, + TypeError = context.TypeError; + + /** Used for built-in method references. */ + var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; + + /** Used to detect overreaching core-js shims. */ + var coreJsData = context['__core-js_shared__']; + + /** Used to detect methods masquerading as native. */ + var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; + }()); + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to generate unique IDs. */ + var idCounter = 0; + + /** Used to infer the `Object` constructor. */ + var objectCtorString = funcToString.call(Object); + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var objectToString = objectProto.toString; + + /** Used to restore the original `_` reference in `_.noConflict`. */ + var oldDash = root._; + + /** Used to detect if a method is native. */ + var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + ); + + /** Built-in value references. */ + var Buffer = moduleExports ? context.Buffer : undefined, + Symbol = context.Symbol, + Uint8Array = context.Uint8Array, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, + getPrototype = overArg(Object.getPrototypeOf, Object), + iteratorSymbol = Symbol ? Symbol.iterator : undefined, + objectCreate = Object.create, + propertyIsEnumerable = objectProto.propertyIsEnumerable, + splice = arrayProto.splice, + spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined; + + var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} + }()); + + /** Mocked built-ins. */ + var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, + ctxNow = Date && Date.now !== root.Date.now && Date.now, + ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeCeil = Math.ceil, + nativeFloor = Math.floor, + nativeGetSymbols = Object.getOwnPropertySymbols, + nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, + nativeIsFinite = context.isFinite, + nativeJoin = arrayProto.join, + nativeKeys = overArg(Object.keys, Object), + nativeMax = Math.max, + nativeMin = Math.min, + nativeNow = Date.now, + nativeParseInt = context.parseInt, + nativeRandom = Math.random, + nativeReverse = arrayProto.reverse; + + /* Built-in method references that are verified to be native. */ + var DataView = getNative(context, 'DataView'), + Map = getNative(context, 'Map'), + Promise = getNative(context, 'Promise'), + Set = getNative(context, 'Set'), + WeakMap = getNative(context, 'WeakMap'), + nativeCreate = getNative(Object, 'create'); + + /** Used to store function metadata. */ + var metaMap = WeakMap && new WeakMap; + + /** Used to lookup unminified function names. */ + var realNames = {}; + + /** Used to detect maps, sets, and weakmaps. */ + var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); + + /** Used to convert symbols to primitives and strings. */ + var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object which wraps `value` to enable implicit method + * chain sequences. Methods that operate on and return arrays, collections, + * and functions can be chained together. Methods that retrieve a single value + * or may return a primitive value will automatically end the chain sequence + * and return the unwrapped value. Otherwise, the value must be unwrapped + * with `_#value`. + * + * Explicit chain sequences, which must be unwrapped with `_#value`, may be + * enabled using `_.chain`. + * + * The execution of chained methods is lazy, that is, it's deferred until + * `_#value` is implicitly or explicitly called. + * + * Lazy evaluation allows several methods to support shortcut fusion. + * Shortcut fusion is an optimization to merge iteratee calls; this avoids + * the creation of intermediate arrays and can greatly reduce the number of + * iteratee executions. Sections of a chain sequence qualify for shortcut + * fusion if the section is applied to an array of at least `200` elements + * and any iteratees accept only one argument. The heuristic for whether a + * section qualifies for shortcut fusion is subject to change. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers have `Array` and `String` methods. + * + * The wrapper `Array` methods are: + * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` + * + * The wrapper `String` methods are: + * `replace` and `split` + * + * The wrapper methods that support shortcut fusion are: + * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, + * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, + * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` + * + * The chainable wrapper methods are: + * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, + * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, + * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, + * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, + * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, + * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, + * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, + * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, + * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, + * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, + * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, + * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, + * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, + * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, + * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, + * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, + * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, + * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, + * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, + * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, + * `zipObject`, `zipObjectDeep`, and `zipWith` + * + * The wrapper methods that are **not** chainable by default are: + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, + * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, + * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, + * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, + * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, + * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, + * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, + * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, + * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, + * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, + * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, + * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, + * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, + * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, + * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, + * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, + * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, + * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, + * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, + * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, + * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, + * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, + * `upperFirst`, `value`, and `words` + * + * @name _ + * @constructor + * @category Seq + * @param {*} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2, 3]); + * + * // Returns an unwrapped value. + * wrapped.reduce(_.add); + * // => 6 + * + * // Returns a wrapped value. + * var squares = wrapped.map(square); + * + * _.isArray(squares); + * // => false + * + * _.isArray(squares.value()); + * // => true + */ + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, '__wrapped__')) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + + /** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; + }()); + + /** + * The function whose prototype chain sequence wrappers inherit from. + * + * @private + */ + function baseLodash() { + // No operation performed. + } + + /** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable explicit method chain sequences. + */ + function LodashWrapper(value, chainAll) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__chain__ = !!chainAll; + this.__index__ = 0; + this.__values__ = undefined; + } + + /** + * By default, the template delimiters used by lodash are like those in + * embedded Ruby (ERB). Change the following template settings to use + * alternative delimiters. + * + * @static + * @memberOf _ + * @type {Object} + */ + lodash.templateSettings = { + + /** + * Used to detect `data` property values to be HTML-escaped. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'escape': reEscape, + + /** + * Used to detect code to be evaluated. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'evaluate': reEvaluate, + + /** + * Used to detect `data` property values to inject. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'interpolate': reInterpolate, + + /** + * Used to reference the data object in the template text. + * + * @memberOf _.templateSettings + * @type {string} + */ + 'variable': '', + + /** + * Used to import variables into the compiled template. + * + * @memberOf _.templateSettings + * @type {Object} + */ + 'imports': { + + /** + * A reference to the `lodash` function. + * + * @memberOf _.templateSettings.imports + * @type {Function} + */ + '_': lodash + } + }; + + // Ensure wrappers are instances of `baseLodash`. + lodash.prototype = baseLodash.prototype; + lodash.prototype.constructor = lodash; + + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. + * + * @private + * @constructor + * @param {*} value The value to wrap. + */ + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = MAX_ARRAY_LENGTH; + this.__views__ = []; + } + + /** + * Creates a clone of the lazy wrapper object. + * + * @private + * @name clone + * @memberOf LazyWrapper + * @returns {Object} Returns the cloned `LazyWrapper` object. + */ + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = copyArray(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = copyArray(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = copyArray(this.__views__); + return result; + } + + /** + * Reverses the direction of lazy iteration. + * + * @private + * @name reverse + * @memberOf LazyWrapper + * @returns {Object} Returns the new reversed `LazyWrapper` object. + */ + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + + /** + * Extracts the unwrapped value from its lazy wrapper. + * + * @private + * @name value + * @memberOf LazyWrapper + * @returns {*} Returns the unwrapped value. + */ + function lazyValue() { + var array = this.__wrapped__.value(), + dir = this.__dir__, + isArr = isArray(array), + isRight = dir < 0, + arrLength = isArr ? array.length : 0, + view = getView(0, arrLength, this.__views__), + start = view.start, + end = view.end, + length = end - start, + index = isRight ? end : (start - 1), + iteratees = this.__iteratees__, + iterLength = iteratees.length, + resIndex = 0, + takeCount = nativeMin(length, this.__takeCount__); + + if (!isArr || arrLength < LARGE_ARRAY_SIZE || + (arrLength == length && takeCount == length)) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + + outer: + while (length-- && resIndex < takeCount) { + index += dir; + + var iterIndex = -1, + value = array[index]; + + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], + iteratee = data.iteratee, + type = data.type, + computed = iteratee(value); + + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + + // Ensure `LazyWrapper` is an instance of `baseLodash`. + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Hash(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; + } + + /** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; + } + + /** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key); + } + + /** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ + function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; + } + + // Add methods to `Hash`. + Hash.prototype.clear = hashClear; + Hash.prototype['delete'] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function ListCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ + function listCacheClear() { + this.__data__ = []; + this.size = 0; + } + + /** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; + } + + /** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; + } + + /** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } + + /** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ + function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; + } + + // Add methods to `ListCache`. + ListCache.prototype.clear = listCacheClear; + ListCache.prototype['delete'] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function MapCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ + function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; + } + + /** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function mapCacheGet(key) { + return getMapData(this, key).get(key); + } + + /** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapCacheHas(key) { + return getMapData(this, key).has(key); + } + + /** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ + function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; + } + + // Add methods to `MapCache`. + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype['delete'] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ + function SetCache(values) { + var index = -1, + length = values ? values.length : 0; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } + } + + /** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ + function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; + } + + /** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ + function setCacheHas(value) { + return this.__data__.has(value); + } + + // Add methods to `SetCache`. + SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; + SetCache.prototype.has = setCacheHas; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; + } + + /** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ + function stackClear() { + this.__data__ = new ListCache; + this.size = 0; + } + + /** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; + } + + /** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function stackGet(key) { + return this.__data__.get(key); + } + + /** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function stackHas(key) { + return this.__data__.has(key); + } + + /** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ + function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; + } + + // Add methods to `Stack`. + Stack.prototype.clear = stackClear; + Stack.prototype['delete'] = stackDelete; + Stack.prototype.get = stackGet; + Stack.prototype.has = stackHas; + Stack.prototype.set = stackSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ + function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; + } + + /** + * A specialized version of `_.sample` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @returns {*} Returns the random element. + */ + function arraySample(array) { + var length = array.length; + return length ? array[baseRandom(0, length - 1)] : undefined; + } + + /** + * A specialized version of `_.sampleSize` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function arraySampleSize(array, n) { + return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length)); + } + + /** + * A specialized version of `_.shuffle` for arrays. + * + * @private + * @param {Array} array The array to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function arrayShuffle(array) { + return shuffleSelf(copyArray(array)); + } + + /** + * Used by `_.defaults` to customize its `_.assignIn` use. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to assign. + * @param {Object} object The parent object of `objValue`. + * @returns {*} Returns the value to assign. + */ + function assignInDefaults(objValue, srcValue, key, object) { + if (objValue === undefined || + (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { + return srcValue; + } + return objValue; + } + + /** + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignMergeValue(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; + } + + /** + * Aggregates elements of `collection` on `accumulator` with keys transformed + * by `iteratee` and values set by `setter`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function baseAggregator(collection, setter, iteratee, accumulator) { + baseEach(collection, function(value, key, collection) { + setter(accumulator, value, iteratee(value), collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.assign` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssign(object, source) { + return object && copyObject(source, keys(source), object); + } + + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } + } + + /** + * The base implementation of `_.at` without support for individual paths. + * + * @private + * @param {Object} object The object to iterate over. + * @param {string[]} paths The property paths of elements to pick. + * @returns {Array} Returns the picked elements. + */ + function baseAt(object, paths) { + var index = -1, + isNil = object == null, + length = paths.length, + result = Array(length); + + while (++index < length) { + result[index] = isNil ? undefined : get(object, paths[index]); + } + return result; + } + + /** + * The base implementation of `_.clamp` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + */ + function baseClamp(number, lower, upper) { + if (number === number) { + if (upper !== undefined) { + number = number <= upper ? number : upper; + } + if (lower !== undefined) { + number = number >= lower ? number : lower; + } + } + return number; + } + + /** + * The base implementation of `_.clone` and `_.cloneDeep` which tracks + * traversed objects. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @param {boolean} [isFull] Specify a clone including symbols. + * @param {Function} [customizer] The function to customize cloning. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The parent object of `value`. + * @param {Object} [stack] Tracks traversed objects and their clone counterparts. + * @returns {*} Returns the cloned value. + */ + function baseClone(value, isDeep, isFull, customizer, key, object, stack) { + var result; + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return copyArray(value, result); + } + } else { + var tag = getTag(value), + isFunc = tag == funcTag || tag == genTag; + + if (isBuffer(value)) { + return cloneBuffer(value, isDeep); + } + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return copySymbols(value, baseAssign(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = initCloneByTag(value, tag, baseClone, isDeep); + } + } + // Check for circular references and return its corresponding clone. + stack || (stack = new Stack); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + + var props = isArr ? undefined : (isFull ? getAllKeys : keys)(value); + arrayEach(props || value, function(subValue, key) { + if (props) { + key = subValue; + subValue = value[key]; + } + // Recursively populate clone (susceptible to call stack limits). + assignValue(result, key, baseClone(subValue, isDeep, isFull, customizer, key, value, stack)); + }); + return result; + } + + /** + * The base implementation of `_.conforms` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property predicates to conform to. + * @returns {Function} Returns the new spec function. + */ + function baseConforms(source) { + var props = keys(source); + return function(object) { + return baseConformsTo(object, source, props); + }; + } + + /** + * The base implementation of `_.conformsTo` which accepts `props` to check. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + */ + function baseConformsTo(object, source, props) { + var length = props.length; + if (object == null) { + return !length; + } + object = Object(object); + while (length--) { + var key = props[length], + predicate = source[key], + value = object[key]; + + if ((value === undefined && !(key in object)) || !predicate(value)) { + return false; + } + } + return true; + } + + /** + * The base implementation of `_.delay` and `_.defer` which accepts `args` + * to provide to `func`. + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {Array} args The arguments to provide to `func`. + * @returns {number|Object} Returns the timer id or timeout object. + */ + function baseDelay(func, wait, args) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * The base implementation of methods like `_.difference` without support + * for excluding multiple arrays or iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Array} values The values to exclude. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + */ + function baseDifference(array, values, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + isCommon = true, + length = array.length, + result = [], + valuesLength = values.length; + + if (!length) { + return result; + } + if (iteratee) { + values = arrayMap(values, baseUnary(iteratee)); + } + if (comparator) { + includes = arrayIncludesWith; + isCommon = false; + } + else if (values.length >= LARGE_ARRAY_SIZE) { + includes = cacheHas; + isCommon = false; + values = new SetCache(values); + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === computed) { + continue outer; + } + } + result.push(value); + } + else if (!includes(values, computed, comparator)) { + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.forEach` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEach = createBaseEach(baseForOwn); + + /** + * The base implementation of `_.forEachRight` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEachRight = createBaseEach(baseForOwnRight, true); + + /** + * The base implementation of `_.every` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` + */ + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + + /** + * The base implementation of methods like `_.max` and `_.min` which accepts a + * `comparator` to determine the extremum value. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The iteratee invoked per iteration. + * @param {Function} comparator The comparator used to compare values. + * @returns {*} Returns the extremum value. + */ + function baseExtremum(array, iteratee, comparator) { + var index = -1, + length = array.length; + + while (++index < length) { + var value = array[index], + current = iteratee(value); + + if (current != null && (computed === undefined + ? (current === current && !isSymbol(current)) + : comparator(current, computed) + )) { + var computed = current, + result = value; + } + } + return result; + } + + /** + * The base implementation of `_.fill` without an iteratee call guard. + * + * @private + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ + function baseFill(array, value, start, end) { + var length = array.length; + + start = toInteger(start); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (end === undefined || end > length) ? length : toInteger(end); + if (end < 0) { + end += length; + } + end = start > end ? 0 : toLength(end); + while (start < end) { + array[start++] = value; + } + return array; + } + + /** + * The base implementation of `_.filter` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + + /** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {number} depth The maximum recursion depth. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ + function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, + length = array.length; + + predicate || (predicate = isFlattenable); + result || (result = []); + + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, depth - 1, predicate, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + + /** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseFor = createBaseFor(); + + /** + * This function is like `baseFor` except that it iterates over properties + * in the opposite order. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseForRight = createBaseFor(true); + + /** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwn(object, iteratee) { + return object && baseFor(object, iteratee, keys); + } + + /** + * The base implementation of `_.forOwnRight` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwnRight(object, iteratee) { + return object && baseForRight(object, iteratee, keys); + } + + /** + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from `props`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the function names. + */ + function baseFunctions(object, props) { + return arrayFilter(props, function(key) { + return isFunction(object[key]); + }); + } + + /** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ + function baseGet(object, path) { + path = isKey(path, object) ? [path] : castPath(path); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; + } + + /** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ + function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); + } + + /** + * The base implementation of `getTag`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + return objectToString.call(value); + } + + /** + * The base implementation of `_.gt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + */ + function baseGt(value, other) { + return value > other; + } + + /** + * The base implementation of `_.has` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHas(object, key) { + return object != null && hasOwnProperty.call(object, key); + } + + /** + * The base implementation of `_.hasIn` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHasIn(object, key) { + return object != null && key in Object(object); + } + + /** + * The base implementation of `_.inRange` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to check. + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + */ + function baseInRange(number, start, end) { + return number >= nativeMin(start, end) && number < nativeMax(start, end); + } + + /** + * The base implementation of methods like `_.intersection`, without support + * for iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of shared values. + */ + function baseIntersection(arrays, iteratee, comparator) { + var includes = comparator ? arrayIncludesWith : arrayIncludes, + length = arrays[0].length, + othLength = arrays.length, + othIndex = othLength, + caches = Array(othLength), + maxLength = Infinity, + result = []; + + while (othIndex--) { + var array = arrays[othIndex]; + if (othIndex && iteratee) { + array = arrayMap(array, baseUnary(iteratee)); + } + maxLength = nativeMin(array.length, maxLength); + caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) + ? new SetCache(othIndex && array) + : undefined; + } + array = arrays[0]; + + var index = -1, + seen = caches[0]; + + outer: + while (++index < length && result.length < maxLength) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (!(seen + ? cacheHas(seen, computed) + : includes(result, computed, comparator) + )) { + othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if (!(cache + ? cacheHas(cache, computed) + : includes(arrays[othIndex], computed, comparator)) + ) { + continue outer; + } + } + if (seen) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.invert` and `_.invertBy` which inverts + * `object` with values transformed by `iteratee` and set by `setter`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform values. + * @param {Object} accumulator The initial inverted object. + * @returns {Function} Returns `accumulator`. + */ + function baseInverter(object, setter, iteratee, accumulator) { + baseForOwn(object, function(value, key, object) { + setter(accumulator, iteratee(value), key, object); + }); + return accumulator; + } + + /** + * The base implementation of `_.invoke` without support for individual + * method arguments. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {Array} args The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + */ + function baseInvoke(object, path, args) { + if (!isKey(path, object)) { + path = castPath(path); + object = parent(object, path); + path = last(path); + } + var func = object == null ? object : object[toKey(path)]; + return func == null ? undefined : apply(func, object, args); + } + + /** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ + function baseIsArguments(value) { + return isObjectLike(value) && objectToString.call(value) == argsTag; + } + + /** + * The base implementation of `_.isArrayBuffer` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + */ + function baseIsArrayBuffer(value) { + return isObjectLike(value) && objectToString.call(value) == arrayBufferTag; + } + + /** + * The base implementation of `_.isDate` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + */ + function baseIsDate(value) { + return isObjectLike(value) && objectToString.call(value) == dateTag; + } + + /** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparisons. + * @param {boolean} [bitmask] The bitmask of comparison flags. + * The bitmask may be composed of the following flags: + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ + function baseIsEqual(value, other, customizer, bitmask, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack); + } + + /** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} [customizer] The function to customize comparisons. + * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` + * for more details. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = arrayTag, + othTag = arrayTag; + + if (!objIsArr) { + objTag = getTag(object); + objTag = objTag == argsTag ? objectTag : objTag; + } + if (!othIsArr) { + othTag = getTag(other); + othTag = othTag == argsTag ? objectTag : othTag; + } + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, equalFunc, customizer, bitmask, stack) + : equalByTag(object, other, objTag, equalFunc, customizer, bitmask, stack); + } + if (!(bitmask & PARTIAL_COMPARE_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, customizer, bitmask, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack); + return equalObjects(object, other, equalFunc, customizer, bitmask, stack); + } + + /** + * The base implementation of `_.isMap` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + */ + function baseIsMap(value) { + return isObjectLike(value) && getTag(value) == mapTag; + } + + /** + * The base implementation of `_.isMatch` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Array} matchData The property names, values, and compare flags to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + */ + function baseIsMatch(object, source, matchData, customizer) { + var index = matchData.length, + length = index, + noCustomizer = !customizer; + + if (object == null) { + return !length; + } + object = Object(object); + while (index--) { + var data = matchData[index]; + if ((noCustomizer && data[2]) + ? data[1] !== object[data[0]] + : !(data[0] in object) + ) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], + objValue = object[key], + srcValue = data[1]; + + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var stack = new Stack; + if (customizer) { + var result = customizer(objValue, srcValue, key, object, source, stack); + } + if (!(result === undefined + ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack) + : result + )) { + return false; + } + } + } + return true; + } + + /** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } + + /** + * The base implementation of `_.isRegExp` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + */ + function baseIsRegExp(value) { + return isObject(value) && objectToString.call(value) == regexpTag; + } + + /** + * The base implementation of `_.isSet` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + */ + function baseIsSet(value) { + return isObjectLike(value) && getTag(value) == setTag; + } + + /** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ + function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[objectToString.call(value)]; + } + + /** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ + function baseIteratee(value) { + // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. + // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. + if (typeof value == 'function') { + return value; + } + if (value == null) { + return identity; + } + if (typeof value == 'object') { + return isArray(value) + ? baseMatchesProperty(value[0], value[1]) + : baseMatches(value); + } + return property(value); + } + + /** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.lt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + */ + function baseLt(value, other) { + return value < other; + } + + /** + * The base implementation of `_.map` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function baseMap(collection, iteratee) { + var index = -1, + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + + /** + * The base implementation of `_.matches` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + return matchesStrictComparable(matchData[0][0], matchData[0][1]); + } + return function(object) { + return object === source || baseIsMatch(object, source, matchData); + }; + } + + /** + * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. + * + * @private + * @param {string} path The path of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatchesProperty(path, srcValue) { + if (isKey(path) && isStrictComparable(srcValue)) { + return matchesStrictComparable(toKey(path), srcValue); + } + return function(object) { + var objValue = get(object, path); + return (objValue === undefined && objValue === srcValue) + ? hasIn(object, path) + : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG); + }; + } + + /** + * The base implementation of `_.merge` without support for multiple sources. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. + * @param {Function} [customizer] The function to customize merged values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor(source, function(srcValue, key) { + if (isObject(srcValue)) { + stack || (stack = new Stack); + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); + } + else { + var newValue = customizer + ? customizer(object[key], srcValue, (key + ''), object, source, stack) + : undefined; + + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); + } + + /** + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize assigned values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = object[key], + srcValue = source[key], + stacked = stack.get(srcValue); + + if (stacked) { + assignMergeValue(object, key, stacked); + return; + } + var newValue = customizer + ? customizer(objValue, srcValue, (key + ''), object, source, stack) + : undefined; + + var isCommon = newValue === undefined; + + if (isCommon) { + var isArr = isArray(srcValue), + isBuff = !isArr && isBuffer(srcValue), + isTyped = !isArr && !isBuff && isTypedArray(srcValue); + + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray(objValue)) { + newValue = objValue; + } + else if (isArrayLikeObject(objValue)) { + newValue = copyArray(objValue); + } + else if (isBuff) { + isCommon = false; + newValue = cloneBuffer(srcValue, true); + } + else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray(srcValue, true); + } + else { + newValue = []; + } + } + else if (isPlainObject(srcValue) || isArguments(srcValue)) { + newValue = objValue; + if (isArguments(objValue)) { + newValue = toPlainObject(objValue); + } + else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { + newValue = initCloneObject(srcValue); + } + } + else { + isCommon = false; + } + } + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack['delete'](srcValue); + } + assignMergeValue(object, key, newValue); + } + + /** + * The base implementation of `_.nth` which doesn't coerce arguments. + * + * @private + * @param {Array} array The array to query. + * @param {number} n The index of the element to return. + * @returns {*} Returns the nth element of `array`. + */ + function baseNth(array, n) { + var length = array.length; + if (!length) { + return; + } + n += n < 0 ? length : 0; + return isIndex(n, length) ? array[n] : undefined; + } + + /** + * The base implementation of `_.orderBy` without param guards. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. + * @param {string[]} orders The sort orders of `iteratees`. + * @returns {Array} Returns the new sorted array. + */ + function baseOrderBy(collection, iteratees, orders) { + var index = -1; + iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee())); + + var result = baseMap(collection, function(value, key, collection) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { 'criteria': criteria, 'index': ++index, 'value': value }; + }); + + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + + /** + * The base implementation of `_.pick` without support for individual + * property identifiers. + * + * @private + * @param {Object} object The source object. + * @param {string[]} props The property identifiers to pick. + * @returns {Object} Returns the new object. + */ + function basePick(object, props) { + object = Object(object); + return basePickBy(object, props, function(value, key) { + return key in object; + }); + } + + /** + * The base implementation of `_.pickBy` without support for iteratee shorthands. + * + * @private + * @param {Object} object The source object. + * @param {string[]} props The property identifiers to pick from. + * @param {Function} predicate The function invoked per property. + * @returns {Object} Returns the new object. + */ + function basePickBy(object, props, predicate) { + var index = -1, + length = props.length, + result = {}; + + while (++index < length) { + var key = props[index], + value = object[key]; + + if (predicate(value, key)) { + baseAssignValue(result, key, value); + } + } + return result; + } + + /** + * A specialized version of `baseProperty` which supports deep paths. + * + * @private + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyDeep(path) { + return function(object) { + return baseGet(object, path); + }; + } + + /** + * The base implementation of `_.pullAllBy` without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + */ + function basePullAll(array, values, iteratee, comparator) { + var indexOf = comparator ? baseIndexOfWith : baseIndexOf, + index = -1, + length = values.length, + seen = array; + + if (array === values) { + values = copyArray(values); + } + if (iteratee) { + seen = arrayMap(array, baseUnary(iteratee)); + } + while (++index < length) { + var fromIndex = 0, + value = values[index], + computed = iteratee ? iteratee(value) : value; + + while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { + if (seen !== array) { + splice.call(seen, fromIndex, 1); + } + splice.call(array, fromIndex, 1); + } + } + return array; + } + + /** + * The base implementation of `_.pullAt` without support for individual + * indexes or capturing the removed elements. + * + * @private + * @param {Array} array The array to modify. + * @param {number[]} indexes The indexes of elements to remove. + * @returns {Array} Returns `array`. + */ + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0, + lastIndex = length - 1; + + while (length--) { + var index = indexes[length]; + if (length == lastIndex || index !== previous) { + var previous = index; + if (isIndex(index)) { + splice.call(array, index, 1); + } + else if (!isKey(index, array)) { + var path = castPath(index), + object = parent(array, path); + + if (object != null) { + delete object[toKey(last(path))]; + } + } + else { + delete array[toKey(index)]; + } + } + } + return array; + } + + /** + * The base implementation of `_.random` without support for returning + * floating-point numbers. + * + * @private + * @param {number} lower The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the random number. + */ + function baseRandom(lower, upper) { + return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); + } + + /** + * The base implementation of `_.range` and `_.rangeRight` which doesn't + * coerce arguments. + * + * @private + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @param {number} step The value to increment or decrement by. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the range of numbers. + */ + function baseRange(start, end, step, fromRight) { + var index = -1, + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), + result = Array(length); + + while (length--) { + result[fromRight ? length : ++index] = start; + start += step; + } + return result; + } + + /** + * The base implementation of `_.repeat` which doesn't coerce arguments. + * + * @private + * @param {string} string The string to repeat. + * @param {number} n The number of times to repeat the string. + * @returns {string} Returns the repeated string. + */ + function baseRepeat(string, n) { + var result = ''; + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { + return result; + } + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + if (n) { + string += string; + } + } while (n); + + return result; + } + + /** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ + function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); + } + + /** + * The base implementation of `_.sample`. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + */ + function baseSample(collection) { + return arraySample(values(collection)); + } + + /** + * The base implementation of `_.sampleSize` without param guards. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function baseSampleSize(collection, n) { + var array = values(collection); + return shuffleSelf(array, baseClamp(n, 0, array.length)); + } + + /** + * The base implementation of `_.set`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseSet(object, path, value, customizer) { + if (!isObject(object)) { + return object; + } + path = isKey(path, object) ? [path] : castPath(path); + + var index = -1, + length = path.length, + lastIndex = length - 1, + nested = object; + + while (nested != null && ++index < length) { + var key = toKey(path[index]), + newValue = value; + + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = isObject(objValue) + ? objValue + : (isIndex(path[index + 1]) ? [] : {}); + } + } + assignValue(nested, key, newValue); + nested = nested[key]; + } + return object; + } + + /** + * The base implementation of `setData` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + + /** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var baseSetToString = !defineProperty ? identity : function(func, string) { + return defineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); + }; + + /** + * The base implementation of `_.shuffle`. + * + * @private + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function baseShuffle(collection) { + return shuffleSelf(values(collection)); + } + + /** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + + /** + * The base implementation of `_.some` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function baseSome(collection, predicate) { + var result; + + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + + /** + * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which + * performs a binary search of `array` to determine the index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndex(array, value, retHighest) { + var low = 0, + high = array ? array.length : low; + + if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = (low + high) >>> 1, + computed = array[mid]; + + if (computed !== null && !isSymbol(computed) && + (retHighest ? (computed <= value) : (computed < value))) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return baseSortedIndexBy(array, value, identity, retHighest); + } + + /** + * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy` + * which invokes `iteratee` for `value` and each element of `array` to compute + * their sort ranking. The iteratee is invoked with one argument; (value). + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} iteratee The iteratee invoked per element. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + + var low = 0, + high = array ? array.length : 0, + valIsNaN = value !== value, + valIsNull = value === null, + valIsSymbol = isSymbol(value), + valIsUndefined = value === undefined; + + while (low < high) { + var mid = nativeFloor((low + high) / 2), + computed = iteratee(array[mid]), + othIsDefined = computed !== undefined, + othIsNull = computed === null, + othIsReflexive = computed === computed, + othIsSymbol = isSymbol(computed); + + if (valIsNaN) { + var setLow = retHighest || othIsReflexive; + } else if (valIsUndefined) { + setLow = othIsReflexive && (retHighest || othIsDefined); + } else if (valIsNull) { + setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); + } else if (valIsSymbol) { + setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); + } else if (othIsNull || othIsSymbol) { + setLow = false; + } else { + setLow = retHighest ? (computed <= value) : (computed < value); + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + + /** + * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseSortedUniq(array, iteratee) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + if (!index || !eq(computed, seen)) { + var seen = computed; + result[resIndex++] = value === 0 ? 0 : value; + } + } + return result; + } + + /** + * The base implementation of `_.toNumber` which doesn't ensure correct + * conversions of binary, hexadecimal, or octal string values. + * + * @private + * @param {*} value The value to process. + * @returns {number} Returns the number. + */ + function baseToNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + return +value; + } + + /** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ + function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * The base implementation of `_.uniqBy` without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseUniq(array, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + length = array.length, + isCommon = true, + result = [], + seen = result; + + if (comparator) { + isCommon = false; + includes = arrayIncludesWith; + } + else if (length >= LARGE_ARRAY_SIZE) { + var set = iteratee ? null : createSet(array); + if (set) { + return setToArray(set); + } + isCommon = false; + includes = cacheHas; + seen = new SetCache; + } + else { + seen = iteratee ? [] : result; + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } + else if (!includes(seen, computed, comparator)) { + if (seen !== result) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.unset`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + */ + function baseUnset(object, path) { + path = isKey(path, object) ? [path] : castPath(path); + object = parent(object, path); + + var key = toKey(last(path)); + return !(object != null && hasOwnProperty.call(object, key)) || delete object[key]; + } + + /** + * The base implementation of `_.update`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to update. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseUpdate(object, path, updater, customizer) { + return baseSet(object, path, updater(baseGet(object, path)), customizer); + } + + /** + * The base implementation of methods like `_.dropWhile` and `_.takeWhile` + * without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to query. + * @param {Function} predicate The function invoked per iteration. + * @param {boolean} [isDrop] Specify dropping elements instead of taking them. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the slice of `array`. + */ + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length) && + predicate(array[index], index, array)) {} + + return isDrop + ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) + : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index)); + } + + /** + * The base implementation of `wrapperValue` which returns the result of + * performing a sequence of actions on the unwrapped `value`, where each + * successive action is supplied the return value of the previous. + * + * @private + * @param {*} value The unwrapped value. + * @param {Array} actions Actions to perform to resolve the unwrapped value. + * @returns {*} Returns the resolved value. + */ + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + return arrayReduce(actions, function(result, action) { + return action.func.apply(action.thisArg, arrayPush([result], action.args)); + }, result); + } + + /** + * The base implementation of methods like `_.xor`, without support for + * iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of values. + */ + function baseXor(arrays, iteratee, comparator) { + var index = -1, + length = arrays.length; + + while (++index < length) { + var result = result + ? arrayPush( + baseDifference(result, arrays[index], iteratee, comparator), + baseDifference(arrays[index], result, iteratee, comparator) + ) + : arrays[index]; + } + return (result && result.length) ? baseUniq(result, iteratee, comparator) : []; + } + + /** + * This base implementation of `_.zipObject` which assigns values using `assignFunc`. + * + * @private + * @param {Array} props The property identifiers. + * @param {Array} values The property values. + * @param {Function} assignFunc The function to assign values. + * @returns {Object} Returns the new object. + */ + function baseZipObject(props, values, assignFunc) { + var index = -1, + length = props.length, + valsLength = values.length, + result = {}; + + while (++index < length) { + var value = index < valsLength ? values[index] : undefined; + assignFunc(result, props[index], value); + } + return result; + } + + /** + * Casts `value` to an empty array if it's not an array like object. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array|Object} Returns the cast array-like object. + */ + function castArrayLikeObject(value) { + return isArrayLikeObject(value) ? value : []; + } + + /** + * Casts `value` to `identity` if it's not a function. + * + * @private + * @param {*} value The value to inspect. + * @returns {Function} Returns cast function. + */ + function castFunction(value) { + return typeof value == 'function' ? value : identity; + } + + /** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array} Returns the cast property path array. + */ + function castPath(value) { + return isArray(value) ? value : stringToPath(value); + } + + /** + * A `baseRest` alias which can be replaced with `identity` by module + * replacement plugins. + * + * @private + * @type {Function} + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + var castRest = baseRest; + + /** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ + function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); + } + + /** + * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout). + * + * @private + * @param {number|Object} id The timer id or timeout object of the timer to clear. + */ + var clearTimeout = ctxClearTimeout || function(id) { + return root.clearTimeout(id); + }; + + /** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ + function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; + } + + /** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); + return result; + } + + /** + * Creates a clone of `dataView`. + * + * @private + * @param {Object} dataView The data view to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned data view. + */ + function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); + } + + /** + * Creates a clone of `map`. + * + * @private + * @param {Object} map The map to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned map. + */ + function cloneMap(map, isDeep, cloneFunc) { + var array = isDeep ? cloneFunc(mapToArray(map), true) : mapToArray(map); + return arrayReduce(array, addMapEntry, new map.constructor); + } + + /** + * Creates a clone of `regexp`. + * + * @private + * @param {Object} regexp The regexp to clone. + * @returns {Object} Returns the cloned regexp. + */ + function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; + } + + /** + * Creates a clone of `set`. + * + * @private + * @param {Object} set The set to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned set. + */ + function cloneSet(set, isDeep, cloneFunc) { + var array = isDeep ? cloneFunc(setToArray(set), true) : setToArray(set); + return arrayReduce(array, addSetEntry, new set.constructor); + } + + /** + * Creates a clone of the `symbol` object. + * + * @private + * @param {Object} symbol The symbol object to clone. + * @returns {Object} Returns the cloned symbol object. + */ + function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; + } + + /** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ + function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); + } + + /** + * Compares values to sort them in ascending order. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {number} Returns the sort order indicator for `value`. + */ + function compareAscending(value, other) { + if (value !== other) { + var valIsDefined = value !== undefined, + valIsNull = value === null, + valIsReflexive = value === value, + valIsSymbol = isSymbol(value); + + var othIsDefined = other !== undefined, + othIsNull = other === null, + othIsReflexive = other === other, + othIsSymbol = isSymbol(other); + + if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || + (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || + (valIsNull && othIsDefined && othIsReflexive) || + (!valIsDefined && othIsReflexive) || + !valIsReflexive) { + return 1; + } + if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || + (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || + (othIsNull && valIsDefined && valIsReflexive) || + (!othIsDefined && valIsReflexive) || + !othIsReflexive) { + return -1; + } + } + return 0; + } + + /** + * Used by `_.orderBy` to compare multiple properties of a value to another + * and stable sort them. + * + * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, + * specify an order of "desc" for descending or "asc" for ascending sort order + * of corresponding values. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {boolean[]|string[]} orders The order to sort by for each property. + * @returns {number} Returns the sort order indicator for `object`. + */ + function compareMultiple(object, other, orders) { + var index = -1, + objCriteria = object.criteria, + othCriteria = other.criteria, + length = objCriteria.length, + ordersLength = orders.length; + + while (++index < length) { + var result = compareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order == 'desc' ? -1 : 1); + } + } + // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications + // that causes it, under certain circumstances, to provide the same value for + // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 + // for more details. + // + // This also ensures a stable sort in V8 and other engines. + // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. + return object.index - other.index; + } + + /** + * Creates an array that is the composition of partially applied arguments, + * placeholders, and provided arguments into a single array of arguments. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to prepend to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgs(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersLength = holders.length, + leftIndex = -1, + leftLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(leftLength + rangeLength), + isUncurried = !isCurried; + + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + } + while (rangeLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + + /** + * This function is like `composeArgs` except that the arguments composition + * is tailored for `_.partialRight`. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to append to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgsRight(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersIndex = -1, + holdersLength = holders.length, + rightIndex = -1, + rightLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(rangeLength + rightLength), + isUncurried = !isCurried; + + while (++argsIndex < rangeLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + } + return result; + } + + /** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ + function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + + /** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ + function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; + } + + /** + * Copies own symbol properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbols(source, object) { + return copyObject(source, getSymbols(source), object); + } + + /** + * Creates a function like `_.groupBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} [initializer] The accumulator object initializer. + * @returns {Function} Returns the new aggregator function. + */ + function createAggregator(setter, initializer) { + return function(collection, iteratee) { + var func = isArray(collection) ? arrayAggregator : baseAggregator, + accumulator = initializer ? initializer() : {}; + + return func(collection, setter, getIteratee(iteratee, 2), accumulator); + }; + } + + /** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + + /** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { + return eachFunc(collection, iteratee); + } + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + + /** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + + /** + * Creates a function that wraps `func` to invoke it with the optional `this` + * binding of `thisArg`. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createBind(func, bitmask, thisArg) { + var isBind = bitmask & BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return fn.apply(isBind ? thisArg : this, arguments); + } + return wrapper; + } + + /** + * Creates a function like `_.lowerFirst`. + * + * @private + * @param {string} methodName The name of the `String` case method to use. + * @returns {Function} Returns the new case function. + */ + function createCaseFirst(methodName) { + return function(string) { + string = toString(string); + + var strSymbols = hasUnicode(string) + ? stringToArray(string) + : undefined; + + var chr = strSymbols + ? strSymbols[0] + : string.charAt(0); + + var trailing = strSymbols + ? castSlice(strSymbols, 1).join('') + : string.slice(1); + + return chr[methodName]() + trailing; + }; + } + + /** + * Creates a function like `_.camelCase`. + * + * @private + * @param {Function} callback The function to combine each word. + * @returns {Function} Returns the new compounder function. + */ + function createCompounder(callback) { + return function(string) { + return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); + }; + } + + /** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ + function createCtor(Ctor) { + return function() { + // Use a `switch` statement to work with class constructors. See + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // for more details. + var args = arguments; + switch (args.length) { + case 0: return new Ctor; + case 1: return new Ctor(args[0]); + case 2: return new Ctor(args[0], args[1]); + case 3: return new Ctor(args[0], args[1], args[2]); + case 4: return new Ctor(args[0], args[1], args[2], args[3]); + case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, args); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; + } + + /** + * Creates a function that wraps `func` to enable currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {number} arity The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createCurry(func, bitmask, arity) { + var Ctor = createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length, + placeholder = getHolder(wrapper); + + while (index--) { + args[index] = arguments[index]; + } + var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) + ? [] + : replaceHolders(args, placeholder); + + length -= holders.length; + if (length < arity) { + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, undefined, + args, holders, undefined, undefined, arity - length); + } + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return apply(fn, this, args); + } + return wrapper; + } + + /** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} findIndexFunc The function to find the collection index. + * @returns {Function} Returns the new find function. + */ + function createFind(findIndexFunc) { + return function(collection, predicate, fromIndex) { + var iterable = Object(collection); + if (!isArrayLike(collection)) { + var iteratee = getIteratee(predicate, 3); + collection = keys(collection); + predicate = function(key) { return iteratee(iterable[key], key, iterable); }; + } + var index = findIndexFunc(collection, predicate, fromIndex); + return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; + }; + } + + /** + * Creates a `_.flow` or `_.flowRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new flow function. + */ + function createFlow(fromRight) { + return flatRest(function(funcs) { + var length = funcs.length, + index = length, + prereq = LodashWrapper.prototype.thru; + + if (fromRight) { + funcs.reverse(); + } + while (index--) { + var func = funcs[index]; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (prereq && !wrapper && getFuncName(func) == 'wrapper') { + var wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? index : length; + while (++index < length) { + func = funcs[index]; + + var funcName = getFuncName(func), + data = funcName == 'wrapper' ? getData(func) : undefined; + + if (data && isLaziable(data[0]) && + data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && + !data[4].length && data[9] == 1 + ) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = (func.length == 1 && isLaziable(func)) + ? wrapper[funcName]() + : wrapper.thru(func); + } + } + return function() { + var args = arguments, + value = args[0]; + + if (wrapper && args.length == 1 && + isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, + result = length ? funcs[index].apply(this, args) : value; + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }); + } + + /** + * Creates a function that wraps `func` to invoke it with optional `this` + * binding of `thisArg`, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [partialsRight] The arguments to append to those provided + * to the new function. + * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, + isBind = bitmask & BIND_FLAG, + isBindKey = bitmask & BIND_KEY_FLAG, + isCurried = bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG), + isFlip = bitmask & FLIP_FLAG, + Ctor = isBindKey ? undefined : createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length; + + while (index--) { + args[index] = arguments[index]; + } + if (isCurried) { + var placeholder = getHolder(wrapper), + holdersCount = countHolders(args, placeholder); + } + if (partials) { + args = composeArgs(args, partials, holders, isCurried); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight, isCurried); + } + length -= holdersCount; + if (isCurried && length < arity) { + var newHolders = replaceHolders(args, placeholder); + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, thisArg, + args, newHolders, argPos, ary, arity - length + ); + } + var thisBinding = isBind ? thisArg : this, + fn = isBindKey ? thisBinding[func] : func; + + length = args.length; + if (argPos) { + args = reorder(args, argPos); + } else if (isFlip && length > 1) { + args.reverse(); + } + if (isAry && ary < length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtor(fn); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + + /** + * Creates a function like `_.invertBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} toIteratee The function to resolve iteratees. + * @returns {Function} Returns the new inverter function. + */ + function createInverter(setter, toIteratee) { + return function(object, iteratee) { + return baseInverter(object, setter, toIteratee(iteratee), {}); + }; + } + + /** + * Creates a function that performs a mathematical operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @param {number} [defaultValue] The value used for `undefined` arguments. + * @returns {Function} Returns the new mathematical operation function. + */ + function createMathOperation(operator, defaultValue) { + return function(value, other) { + var result; + if (value === undefined && other === undefined) { + return defaultValue; + } + if (value !== undefined) { + result = value; + } + if (other !== undefined) { + if (result === undefined) { + return other; + } + if (typeof value == 'string' || typeof other == 'string') { + value = baseToString(value); + other = baseToString(other); + } else { + value = baseToNumber(value); + other = baseToNumber(other); + } + result = operator(value, other); + } + return result; + }; + } + + /** + * Creates a function like `_.over`. + * + * @private + * @param {Function} arrayFunc The function to iterate over iteratees. + * @returns {Function} Returns the new over function. + */ + function createOver(arrayFunc) { + return flatRest(function(iteratees) { + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); + return baseRest(function(args) { + var thisArg = this; + return arrayFunc(iteratees, function(iteratee) { + return apply(iteratee, thisArg, args); + }); + }); + }); + } + + /** + * Creates the padding for `string` based on `length`. The `chars` string + * is truncated if the number of characters exceeds `length`. + * + * @private + * @param {number} length The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padding for `string`. + */ + function createPadding(length, chars) { + chars = chars === undefined ? ' ' : baseToString(chars); + + var charsLength = chars.length; + if (charsLength < 2) { + return charsLength ? baseRepeat(chars, length) : chars; + } + var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); + return hasUnicode(chars) + ? castSlice(stringToArray(result), 0, length).join('') + : result.slice(0, length); + } + + /** + * Creates a function that wraps `func` to invoke it with the `this` binding + * of `thisArg` and `partials` prepended to the arguments it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to + * the new function. + * @returns {Function} Returns the new wrapped function. + */ + function createPartial(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(leftLength + argsLength), + fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return apply(fn, isBind ? thisArg : this, args); + } + return wrapper; + } + + /** + * Creates a `_.range` or `_.rangeRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new range function. + */ + function createRange(fromRight) { + return function(start, end, step) { + if (step && typeof step != 'number' && isIterateeCall(start, end, step)) { + end = step = undefined; + } + // Ensure the sign of `-0` is preserved. + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + step = step === undefined ? (start < end ? 1 : -1) : toFinite(step); + return baseRange(start, end, step, fromRight); + }; + } + + /** + * Creates a function that performs a relational operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @returns {Function} Returns the new relational operation function. + */ + function createRelationalOperation(operator) { + return function(value, other) { + if (!(typeof value == 'string' && typeof other == 'string')) { + value = toNumber(value); + other = toNumber(other); + } + return operator(value, other); + }; + } + + /** + * Creates a function that wraps `func` to continue currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {Function} wrapFunc The function to create the `func` wrapper. + * @param {*} placeholder The placeholder value. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { + var isCurry = bitmask & CURRY_FLAG, + newHolders = isCurry ? holders : undefined, + newHoldersRight = isCurry ? undefined : holders, + newPartials = isCurry ? partials : undefined, + newPartialsRight = isCurry ? undefined : partials; + + bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + + if (!(bitmask & CURRY_BOUND_FLAG)) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ + func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, + newHoldersRight, argPos, ary, arity + ]; + + var result = wrapFunc.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return setWrapToString(result, func, bitmask); + } + + /** + * Creates a function like `_.round`. + * + * @private + * @param {string} methodName The name of the `Math` method to use when rounding. + * @returns {Function} Returns the new round function. + */ + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + number = toNumber(number); + precision = nativeMin(toInteger(precision), 292); + if (precision) { + // Shift with exponential notation to avoid floating-point issues. + // See [MDN](https://mdn.io/round#Examples) for more details. + var pair = (toString(number) + 'e').split('e'), + value = func(pair[0] + 'e' + (+pair[1] + precision)); + + pair = (toString(value) + 'e').split('e'); + return +(pair[0] + 'e' + (+pair[1] - precision)); + } + return func(number); + }; + } + + /** + * Creates a set object of `values`. + * + * @private + * @param {Array} values The values to add to the set. + * @returns {Object} Returns the new set. + */ + var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) { + return new Set(values); + }; + + /** + * Creates a `_.toPairs` or `_.toPairsIn` function. + * + * @private + * @param {Function} keysFunc The function to get the keys of a given object. + * @returns {Function} Returns the new pairs function. + */ + function createToPairs(keysFunc) { + return function(object) { + var tag = getTag(object); + if (tag == mapTag) { + return mapToArray(object); + } + if (tag == setTag) { + return setToPairs(object); + } + return baseToPairs(object, keysFunc(object)); + }; + } + + /** + * Creates a function that either curries or invokes `func` with optional + * `this` binding and partially applied arguments. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. + * The bitmask may be composed of the following flags: + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` or `_.curryRight` of a bound function + * 8 - `_.curry` + * 16 - `_.curryRight` + * 32 - `_.partial` + * 64 - `_.partialRight` + * 128 - `_.rearg` + * 256 - `_.ary` + * 512 - `_.flip` + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to be partially applied. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); + arity = arity === undefined ? arity : toInteger(arity); + length -= holders ? holders.length : 0; + + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, + holdersRight = holders; + + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func); + + var newData = [ + func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, + argPos, ary, arity + ]; + + if (data) { + mergeData(newData, data); + } + func = newData[0]; + bitmask = newData[1]; + thisArg = newData[2]; + partials = newData[3]; + holders = newData[4]; + arity = newData[9] = newData[9] == null + ? (isBindKey ? 0 : func.length) + : nativeMax(newData[9] - length, 0); + + if (!arity && bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG)) { + bitmask &= ~(CURRY_FLAG | CURRY_RIGHT_FLAG); + } + if (!bitmask || bitmask == BIND_FLAG) { + var result = createBind(func, bitmask, thisArg); + } else if (bitmask == CURRY_FLAG || bitmask == CURRY_RIGHT_FLAG) { + result = createCurry(func, bitmask, arity); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !holders.length) { + result = createPartial(func, bitmask, thisArg, partials); + } else { + result = createHybrid.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setWrapToString(setter(result, newData), func, bitmask); + } + + /** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} customizer The function to customize comparisons. + * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual` + * for more details. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ + function equalArrays(array, other, equalFunc, customizer, bitmask, stack) { + var isPartial = bitmask & PARTIAL_COMPARE_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(array); + if (stacked && stack.get(other)) { + return stacked == other; + } + var index = -1, + result = true, + seen = (bitmask & UNORDERED_COMPARE_FLAG) ? new SetCache : undefined; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, customizer, bitmask, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} customizer The function to customize comparisons. + * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual` + * for more details. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalByTag(object, other, tag, equalFunc, customizer, bitmask, stack) { + switch (tag) { + case dataViewTag: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; + + case arrayBufferTag: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); + + case errorTag: + return object.name == other.name && object.message == other.message; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); + + case mapTag: + var convert = mapToArray; + + case setTag: + var isPartial = bitmask & PARTIAL_COMPARE_FLAG; + convert || (convert = setToArray); + + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= UNORDERED_COMPARE_FLAG; + + // Recursively compare objects (susceptible to call stack limits). + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), equalFunc, customizer, bitmask, stack); + stack['delete'](object); + return result; + + case symbolTag: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; + } + + /** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} customizer The function to customize comparisons. + * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual` + * for more details. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalObjects(object, other, equalFunc, customizer, bitmask, stack) { + var isPartial = bitmask & PARTIAL_COMPARE_FLAG, + objProps = keys(object), + objLength = objProps.length, + othProps = keys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked && stack.get(other)) { + return stacked == other; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + stack['delete'](object); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseRest` which flattens the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + function flatRest(func) { + return setToString(overRest(func, undefined, flatten), func + ''); + } + + /** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); + } + + /** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); + } + + /** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + + /** + * Gets the name of `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {string} Returns the function name. + */ + function getFuncName(func) { + var result = (func.name + ''), + array = realNames[result], + length = hasOwnProperty.call(realNames, result) ? array.length : 0; + + while (length--) { + var data = array[length], + otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + + /** + * Gets the argument placeholder value for `func`. + * + * @private + * @param {Function} func The function to inspect. + * @returns {*} Returns the placeholder value. + */ + function getHolder(func) { + var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func; + return object.placeholder; + } + + /** + * Gets the appropriate "iteratee" function. If `_.iteratee` is customized, + * this function returns the custom method, otherwise it returns `baseIteratee`. + * If arguments are provided, the chosen function is invoked with them and + * its result is returned. + * + * @private + * @param {*} [value] The value to convert to an iteratee. + * @param {number} [arity] The arity of the created iteratee. + * @returns {Function} Returns the chosen function or its result. + */ + function getIteratee() { + var result = lodash.iteratee || iteratee; + result = result === iteratee ? baseIteratee : result; + return arguments.length ? result(arguments[0], arguments[1]) : result; + } + + /** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ + function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; + } + + /** + * Gets the property names, values, and compare flags of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the match data of `object`. + */ + function getMatchData(object) { + var result = keys(object), + length = result.length; + + while (length--) { + var key = result[length], + value = object[key]; + + result[length] = [key, value, isStrictComparable(value)]; + } + return result; + } + + /** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; + } + + /** + * Creates an array of the own enumerable symbol properties of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbols = nativeGetSymbols ? overArg(nativeGetSymbols, Object) : stubArray; + + /** + * Creates an array of the own and inherited enumerable symbol properties + * of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototype(object); + } + return result; + }; + + /** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + var getTag = baseGetTag; + + // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. + if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = objectToString.call(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : undefined; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; + } + + /** + * Gets the view, applying any `transforms` to the `start` and `end` positions. + * + * @private + * @param {number} start The start of the view. + * @param {number} end The end of the view. + * @param {Array} transforms The transformations to apply to the view. + * @returns {Object} Returns an object containing the `start` and `end` + * positions of the view. + */ + function getView(start, end, transforms) { + var index = -1, + length = transforms.length; + + while (++index < length) { + var data = transforms[index], + size = data.size; + + switch (data.type) { + case 'drop': start += size; break; + case 'dropRight': end -= size; break; + case 'take': end = nativeMin(end, start + size); break; + case 'takeRight': start = nativeMax(start, end - size); break; + } + } + return { 'start': start, 'end': end }; + } + + /** + * Extracts wrapper details from the `source` body comment. + * + * @private + * @param {string} source The source to inspect. + * @returns {Array} Returns the wrapper details. + */ + function getWrapDetails(source) { + var match = source.match(reWrapDetails); + return match ? match[1].split(reSplitDetails) : []; + } + + /** + * Checks if `path` exists on `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @param {Function} hasFunc The function to check properties. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + */ + function hasPath(object, path, hasFunc) { + path = isKey(path, object) ? [path] : castPath(path); + + var index = -1, + length = path.length, + result = false; + + while (++index < length) { + var key = toKey(path[index]); + if (!(result = object != null && hasFunc(object, key))) { + break; + } + object = object[key]; + } + if (result || ++index != length) { + return result; + } + length = object ? object.length : 0; + return !!length && isLength(length) && isIndex(key, length) && + (isArray(object) || isArguments(object)); + } + + /** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ + function initCloneArray(array) { + var length = array.length, + result = array.constructor(length); + + // Add properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; + } + + /** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; + } + + /** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneByTag(object, tag, cloneFunc, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return cloneArrayBuffer(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case dataViewTag: + return cloneDataView(object, isDeep); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + return cloneTypedArray(object, isDeep); + + case mapTag: + return cloneMap(object, isDeep, cloneFunc); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + return cloneRegExp(object); + + case setTag: + return cloneSet(object, isDeep, cloneFunc); + + case symbolTag: + return cloneSymbol(object); + } + } + + /** + * Inserts wrapper `details` in a comment at the top of the `source` body. + * + * @private + * @param {string} source The source to modify. + * @returns {Array} details The details to insert. + * @returns {string} Returns the modified source. + */ + function insertWrapDetails(source, details) { + var length = details.length; + if (!length) { + return source; + } + var lastIndex = length - 1; + details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; + details = details.join(length > 2 ? ', ' : ' '); + return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); + } + + /** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ + function isFlattenable(value) { + return isArray(value) || isArguments(value) || + !!(spreadableSymbol && value && value[spreadableSymbol]); + } + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + length = length == null ? MAX_SAFE_INTEGER : length; + return !!length && + (typeof value == 'number' || reIsUint.test(value)) && + (value > -1 && value % 1 == 0 && value < length); + } + + /** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; + } + + /** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ + function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); + } + + /** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ + function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); + } + + /** + * Checks if `func` has a lazy counterpart. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` has a lazy counterpart, + * else `false`. + */ + function isLaziable(func) { + var funcName = getFuncName(func), + other = lodash[funcName]; + + if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + + /** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ + function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); + } + + /** + * Checks if `func` is capable of being masked. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `func` is maskable, else `false`. + */ + var isMaskable = coreJsData ? isFunction : stubFalse; + + /** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ + function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; + } + + /** + * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` if suitable for strict + * equality comparisons, else `false`. + */ + function isStrictComparable(value) { + return value === value && !isObject(value); + } + + /** + * A specialized version of `matchesProperty` for source values suitable + * for strict equality comparisons, i.e. `===`. + * + * @private + * @param {string} key The key of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + return false; + } + return object[key] === srcValue && + (srcValue !== undefined || (key in Object(object))); + }; + } + + /** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ + function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; + } + + /** + * Merges the function metadata of `source` into `data`. + * + * Merging metadata reduces the number of wrappers used to invoke a function. + * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` + * may be applied regardless of execution order. Methods like `_.ary` and + * `_.rearg` modify function arguments, making the order in which they are + * executed important, preventing the merging of metadata. However, we make + * an exception for a safe combined case where curried functions have `_.ary` + * and or `_.rearg` applied. + * + * @private + * @param {Array} data The destination metadata. + * @param {Array} source The source metadata. + * @returns {Array} Returns `data`. + */ + function mergeData(data, source) { + var bitmask = data[1], + srcBitmask = source[1], + newBitmask = bitmask | srcBitmask, + isCommon = newBitmask < (BIND_FLAG | BIND_KEY_FLAG | ARY_FLAG); + + var isCombo = + ((srcBitmask == ARY_FLAG) && (bitmask == CURRY_FLAG)) || + ((srcBitmask == ARY_FLAG) && (bitmask == REARG_FLAG) && (data[7].length <= source[8])) || + ((srcBitmask == (ARY_FLAG | REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == CURRY_FLAG)); + + // Exit early if metadata can't be merged. + if (!(isCommon || isCombo)) { + return data; + } + // Use source `thisArg` if available. + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + // Set when currying a bound function. + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + // Compose partial arguments. + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : value; + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; + } + // Compose partial right arguments. + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; + } + // Use source `argPos` if available. + value = source[7]; + if (value) { + data[7] = value; + } + // Use source `ary` if it's smaller. + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + // Use source `arity` if one is not provided. + if (data[9] == null) { + data[9] = source[9]; + } + // Use source `func` and merge bitmasks. + data[0] = source[0]; + data[1] = newBitmask; + + return data; + } + + /** + * Used by `_.defaultsDeep` to customize its `_.merge` use. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to merge. + * @param {Object} object The parent object of `objValue`. + * @param {Object} source The parent object of `srcValue`. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + * @returns {*} Returns the value to assign. + */ + function mergeDefaults(objValue, srcValue, key, object, source, stack) { + if (isObject(objValue) && isObject(srcValue)) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, objValue); + baseMerge(objValue, srcValue, undefined, mergeDefaults, stack); + stack['delete'](srcValue); + } + return objValue; + } + + /** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; + } + + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; + } + + /** + * Gets the parent value at `path` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} path The path to get the parent value of. + * @returns {*} Returns the parent value. + */ + function parent(object, path) { + return path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + } + + /** + * Reorder `array` according to the specified indexes where the element at + * the first index is assigned as the first element, the element at + * the second index is assigned as the second element, and so on. + * + * @private + * @param {Array} array The array to reorder. + * @param {Array} indexes The arranged array indexes. + * @returns {Array} Returns `array`. + */ + function reorder(array, indexes) { + var arrLength = array.length, + length = nativeMin(indexes.length, arrLength), + oldArray = copyArray(array); + + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + + /** + * Sets metadata for `func`. + * + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short + * period of time, it will trip its breaker and transition to an identity + * function to avoid garbage collection pauses in V8. See + * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) + * for more details. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var setData = shortOut(baseSetData); + + /** + * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout). + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @returns {number|Object} Returns the timer id or timeout object. + */ + var setTimeout = ctxSetTimeout || function(func, wait) { + return root.setTimeout(func, wait); + }; + + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = shortOut(baseSetToString); + + /** + * Sets the `toString` method of `wrapper` to mimic the source of `reference` + * with wrapper details in a comment at the top of the source body. + * + * @private + * @param {Function} wrapper The function to modify. + * @param {Function} reference The reference function. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Function} Returns `wrapper`. + */ + function setWrapToString(wrapper, reference, bitmask) { + var source = (reference + ''); + return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); + } + + /** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ + function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; + } + + /** + * A specialized version of `_.shuffle` which mutates and sets the size of `array`. + * + * @private + * @param {Array} array The array to shuffle. + * @param {number} [size=array.length] The size of `array`. + * @returns {Array} Returns `array`. + */ + function shuffleSelf(array, size) { + var index = -1, + length = array.length, + lastIndex = length - 1; + + size = size === undefined ? length : size; + while (++index < size) { + var rand = baseRandom(index, lastIndex), + value = array[rand]; + + array[rand] = array[index]; + array[index] = value; + } + array.length = size; + return array; + } + + /** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ + var stringToPath = memoizeCapped(function(string) { + string = toString(string); + + var result = []; + if (reLeadingDot.test(string)) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; + }); + + /** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ + function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to process. + * @returns {string} Returns the source code. + */ + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; + } + + /** + * Updates wrapper `details` based on `bitmask` flags. + * + * @private + * @returns {Array} details The details to modify. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Array} Returns `details`. + */ + function updateWrapDetails(details, bitmask) { + arrayEach(wrapFlags, function(pair) { + var value = '_.' + pair[0]; + if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { + details.push(value); + } + }); + return details.sort(); + } + + /** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ + function wrapperClone(wrapper) { + if (wrapper instanceof LazyWrapper) { + return wrapper.clone(); + } + var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); + result.__actions__ = copyArray(wrapper.__actions__); + result.__index__ = wrapper.__index__; + result.__values__ = wrapper.__values__; + return result; + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of elements split into groups the length of `size`. + * If `array` can't be split evenly, the final chunk will be the remaining + * elements. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to process. + * @param {number} [size=1] The length of each chunk + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the new array of chunks. + * @example + * + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] + */ + function chunk(array, size, guard) { + if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) { + size = 1; + } else { + size = nativeMax(toInteger(size), 0); + } + var length = array ? array.length : 0; + if (!length || size < 1) { + return []; + } + var index = 0, + resIndex = 0, + result = Array(nativeCeil(length / size)); + + while (index < length) { + result[resIndex++] = baseSlice(array, index, (index += size)); + } + return result; + } + + /** + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are falsey. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + var index = -1, + length = array ? array.length : 0, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * Creates a new array concatenating `array` with any additional arrays + * and/or values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to concatenate. + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var other = _.concat(array, 2, [3], [[4]]); + * + * console.log(other); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ + function concat() { + var length = arguments.length; + if (!length) { + return []; + } + var args = Array(length - 1), + array = arguments[0], + index = length; + + while (index--) { + args[index - 1] = arguments[index]; + } + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); + } + + /** + * Creates an array of `array` values not included in the other given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * **Note:** Unlike `_.pullAll`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.without, _.xor + * @example + * + * _.difference([2, 1], [2, 3]); + * // => [1] + */ + var difference = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `iteratee` which + * is invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * **Note:** Unlike `_.pullAllBy`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2] + * + * // The `_.property` iteratee shorthand. + * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var differenceBy = baseRest(function(array, values) { + var iteratee = last(values); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `comparator` + * which is invoked to compare elements of `array` to `values`. The order and + * references of result values are determined by the first array. The comparator + * is invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.pullAllWith`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * + * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual); + * // => [{ 'x': 2, 'y': 1 }] + */ + var differenceWith = baseRest(function(array, values) { + var comparator = last(values); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator) + : []; + }); + + /** + * Creates a slice of `array` with `n` elements dropped from the beginning. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.drop([1, 2, 3]); + * // => [2, 3] + * + * _.drop([1, 2, 3], 2); + * // => [3] + * + * _.drop([1, 2, 3], 5); + * // => [] + * + * _.drop([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with `n` elements dropped from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.dropRight([1, 2, 3]); + * // => [1, 2] + * + * _.dropRight([1, 2, 3], 2); + * // => [1] + * + * _.dropRight([1, 2, 3], 5); + * // => [] + * + * _.dropRight([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` excluding elements dropped from the end. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.dropRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney'] + * + * // The `_.matches` iteratee shorthand. + * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropRightWhile(users, ['active', false]); + * // => objects for ['barney'] + * + * // The `_.property` iteratee shorthand. + * _.dropRightWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true, true) + : []; + } + + /** + * Creates a slice of `array` excluding elements dropped from the beginning. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.dropWhile(users, function(o) { return !o.active; }); + * // => objects for ['pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.dropWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropWhile(users, ['active', false]); + * // => objects for ['pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.dropWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true) + : []; + } + + /** + * Fills elements of `array` with `value` from `start` up to, but not + * including, `end`. + * + * **Note:** This method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Array + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.fill(array, 'a'); + * console.log(array); + * // => ['a', 'a', 'a'] + * + * _.fill(Array(3), 2); + * // => [2, 2, 2] + * + * _.fill([4, 6, 8, 10], '*', 1, 3); + * // => [4, '*', '*', 10] + */ + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + + /** + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.findIndex(users, function(o) { return o.user == 'barney'; }); + * // => 0 + * + * // The `_.matches` iteratee shorthand. + * _.findIndex(users, { 'user': 'fred', 'active': false }); + * // => 1 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findIndex(users, ['active', false]); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.findIndex(users, 'active'); + * // => 2 + */ + function findIndex(array, predicate, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseFindIndex(array, getIteratee(predicate, 3), index); + } + + /** + * This method is like `_.findIndex` except that it iterates over elements + * of `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); + * // => 2 + * + * // The `_.matches` iteratee shorthand. + * _.findLastIndex(users, { 'user': 'barney', 'active': true }); + * // => 0 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastIndex(users, ['active', false]); + * // => 2 + * + * // The `_.property` iteratee shorthand. + * _.findLastIndex(users, 'active'); + * // => 0 + */ + function findLastIndex(array, predicate, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length - 1; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = fromIndex < 0 + ? nativeMax(length + index, 0) + : nativeMin(index, length - 1); + } + return baseFindIndex(array, getIteratee(predicate, 3), index, true); + } + + /** + * Flattens `array` a single level deep. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flatten([1, [2, [3, [4]], 5]]); + * // => [1, 2, [3, [4]], 5] + */ + function flatten(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, 1) : []; + } + + /** + * Recursively flattens `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flattenDeep([1, [2, [3, [4]], 5]]); + * // => [1, 2, 3, 4, 5] + */ + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, INFINITY) : []; + } + + /** + * Recursively flatten `array` up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Array + * @param {Array} array The array to flatten. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * var array = [1, [2, [3, [4]], 5]]; + * + * _.flattenDepth(array, 1); + * // => [1, 2, [3, [4]], 5] + * + * _.flattenDepth(array, 2); + * // => [1, 2, 3, [4], 5] + */ + function flattenDepth(array, depth) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(array, depth); + } + + /** + * The inverse of `_.toPairs`; this method returns an object composed + * from key-value `pairs`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} pairs The key-value pairs. + * @returns {Object} Returns the new object. + * @example + * + * _.fromPairs([['a', 1], ['b', 2]]); + * // => { 'a': 1, 'b': 2 } + */ + function fromPairs(pairs) { + var index = -1, + length = pairs ? pairs.length : 0, + result = {}; + + while (++index < length) { + var pair = pairs[index]; + result[pair[0]] = pair[1]; + } + return result; + } + + /** + * Gets the first element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias first + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the first element of `array`. + * @example + * + * _.head([1, 2, 3]); + * // => 1 + * + * _.head([]); + * // => undefined + */ + function head(array) { + return (array && array.length) ? array[0] : undefined; + } + + /** + * Gets the index at which the first occurrence of `value` is found in `array` + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the + * offset from the end of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // Search from the `fromIndex`. + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + */ + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseIndexOf(array, value, index); + } + + /** + * Gets all but the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.initial([1, 2, 3]); + * // => [1, 2] + */ + function initial(array) { + var length = array ? array.length : 0; + return length ? baseSlice(array, 0, -1) : []; + } + + /** + * Creates an array of unique values that are included in all given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersection([2, 1], [2, 3]); + * // => [2] + */ + var intersection = baseRest(function(arrays) { + var mapped = arrayMap(arrays, castArrayLikeObject); + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `iteratee` + * which is invoked for each element of each `arrays` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [2.1] + * + * // The `_.property` iteratee shorthand. + * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }] + */ + var intersectionBy = baseRest(function(arrays) { + var iteratee = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + if (iteratee === last(mapped)) { + iteratee = undefined; + } else { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `comparator` + * which is invoked to compare elements of `arrays`. The order and references + * of result values are determined by the first array. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.intersectionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }] + */ + var intersectionWith = baseRest(function(arrays) { + var comparator = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + if (comparator === last(mapped)) { + comparator = undefined; + } else { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, undefined, comparator) + : []; + }); + + /** + * Converts all elements in `array` into a string separated by `separator`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to convert. + * @param {string} [separator=','] The element separator. + * @returns {string} Returns the joined string. + * @example + * + * _.join(['a', 'b', 'c'], '~'); + * // => 'a~b~c' + */ + function join(array, separator) { + return array ? nativeJoin.call(array, separator) : ''; + } + + /** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + + /** + * This method is like `_.indexOf` except that it iterates over elements of + * `array` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.lastIndexOf([1, 2, 1, 2], 2); + * // => 3 + * + * // Search from the `fromIndex`. + * _.lastIndexOf([1, 2, 1, 2], 2, 2); + * // => 1 + */ + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); + } + return value === value + ? strictLastIndexOf(array, value, index) + : baseFindIndex(array, baseIsNaN, index, true); + } + + /** + * Gets the element at index `n` of `array`. If `n` is negative, the nth + * element from the end is returned. + * + * @static + * @memberOf _ + * @since 4.11.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=0] The index of the element to return. + * @returns {*} Returns the nth element of `array`. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * + * _.nth(array, 1); + * // => 'b' + * + * _.nth(array, -2); + * // => 'c'; + */ + function nth(array, n) { + return (array && array.length) ? baseNth(array, toInteger(n)) : undefined; + } + + /** + * Removes all given values from `array` using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` + * to remove elements from an array by predicate. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...*} [values] The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pull(array, 'a', 'c'); + * console.log(array); + * // => ['b', 'b'] + */ + var pull = baseRest(pullAll); + + /** + * This method is like `_.pull` except that it accepts an array of values to remove. + * + * **Note:** Unlike `_.difference`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pullAll(array, ['a', 'c']); + * console.log(array); + * // => ['b', 'b'] + */ + function pullAll(array, values) { + return (array && array.length && values && values.length) + ? basePullAll(array, values) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `iteratee` which is + * invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The iteratee is invoked with one argument: (value). + * + * **Note:** Unlike `_.differenceBy`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee=_.identity] + * The iteratee invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }]; + * + * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x'); + * console.log(array); + * // => [{ 'x': 2 }] + */ + function pullAllBy(array, values, iteratee) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, getIteratee(iteratee, 2)) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `comparator` which + * is invoked to compare elements of `array` to `values`. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.differenceWith`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }]; + * + * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual); + * console.log(array); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }] + */ + function pullAllWith(array, values, comparator) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, undefined, comparator) + : array; + } + + /** + * Removes elements from `array` corresponding to `indexes` and returns an + * array of removed elements. + * + * **Note:** Unlike `_.at`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...(number|number[])} [indexes] The indexes of elements to remove. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * var pulled = _.pullAt(array, [1, 3]); + * + * console.log(array); + * // => ['a', 'c'] + * + * console.log(pulled); + * // => ['b', 'd'] + */ + var pullAt = flatRest(function(array, indexes) { + var length = array ? array.length : 0, + result = baseAt(array, indexes); + + basePullAt(array, arrayMap(indexes, function(index) { + return isIndex(index, length) ? +index : index; + }).sort(compareAscending)); + + return result; + }); + + /** + * Removes all elements from `array` that `predicate` returns truthy for + * and returns an array of the removed elements. The predicate is invoked + * with three arguments: (value, index, array). + * + * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull` + * to pull elements from an array by value. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = [1, 2, 3, 4]; + * var evens = _.remove(array, function(n) { + * return n % 2 == 0; + * }); + * + * console.log(array); + * // => [1, 3] + * + * console.log(evens); + * // => [2, 4] + */ + function remove(array, predicate) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, + indexes = [], + length = array.length; + + predicate = getIteratee(predicate, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + + /** + * Reverses `array` so that the first element becomes the last, the second + * element becomes the second to last, and so on. + * + * **Note:** This method mutates `array` and is based on + * [`Array#reverse`](https://mdn.io/Array/reverse). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.reverse(array); + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function reverse(array) { + return array ? nativeReverse.call(array) : array; + } + + /** + * Creates a slice of `array` from `start` up to, but not including, `end`. + * + * **Note:** This method is used instead of + * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are + * returned. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + else { + start = start == null ? 0 : toInteger(start); + end = end === undefined ? length : toInteger(end); + } + return baseSlice(array, start, end); + } + + /** + * Uses a binary search to determine the lowest index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedIndex([30, 50], 40); + * // => 1 + */ + function sortedIndex(array, value) { + return baseSortedIndex(array, value); + } + + /** + * This method is like `_.sortedIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] + * The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.sortedIndexBy(objects, { 'x': 4 }, 'x'); + * // => 0 + */ + function sortedIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2)); + } + + /** + * This method is like `_.indexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedIndexOf([4, 5, 5, 5, 6], 5); + * // => 1 + */ + function sortedIndexOf(array, value) { + var length = array ? array.length : 0; + if (length) { + var index = baseSortedIndex(array, value); + if (index < length && eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.sortedIndex` except that it returns the highest + * index at which `value` should be inserted into `array` in order to + * maintain its sort order. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedLastIndex([4, 5, 5, 5, 6], 5); + * // => 4 + */ + function sortedLastIndex(array, value) { + return baseSortedIndex(array, value, true); + } + + /** + * This method is like `_.sortedLastIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] + * The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 1 + * + * // The `_.property` iteratee shorthand. + * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x'); + * // => 1 + */ + function sortedLastIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true); + } + + /** + * This method is like `_.lastIndexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5); + * // => 3 + */ + function sortedLastIndexOf(array, value) { + var length = array ? array.length : 0; + if (length) { + var index = baseSortedIndex(array, value, true) - 1; + if (eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.uniq` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniq([1, 1, 2]); + * // => [1, 2] + */ + function sortedUniq(array) { + return (array && array.length) + ? baseSortedUniq(array) + : []; + } + + /** + * This method is like `_.uniqBy` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor); + * // => [1.1, 2.3] + */ + function sortedUniqBy(array, iteratee) { + return (array && array.length) + ? baseSortedUniq(array, getIteratee(iteratee, 2)) + : []; + } + + /** + * Gets all but the first element of `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.tail([1, 2, 3]); + * // => [2, 3] + */ + function tail(array) { + var length = array ? array.length : 0; + return length ? baseSlice(array, 1, length) : []; + } + + /** + * Creates a slice of `array` with `n` elements taken from the beginning. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.take([1, 2, 3]); + * // => [1] + * + * _.take([1, 2, 3], 2); + * // => [1, 2] + * + * _.take([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.take([1, 2, 3], 0); + * // => [] + */ + function take(array, n, guard) { + if (!(array && array.length)) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` with `n` elements taken from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.takeRight([1, 2, 3]); + * // => [3] + * + * _.takeRight([1, 2, 3], 2); + * // => [2, 3] + * + * _.takeRight([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.takeRight([1, 2, 3], 0); + * // => [] + */ + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with elements taken from the end. Elements are + * taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.takeRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeRightWhile(users, ['active', false]); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.takeRightWhile(users, 'active'); + * // => [] + */ + function takeRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), false, true) + : []; + } + + /** + * Creates a slice of `array` with elements taken from the beginning. Elements + * are taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false}, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.takeWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matches` iteratee shorthand. + * _.takeWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeWhile(users, ['active', false]); + * // => objects for ['barney', 'fred'] + * + * // The `_.property` iteratee shorthand. + * _.takeWhile(users, 'active'); + * // => [] + */ + function takeWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3)) + : []; + } + + /** + * Creates an array of unique values, in order, from all given arrays using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.union([2], [1, 2]); + * // => [2, 1] + */ + var union = baseRest(function(arrays) { + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); + }); + + /** + * This method is like `_.union` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which uniqueness is computed. Result values are chosen from the first + * array in which the value occurs. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] + * The iteratee invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.unionBy([2.1], [1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + var unionBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.union` except that it accepts `comparator` which + * is invoked to compare elements of `arrays`. Result values are chosen from + * the first array in which the value occurs. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.unionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var unionWith = baseRest(function(arrays) { + var comparator = last(arrays); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator); + }); + + /** + * Creates a duplicate-free version of an array, using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons, in which only the first occurrence of each element + * is kept. The order of result values is determined by the order they occur + * in the array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniq([2, 1, 2]); + * // => [2, 1] + */ + function uniq(array) { + return (array && array.length) + ? baseUniq(array) + : []; + } + + /** + * This method is like `_.uniq` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the criterion by which + * uniqueness is computed. The order of result values is determined by the + * order they occur in the array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee=_.identity] + * The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniqBy([2.1, 1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + function uniqBy(array, iteratee) { + return (array && array.length) + ? baseUniq(array, getIteratee(iteratee, 2)) + : []; + } + + /** + * This method is like `_.uniq` except that it accepts `comparator` which + * is invoked to compare elements of `array`. The order of result values is + * determined by the order they occur in the array.The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.uniqWith(objects, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] + */ + function uniqWith(array, comparator) { + return (array && array.length) + ? baseUniq(array, undefined, comparator) + : []; + } + + /** + * This method is like `_.zip` except that it accepts an array of grouped + * elements and creates an array regrouping the elements to their pre-zip + * configuration. + * + * @static + * @memberOf _ + * @since 1.2.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + * + * _.unzip(zipped); + * // => [['a', 'b'], [1, 2], [true, false]] + */ + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLikeObject(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + return baseTimes(length, function(index) { + return arrayMap(array, baseProperty(index)); + }); + } + + /** + * This method is like `_.unzip` except that it accepts `iteratee` to specify + * how regrouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @param {Function} [iteratee=_.identity] The function to combine + * regrouped values. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip([1, 2], [10, 20], [100, 200]); + * // => [[1, 10, 100], [2, 20, 200]] + * + * _.unzipWith(zipped, _.add); + * // => [3, 30, 300] + */ + function unzipWith(array, iteratee) { + if (!(array && array.length)) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + return arrayMap(result, function(group) { + return apply(iteratee, undefined, group); + }); + } + + /** + * Creates an array excluding all given values using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.pull`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...*} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.xor + * @example + * + * _.without([2, 1, 2, 3], 1, 2); + * // => [3] + */ + var without = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, values) + : []; + }); + + /** + * Creates an array of unique values that is the + * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) + * of the given arrays. The order of result values is determined by the order + * they occur in the arrays. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.without + * @example + * + * _.xor([2, 1], [2, 3]); + * // => [1, 3] + */ + var xor = baseRest(function(arrays) { + return baseXor(arrayFilter(arrays, isArrayLikeObject)); + }); + + /** + * This method is like `_.xor` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which by which they're compared. The order of result values is determined + * by the order they occur in the arrays. The iteratee is invoked with one + * argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] + * The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2, 3.4] + * + * // The `_.property` iteratee shorthand. + * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var xorBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.xor` except that it accepts `comparator` which is + * invoked to compare elements of `arrays`. The order of result values is + * determined by the order they occur in the arrays. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.xorWith(objects, others, _.isEqual); + * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var xorWith = baseRest(function(arrays) { + var comparator = last(arrays); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator); + }); + + /** + * Creates an array of grouped elements, the first of which contains the + * first elements of the given arrays, the second of which contains the + * second elements of the given arrays, and so on. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + */ + var zip = baseRest(unzip); + + /** + * This method is like `_.fromPairs` except that it accepts two arrays, + * one of property identifiers and one of corresponding values. + * + * @static + * @memberOf _ + * @since 0.4.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObject(['a', 'b'], [1, 2]); + * // => { 'a': 1, 'b': 2 } + */ + function zipObject(props, values) { + return baseZipObject(props || [], values || [], assignValue); + } + + /** + * This method is like `_.zipObject` except that it supports property paths. + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]); + * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } } + */ + function zipObjectDeep(props, values) { + return baseZipObject(props || [], values || [], baseSet); + } + + /** + * This method is like `_.zip` except that it accepts `iteratee` to specify + * how grouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @param {Function} [iteratee=_.identity] The function to combine grouped values. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) { + * return a + b + c; + * }); + * // => [111, 222] + */ + var zipWith = baseRest(function(arrays) { + var length = arrays.length, + iteratee = length > 1 ? arrays[length - 1] : undefined; + + iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined; + return unzipWith(arrays, iteratee); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` wrapper instance that wraps `value` with explicit method + * chain sequences enabled. The result of such sequences must be unwrapped + * with `_#value`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Seq + * @param {*} value The value to wrap. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'pebbles', 'age': 1 } + * ]; + * + * var youngest = _ + * .chain(users) + * .sortBy('age') + * .map(function(o) { + * return o.user + ' is ' + o.age; + * }) + * .head() + * .value(); + * // => 'pebbles is 1' + */ + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + + /** + * This method invokes `interceptor` and returns `value`. The interceptor + * is invoked with one argument; (value). The purpose of this method is to + * "tap into" a method chain sequence in order to modify intermediate results. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns `value`. + * @example + * + * _([1, 2, 3]) + * .tap(function(array) { + * // Mutate input array. + * array.pop(); + * }) + * .reverse() + * .value(); + * // => [2, 1] + */ + function tap(value, interceptor) { + interceptor(value); + return value; + } + + /** + * This method is like `_.tap` except that it returns the result of `interceptor`. + * The purpose of this method is to "pass thru" values replacing intermediate + * results in a method chain sequence. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns the result of `interceptor`. + * @example + * + * _(' abc ') + * .chain() + * .trim() + * .thru(function(value) { + * return [value]; + * }) + * .value(); + * // => ['abc'] + */ + function thru(value, interceptor) { + return interceptor(value); + } + + /** + * This method is the wrapper version of `_.at`. + * + * @name at + * @memberOf _ + * @since 1.0.0 + * @category Seq + * @param {...(string|string[])} [paths] The property paths of elements to pick. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _(object).at(['a[0].b.c', 'a[1]']).value(); + * // => [3, 4] + */ + var wrapperAt = flatRest(function(paths) { + var length = paths.length, + start = length ? paths[0] : 0, + value = this.__wrapped__, + interceptor = function(object) { return baseAt(object, paths); }; + + if (length > 1 || this.__actions__.length || + !(value instanceof LazyWrapper) || !isIndex(start)) { + return this.thru(interceptor); + } + value = value.slice(start, +start + (length ? 1 : 0)); + value.__actions__.push({ + 'func': thru, + 'args': [interceptor], + 'thisArg': undefined + }); + return new LodashWrapper(value, this.__chain__).thru(function(array) { + if (length && !array.length) { + array.push(undefined); + } + return array; + }); + }); + + /** + * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. + * + * @name chain + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * // A sequence without explicit chaining. + * _(users).head(); + * // => { 'user': 'barney', 'age': 36 } + * + * // A sequence with explicit chaining. + * _(users) + * .chain() + * .head() + * .pick('user') + * .value(); + * // => { 'user': 'barney' } + */ + function wrapperChain() { + return chain(this); + } + + /** + * Executes the chain sequence and returns the wrapped result. + * + * @name commit + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapped = _(array).push(3); + * + * console.log(array); + * // => [1, 2] + * + * wrapped = wrapped.commit(); + * console.log(array); + * // => [1, 2, 3] + * + * wrapped.last(); + * // => 3 + * + * console.log(array); + * // => [1, 2, 3] + */ + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + + /** + * Gets the next value on a wrapped object following the + * [iterator protocol](https://mdn.io/iteration_protocols#iterator). + * + * @name next + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the next iterator value. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped.next(); + * // => { 'done': false, 'value': 1 } + * + * wrapped.next(); + * // => { 'done': false, 'value': 2 } + * + * wrapped.next(); + * // => { 'done': true, 'value': undefined } + */ + function wrapperNext() { + if (this.__values__ === undefined) { + this.__values__ = toArray(this.value()); + } + var done = this.__index__ >= this.__values__.length, + value = done ? undefined : this.__values__[this.__index__++]; + + return { 'done': done, 'value': value }; + } + + /** + * Enables the wrapper to be iterable. + * + * @name Symbol.iterator + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the wrapper object. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped[Symbol.iterator]() === wrapped; + * // => true + * + * Array.from(wrapped); + * // => [1, 2] + */ + function wrapperToIterator() { + return this; + } + + /** + * Creates a clone of the chain sequence planting `value` as the wrapped value. + * + * @name plant + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @param {*} value The value to plant. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2]).map(square); + * var other = wrapped.plant([3, 4]); + * + * other.value(); + * // => [9, 16] + * + * wrapped.value(); + * // => [1, 4] + */ + function wrapperPlant(value) { + var result, + parent = this; + + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + clone.__index__ = 0; + clone.__values__ = undefined; + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + + /** + * This method is the wrapper version of `_.reverse`. + * + * **Note:** This method mutates the wrapped array. + * + * @name reverse + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2, 3]; + * + * _(array).reverse().value() + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function wrapperReverse() { + var value = this.__wrapped__; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + 'func': thru, + 'args': [reverse], + 'thisArg': undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(reverse); + } + + /** + * Executes the chain sequence to resolve the unwrapped value. + * + * @name value + * @memberOf _ + * @since 0.1.0 + * @alias toJSON, valueOf + * @category Seq + * @returns {*} Returns the resolved unwrapped value. + * @example + * + * _([1, 2, 3]).value(); + * // => [1, 2, 3] + */ + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the number of times the key was returned by `iteratee`. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] + * The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.countBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': 1, '6': 2 } + * + * // The `_.property` iteratee shorthand. + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ + var countBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + ++result[key]; + } else { + baseAssignValue(result, key, 1); + } + }); + + /** + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * Iteration is stopped once `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.every(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.every(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.every(users, 'active'); + * // => false + */ + function every(collection, predicate, guard) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning an array of all elements + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * **Note:** Unlike `_.remove`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.reject + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * _.filter(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, { 'age': 36, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.filter(users, 'active'); + * // => objects for ['barney'] + */ + function filter(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.find(users, function(o) { return o.age < 40; }); + * // => object for 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.find(users, { 'age': 1, 'active': true }); + * // => object for 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.find(users, ['active', false]); + * // => object for 'fred' + * + * // The `_.property` iteratee shorthand. + * _.find(users, 'active'); + * // => object for 'barney' + */ + var find = createFind(findIndex); + + /** + * This method is like `_.find` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @param {number} [fromIndex=collection.length-1] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * _.findLast([1, 2, 3, 4], function(n) { + * return n % 2 == 1; + * }); + * // => 3 + */ + var findLast = createFind(findLastIndex); + + /** + * Creates a flattened array of values by running each element in `collection` + * thru `iteratee` and flattening the mapped results. The iteratee is invoked + * with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [n, n]; + * } + * + * _.flatMap([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMap(collection, iteratee) { + return baseFlatten(map(collection, iteratee), 1); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDeep([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMapDeep(collection, iteratee) { + return baseFlatten(map(collection, iteratee), INFINITY); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] + * The function invoked per iteration. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDepth([1, 2], duplicate, 2); + * // => [[1, 1], [2, 2]] + */ + function flatMapDepth(collection, iteratee, depth) { + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(map(collection, iteratee), depth); + } + + /** + * Iterates over elements of `collection` and invokes `iteratee` for each element. + * The iteratee is invoked with three arguments: (value, index|key, collection). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a "length" + * property are iterated like arrays. To avoid this behavior use `_.forIn` + * or `_.forOwn` for object iteration. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias each + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEachRight + * @example + * + * _.forEach([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `1` then `2`. + * + * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forEach(collection, iteratee) { + var func = isArray(collection) ? arrayEach : baseEach; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forEach` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @alias eachRight + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEach + * @example + * + * _.forEachRight([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `2` then `1`. + */ + function forEachRight(collection, iteratee) { + var func = isArray(collection) ? arrayEachRight : baseEachRight; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The order of grouped values + * is determined by the order they occur in `collection`. The corresponding + * value of each key is an array of elements responsible for generating the + * key. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] + * The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': [4.2], '6': [6.1, 6.3] } + * + * // The `_.property` iteratee shorthand. + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + baseAssignValue(result, key, [value]); + } + }); + + /** + * Checks if `value` is in `collection`. If `collection` is a string, it's + * checked for a substring of `value`, otherwise + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * is used for equality comparisons. If `fromIndex` is negative, it's used as + * the offset from the end of `collection`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {boolean} Returns `true` if `value` is found, else `false`. + * @example + * + * _.includes([1, 2, 3], 1); + * // => true + * + * _.includes([1, 2, 3], 1, 2); + * // => false + * + * _.includes({ 'a': 1, 'b': 2 }, 1); + * // => true + * + * _.includes('abcd', 'bc'); + * // => true + */ + function includes(collection, value, fromIndex, guard) { + collection = isArrayLike(collection) ? collection : values(collection); + fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0; + + var length = collection.length; + if (fromIndex < 0) { + fromIndex = nativeMax(length + fromIndex, 0); + } + return isString(collection) + ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1) + : (!!length && baseIndexOf(collection, value, fromIndex) > -1); + } + + /** + * Invokes the method at `path` of each element in `collection`, returning + * an array of the results of each invoked method. Any additional arguments + * are provided to each invoked method. If `path` is a function, it's invoked + * for, and `this` bound to, each element in `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array|Function|string} path The path of the method to invoke or + * the function invoked per iteration. + * @param {...*} [args] The arguments to invoke each method with. + * @returns {Array} Returns the array of results. + * @example + * + * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invokeMap([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ + var invokeMap = baseRest(function(collection, path, args) { + var index = -1, + isFunc = typeof path == 'function', + isProp = isKey(path), + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value) { + var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined); + result[++index] = func ? apply(func, value, args) : baseInvoke(value, path, args); + }); + return result; + }); + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the last element responsible for generating the key. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] + * The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * var array = [ + * { 'dir': 'left', 'code': 97 }, + * { 'dir': 'right', 'code': 100 } + * ]; + * + * _.keyBy(array, function(o) { + * return String.fromCharCode(o.code); + * }); + * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + * + * _.keyBy(array, 'dir'); + * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } + */ + var keyBy = createAggregator(function(result, value, key) { + baseAssignValue(result, key, value); + }); + + /** + * Creates an array of values by running each element in `collection` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, + * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, + * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, + * `template`, `trim`, `trimEnd`, `trimStart`, and `words` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + * @example + * + * function square(n) { + * return n * n; + * } + * + * _.map([4, 8], square); + * // => [16, 64] + * + * _.map({ 'a': 4, 'b': 8 }, square); + * // => [16, 64] (iteration order is not guaranteed) + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * // The `_.property` iteratee shorthand. + * _.map(users, 'user'); + * // => ['barney', 'fred'] + */ + function map(collection, iteratee) { + var func = isArray(collection) ? arrayMap : baseMap; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.sortBy` except that it allows specifying the sort + * orders of the iteratees to sort by. If `orders` is unspecified, all values + * are sorted in ascending order. Otherwise, specify an order of "desc" for + * descending or "asc" for ascending sort order of corresponding values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]] + * The iteratees to sort by. + * @param {string[]} [orders] The sort orders of `iteratees`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 34 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 36 } + * ]; + * + * // Sort by `user` in ascending order and by `age` in descending order. + * _.orderBy(users, ['user', 'age'], ['asc', 'desc']); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] + */ + function orderBy(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [iteratees]; + } + orders = guard ? undefined : orders; + if (!isArray(orders)) { + orders = orders == null ? [] : [orders]; + } + return baseOrderBy(collection, iteratees, orders); + } + + /** + * Creates an array of elements split into two groups, the first of which + * contains elements `predicate` returns truthy for, the second of which + * contains elements `predicate` returns falsey for. The predicate is + * invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the array of grouped elements. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true }, + * { 'user': 'pebbles', 'age': 1, 'active': false } + * ]; + * + * _.partition(users, function(o) { return o.active; }); + * // => objects for [['fred'], ['barney', 'pebbles']] + * + * // The `_.matches` iteratee shorthand. + * _.partition(users, { 'age': 1, 'active': false }); + * // => objects for [['pebbles'], ['barney', 'fred']] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.partition(users, ['active', false]); + * // => objects for [['barney', 'pebbles'], ['fred']] + * + * // The `_.property` iteratee shorthand. + * _.partition(users, 'active'); + * // => objects for [['fred'], ['barney', 'pebbles']] + */ + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { return [[], []]; }); + + /** + * Reduces `collection` to a value which is the accumulated result of running + * each element in `collection` thru `iteratee`, where each successive + * invocation is supplied the return value of the previous. If `accumulator` + * is not given, the first element of `collection` is used as the initial + * value. The iteratee is invoked with four arguments: + * (accumulator, value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.reduce`, `_.reduceRight`, and `_.transform`. + * + * The guarded methods are: + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, + * and `sortBy` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduceRight + * @example + * + * _.reduce([1, 2], function(sum, n) { + * return sum + n; + * }, 0); + * // => 3 + * + * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * return result; + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) + */ + function reduce(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduce : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach); + } + + /** + * This method is like `_.reduce` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduce + * @example + * + * var array = [[0, 1], [2, 3], [4, 5]]; + * + * _.reduceRight(array, function(flattened, other) { + * return flattened.concat(other); + * }, []); + * // => [4, 5, 2, 3, 0, 1] + */ + function reduceRight(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduceRight : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight); + } + + /** + * The opposite of `_.filter`; this method returns the elements of `collection` + * that `predicate` does **not** return truthy for. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.filter + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true } + * ]; + * + * _.reject(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.reject(users, { 'age': 40, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.reject(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.reject(users, 'active'); + * // => objects for ['barney'] + */ + function reject(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, negate(getIteratee(predicate, 3))); + } + + /** + * Gets a random element from `collection`. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + * @example + * + * _.sample([1, 2, 3, 4]); + * // => 2 + */ + function sample(collection) { + var func = isArray(collection) ? arraySample : baseSample; + return func(collection); + } + + /** + * Gets `n` random elements at unique keys from `collection` up to the + * size of `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @param {number} [n=1] The number of elements to sample. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the random elements. + * @example + * + * _.sampleSize([1, 2, 3], 2); + * // => [3, 1] + * + * _.sampleSize([1, 2, 3], 4); + * // => [2, 3, 1] + */ + function sampleSize(collection, n, guard) { + if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + var func = isArray(collection) ? arraySampleSize : baseSampleSize; + return func(collection, n); + } + + /** + * Creates an array of shuffled values, using a version of the + * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + * @example + * + * _.shuffle([1, 2, 3, 4]); + * // => [4, 1, 3, 2] + */ + function shuffle(collection) { + var func = isArray(collection) ? arrayShuffle : baseShuffle; + return func(collection); + } + + /** + * Gets the size of `collection` by returning its length for array-like + * values or the number of own enumerable string keyed properties for objects. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @returns {number} Returns the collection size. + * @example + * + * _.size([1, 2, 3]); + * // => 3 + * + * _.size({ 'a': 1, 'b': 2 }); + * // => 2 + * + * _.size('pebbles'); + * // => 7 + */ + function size(collection) { + if (collection == null) { + return 0; + } + if (isArrayLike(collection)) { + return isString(collection) ? stringSize(collection) : collection.length; + } + var tag = getTag(collection); + if (tag == mapTag || tag == setTag) { + return collection.size; + } + return baseKeys(collection).length; + } + + /** + * Checks if `predicate` returns truthy for **any** element of `collection`. + * Iteration is stopped once `predicate` returns truthy. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); + * // => true + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.some(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.some(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.some(users, 'active'); + * // => true + */ + function some(collection, predicate, guard) { + var func = isArray(collection) ? arraySome : baseSome; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Creates an array of elements, sorted in ascending order by the results of + * running each element in a collection thru each iteratee. This method + * performs a stable sort, that is, it preserves the original sort order of + * equal elements. The iteratees are invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {...(Function|Function[])} [iteratees=[_.identity]] + * The iteratees to sort by. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 34 } + * ]; + * + * _.sortBy(users, [function(o) { return o.user; }]); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] + * + * _.sortBy(users, ['user', 'age']); + * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] + */ + var sortBy = baseRest(function(collection, iteratees) { + if (collection == null) { + return []; + } + var length = iteratees.length; + if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { + iteratees = []; + } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { + iteratees = [iteratees[0]]; + } + return baseOrderBy(collection, baseFlatten(iteratees, 1), []); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Gets the timestamp of the number of milliseconds that have elapsed since + * the Unix epoch (1 January 1970 00:00:00 UTC). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Date + * @returns {number} Returns the timestamp. + * @example + * + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => Logs the number of milliseconds it took for the deferred invocation. + */ + var now = ctxNow || function() { + return root.Date.now(); + }; + + /*------------------------------------------------------------------------*/ + + /** + * The opposite of `_.before`; this method creates a function that invokes + * `func` once it's called `n` or more times. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {number} n The number of calls before `func` is invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var saves = ['profile', 'settings']; + * + * var done = _.after(saves.length, function() { + * console.log('done saving!'); + * }); + * + * _.forEach(saves, function(type) { + * asyncSave({ 'type': type, 'complete': done }); + * }); + * // => Logs 'done saving!' after the two async saves have completed. + */ + function after(n, func) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + + /** + * Creates a function that invokes `func`, with up to `n` arguments, + * ignoring any additional arguments. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @param {number} [n=func.length] The arity cap. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.ary(parseInt, 1)); + * // => [6, 8, 10] + */ + function ary(func, n, guard) { + n = guard ? undefined : n; + n = (func && n == null) ? func.length : n; + return createWrap(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + + /** + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it's called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * jQuery(element).on('click', _.before(5, addContactToList)); + * // => Allows adding up to 4 contacts to the list. + */ + function before(n, func) { + var result; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + + /** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and `partials` prepended to the arguments it receives. + * + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. + * + * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" + * property of bound functions. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * function greet(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * + * var object = { 'user': 'fred' }; + * + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * // Bound with placeholders. + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' + */ + var bind = baseRest(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bind)); + bitmask |= PARTIAL_FLAG; + } + return createWrap(func, bitmask, thisArg, partials, holders); + }); + + /** + * Creates a function that invokes the method at `object[key]` with `partials` + * prepended to the arguments it receives. + * + * This method differs from `_.bind` by allowing bound functions to reference + * methods that may be redefined or don't yet exist. See + * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern) + * for more details. + * + * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Function + * @param {Object} object The object to invoke the method on. + * @param {string} key The key of the method. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var object = { + * 'user': 'fred', + * 'greet': function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * }; + * + * var bound = _.bindKey(object, 'greet', 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * object.greet = function(greeting, punctuation) { + * return greeting + 'ya ' + this.user + punctuation; + * }; + * + * bound('!'); + * // => 'hiya fred!' + * + * // Bound with placeholders. + * var bound = _.bindKey(object, 'greet', _, '!'); + * bound('hi'); + * // => 'hiya fred!' + */ + var bindKey = baseRest(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bindKey)); + bitmask |= PARTIAL_FLAG; + } + return createWrap(key, bitmask, object, partials, holders); + }); + + /** + * Creates a function that accepts arguments of `func` and either invokes + * `func` returning its result, if at least `arity` number of arguments have + * been provided, or returns a function that accepts the remaining `func` + * arguments, and so on. The arity of `func` may be specified if `func.length` + * is not sufficient. + * + * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curry(abc); + * + * curried(1)(2)(3); + * // => [1, 2, 3] + * + * curried(1, 2)(3); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(1)(_, 3)(2); + * // => [1, 2, 3] + */ + function curry(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curry.placeholder; + return result; + } + + /** + * This method is like `_.curry` except that arguments are applied to `func` + * in the manner of `_.partialRight` instead of `_.partial`. + * + * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curryRight(abc); + * + * curried(3)(2)(1); + * // => [1, 2, 3] + * + * curried(2, 3)(1); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(3)(1, _)(2); + * // => [1, 2, 3] + */ + function curryRight(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryRight.placeholder; + return result; + } + + /** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed `func` invocations and a `flush` method to immediately invoke them. + * Provide `options` to indicate whether `func` should be invoked on the + * leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent + * calls to the debounced function return the result of the last `func` + * invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the debounced function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.debounce` and `_.throttle`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] The number of milliseconds to delay. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * // Avoid costly calculations while the window size is in flux. + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); + * + * // Invoke `sendMail` when clicked, debouncing subsequent calls. + * jQuery(element).on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); + * + * // Ensure `batchLog` is invoked once after 1 second of debounced calls. + * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); + * var source = new EventSource('/stream'); + * jQuery(source).on('message', debounced); + * + * // Cancel the trailing debounced invocation. + * jQuery(window).on('popstate', debounced.cancel); + */ + function debounce(func, wait, options) { + var lastArgs, + lastThis, + maxWait, + result, + timerId, + lastCallTime, + lastInvokeTime = 0, + leading = false, + maxing = false, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = toNumber(wait) || 0; + if (isObject(options)) { + leading = !!options.leading; + maxing = 'maxWait' in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + + function invokeFunc(time) { + var args = lastArgs, + thisArg = lastThis; + + lastArgs = lastThis = undefined; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time; + // Start the timer for the trailing edge. + timerId = setTimeout(timerExpired, wait); + // Invoke the leading edge. + return leading ? invokeFunc(time) : result; + } + + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime, + result = wait - timeSinceLastCall; + + return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result; + } + + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime; + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); + } + + function timerExpired() { + var time = now(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + // Restart the timer. + timerId = setTimeout(timerExpired, remainingWait(time)); + } + + function trailingEdge(time) { + timerId = undefined; + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = undefined; + return result; + } + + function cancel() { + if (timerId !== undefined) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined; + } + + function flush() { + return timerId === undefined ? result : trailingEdge(now()); + } + + function debounced() { + var time = now(), + isInvoking = shouldInvoke(time); + + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime); + } + if (maxing) { + // Handle invocations in a tight loop. + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === undefined) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; + } + + /** + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to defer. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.defer(function(text) { + * console.log(text); + * }, 'deferred'); + * // => Logs 'deferred' after one millisecond. + */ + var defer = baseRest(function(func, args) { + return baseDelay(func, 1, args); + }); + + /** + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.delay(function(text) { + * console.log(text); + * }, 1000, 'later'); + * // => Logs 'later' after one second. + */ + var delay = baseRest(function(func, wait, args) { + return baseDelay(func, toNumber(wait) || 0, args); + }); + + /** + * Creates a function that invokes `func` with arguments reversed. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to flip arguments for. + * @returns {Function} Returns the new flipped function. + * @example + * + * var flipped = _.flip(function() { + * return _.toArray(arguments); + * }); + * + * flipped('a', 'b', 'c', 'd'); + * // => ['d', 'c', 'b', 'a'] + */ + function flip(func) { + return createWrap(func, FLIP_FLAG); + } + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided, it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `delete`, `get`, `has`, and `set`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoized function. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; + * + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */ + function memoize(func, resolver) { + if (typeof func != 'function' || (resolver && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; + + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result) || cache; + return result; + }; + memoized.cache = new (memoize.Cache || MapCache); + return memoized; + } + + // Expose `MapCache`. + memoize.Cache = MapCache; + + /** + * Creates a function that negates the result of the predicate `func`. The + * `func` predicate is invoked with the `this` binding and arguments of the + * created function. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new negated function. + * @example + * + * function isEven(n) { + * return n % 2 == 0; + * } + * + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] + */ + function negate(predicate) { + if (typeof predicate != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var args = arguments; + switch (args.length) { + case 0: return !predicate.call(this); + case 1: return !predicate.call(this, args[0]); + case 2: return !predicate.call(this, args[0], args[1]); + case 3: return !predicate.call(this, args[0], args[1], args[2]); + } + return !predicate.apply(this, args); + }; + } + + /** + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first invocation. The `func` is + * invoked with the `this` binding and arguments of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // => `createApplication` is invoked once + */ + function once(func) { + return before(2, func); + } + + /** + * Creates a function that invokes `func` with its arguments transformed. + * + * @static + * @since 4.0.0 + * @memberOf _ + * @category Function + * @param {Function} func The function to wrap. + * @param {...(Function|Function[])} [transforms=[_.identity]] + * The argument transforms. + * @returns {Function} Returns the new function. + * @example + * + * function doubled(n) { + * return n * 2; + * } + * + * function square(n) { + * return n * n; + * } + * + * var func = _.overArgs(function(x, y) { + * return [x, y]; + * }, [square, doubled]); + * + * func(9, 3); + * // => [81, 6] + * + * func(10, 5); + * // => [100, 10] + */ + var overArgs = castRest(function(func, transforms) { + transforms = (transforms.length == 1 && isArray(transforms[0])) + ? arrayMap(transforms[0], baseUnary(getIteratee())) + : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee())); + + var funcsLength = transforms.length; + return baseRest(function(args) { + var index = -1, + length = nativeMin(args.length, funcsLength); + + while (++index < length) { + args[index] = transforms[index].call(this, args[index]); + } + return apply(func, this, args); + }); + }); + + /** + * Creates a function that invokes `func` with `partials` prepended to the + * arguments it receives. This method is like `_.bind` except it does **not** + * alter the `this` binding. + * + * The `_.partial.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 0.2.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var sayHelloTo = _.partial(greet, 'hello'); + * sayHelloTo('fred'); + * // => 'hello fred' + * + * // Partially applied with placeholders. + * var greetFred = _.partial(greet, _, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + */ + var partial = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partial)); + return createWrap(func, PARTIAL_FLAG, undefined, partials, holders); + }); + + /** + * This method is like `_.partial` except that partially applied arguments + * are appended to the arguments it receives. + * + * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var greetFred = _.partialRight(greet, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + * + * // Partially applied with placeholders. + * var sayHelloTo = _.partialRight(greet, 'hello', _); + * sayHelloTo('fred'); + * // => 'hello fred' + */ + var partialRight = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partialRight)); + return createWrap(func, PARTIAL_RIGHT_FLAG, undefined, partials, holders); + }); + + /** + * Creates a function that invokes `func` with arguments arranged according + * to the specified `indexes` where the argument value at the first index is + * provided as the first argument, the argument value at the second index is + * provided as the second argument, and so on. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to rearrange arguments for. + * @param {...(number|number[])} indexes The arranged argument indexes. + * @returns {Function} Returns the new function. + * @example + * + * var rearged = _.rearg(function(a, b, c) { + * return [a, b, c]; + * }, [2, 0, 1]); + * + * rearged('b', 'c', 'a') + * // => ['a', 'b', 'c'] + */ + var rearg = flatRest(function(func, indexes) { + return createWrap(func, REARG_FLAG, undefined, undefined, undefined, indexes); + }); + + /** + * Creates a function that invokes `func` with the `this` binding of the + * created function and arguments from `start` and beyond provided as + * an array. + * + * **Note:** This method is based on the + * [rest parameter](https://mdn.io/rest_parameters). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.rest(function(what, names) { + * return what + ' ' + _.initial(names).join(', ') + + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); + * }); + * + * say('hello', 'fred', 'barney', 'pebbles'); + * // => 'hello fred, barney, & pebbles' + */ + function rest(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start === undefined ? start : toInteger(start); + return baseRest(func, start); + } + + /** + * Creates a function that invokes `func` with the `this` binding of the + * create function and an array of arguments much like + * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply). + * + * **Note:** This method is based on the + * [spread operator](https://mdn.io/spread_operator). + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Function + * @param {Function} func The function to spread arguments over. + * @param {number} [start=0] The start position of the spread. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.spread(function(who, what) { + * return who + ' says ' + what; + * }); + * + * say(['fred', 'hello']); + * // => 'fred says hello' + * + * var numbers = Promise.all([ + * Promise.resolve(40), + * Promise.resolve(36) + * ]); + * + * numbers.then(_.spread(function(x, y) { + * return x + y; + * })); + * // => a Promise of 76 + */ + function spread(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start === undefined ? 0 : nativeMax(toInteger(start), 0); + return baseRest(function(args) { + var array = args[start], + otherArgs = castSlice(args, 0, start); + + if (array) { + arrayPush(otherArgs, array); + } + return apply(func, this, otherArgs); + }); + } + + /** + * Creates a throttled function that only invokes `func` at most once per + * every `wait` milliseconds. The throttled function comes with a `cancel` + * method to cancel delayed `func` invocations and a `flush` method to + * immediately invoke them. Provide `options` to indicate whether `func` + * should be invoked on the leading and/or trailing edge of the `wait` + * timeout. The `func` is invoked with the last arguments provided to the + * throttled function. Subsequent calls to the throttled function return the + * result of the last `func` invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the throttled function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.throttle` and `_.debounce`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to throttle. + * @param {number} [wait=0] The number of milliseconds to throttle invocations to. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=true] + * Specify invoking on the leading edge of the timeout. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new throttled function. + * @example + * + * // Avoid excessively updating the position while scrolling. + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); + * + * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); + * jQuery(element).on('click', throttled); + * + * // Cancel the trailing throttled invocation. + * jQuery(window).on('popstate', throttled.cancel); + */ + function throttle(func, wait, options) { + var leading = true, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (isObject(options)) { + leading = 'leading' in options ? !!options.leading : leading; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + 'leading': leading, + 'maxWait': wait, + 'trailing': trailing + }); + } + + /** + * Creates a function that accepts up to one argument, ignoring any + * additional arguments. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.unary(parseInt)); + * // => [6, 8, 10] + */ + function unary(func) { + return ary(func, 1); + } + + /** + * Creates a function that provides `value` to `wrapper` as its first + * argument. Any additional arguments provided to the function are appended + * to those provided to the `wrapper`. The wrapper is invoked with the `this` + * binding of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {*} value The value to wrap. + * @param {Function} [wrapper=identity] The wrapper function. + * @returns {Function} Returns the new function. + * @example + * + * var p = _.wrap(_.escape, function(func, text) { + * return '<p>' + func(text) + '</p>'; + * }); + * + * p('fred, barney, & pebbles'); + * // => '<p>fred, barney, & pebbles</p>' + */ + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return partial(wrapper, value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Casts `value` as an array if it's not one. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Lang + * @param {*} value The value to inspect. + * @returns {Array} Returns the cast array. + * @example + * + * _.castArray(1); + * // => [1] + * + * _.castArray({ 'a': 1 }); + * // => [{ 'a': 1 }] + * + * _.castArray('abc'); + * // => ['abc'] + * + * _.castArray(null); + * // => [null] + * + * _.castArray(undefined); + * // => [undefined] + * + * _.castArray(); + * // => [] + * + * var array = [1, 2, 3]; + * console.log(_.castArray(array) === array); + * // => true + */ + function castArray() { + if (!arguments.length) { + return []; + } + var value = arguments[0]; + return isArray(value) ? value : [value]; + } + + /** + * Creates a shallow clone of `value`. + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) + * and supports cloning arrays, array buffers, booleans, date objects, maps, + * numbers, `Object` objects, regexes, sets, strings, symbols, and typed + * arrays. The own enumerable properties of `arguments` objects are cloned + * as plain objects. An empty object is returned for uncloneable values such + * as error objects, functions, DOM nodes, and WeakMaps. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to clone. + * @returns {*} Returns the cloned value. + * @see _.cloneDeep + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var shallow = _.clone(objects); + * console.log(shallow[0] === objects[0]); + * // => true + */ + function clone(value) { + return baseClone(value, false, true); + } + + /** + * This method is like `_.clone` except that it accepts `customizer` which + * is invoked to produce the cloned value. If `customizer` returns `undefined`, + * cloning is handled by the method instead. The `customizer` is invoked with + * up to four arguments; (value [, index|key, object, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the cloned value. + * @see _.cloneDeepWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(false); + * } + * } + * + * var el = _.cloneWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 0 + */ + function cloneWith(value, customizer) { + return baseClone(value, false, true, customizer); + } + + /** + * This method is like `_.clone` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @returns {*} Returns the deep cloned value. + * @see _.clone + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var deep = _.cloneDeep(objects); + * console.log(deep[0] === objects[0]); + * // => false + */ + function cloneDeep(value) { + return baseClone(value, true, true); + } + + /** + * This method is like `_.cloneWith` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the deep cloned value. + * @see _.cloneWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(true); + * } + * } + * + * var el = _.cloneDeepWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 20 + */ + function cloneDeepWith(value, customizer) { + return baseClone(value, true, true, customizer); + } + + /** + * Checks if `object` conforms to `source` by invoking the predicate + * properties of `source` with the corresponding property values of `object`. + * + * **Note:** This method is equivalent to `_.conforms` when `source` is + * partially applied. + * + * @static + * @memberOf _ + * @since 4.14.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.conformsTo(object, { 'b': function(n) { return n > 1; } }); + * // => true + * + * _.conformsTo(object, { 'b': function(n) { return n > 2; } }); + * // => false + */ + function conformsTo(object, source) { + return source == null || baseConformsTo(object, source, keys(source)); + } + + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } + + /** + * Checks if `value` is greater than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + * @see _.lt + * @example + * + * _.gt(3, 1); + * // => true + * + * _.gt(3, 3); + * // => false + * + * _.gt(1, 3); + * // => false + */ + var gt = createRelationalOperation(baseGt); + + /** + * Checks if `value` is greater than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than or equal to + * `other`, else `false`. + * @see _.lte + * @example + * + * _.gte(3, 1); + * // => true + * + * _.gte(3, 3); + * // => true + * + * _.gte(1, 3); + * // => false + */ + var gte = createRelationalOperation(function(value, other) { + return value >= other; + }); + + /** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); + }; + + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; + + /** + * Checks if `value` is classified as an `ArrayBuffer` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + * @example + * + * _.isArrayBuffer(new ArrayBuffer(2)); + * // => true + * + * _.isArrayBuffer(new Array(2)); + * // => false + */ + var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer; + + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } + + /** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ + function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); + } + + /** + * Checks if `value` is classified as a boolean primitive or object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. + * @example + * + * _.isBoolean(false); + * // => true + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || + (isObjectLike(value) && objectToString.call(value) == boolTag); + } + + /** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ + var isBuffer = nativeIsBuffer || stubFalse; + + /** + * Checks if `value` is classified as a `Date` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + * + * _.isDate('Mon April 23 2012'); + * // => false + */ + var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; + + /** + * Checks if `value` is likely a DOM element. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. + * @example + * + * _.isElement(document.body); + * // => true + * + * _.isElement('<body>'); + * // => false + */ + function isElement(value) { + return value != null && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + + /** + * Checks if `value` is an empty object, collection, map, or set. + * + * Objects are considered empty if they have no own enumerable string keyed + * properties. + * + * Array-like values such as `arguments` objects, arrays, buffers, strings, or + * jQuery-like collections are considered empty if they have a `length` of `0`. + * Similarly, maps and sets are considered empty if they have a `size` of `0`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @example + * + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false + */ + function isEmpty(value) { + if (isArrayLike(value) && + (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || + isBuffer(value) || isTypedArray(value) || isArguments(value))) { + return !value.length; + } + var tag = getTag(value); + if (tag == mapTag || tag == setTag) { + return !value.size; + } + if (isPrototype(value)) { + return !baseKeys(value).length; + } + for (var key in value) { + if (hasOwnProperty.call(value, key)) { + return false; + } + } + return true; + } + + /** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are **not** supported. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ + function isEqual(value, other) { + return baseIsEqual(value, other); + } + + /** + * This method is like `_.isEqual` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with up to + * six arguments: (objValue, othValue [, index|key, object, other, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, othValue) { + * if (isGreeting(objValue) && isGreeting(othValue)) { + * return true; + * } + * } + * + * var array = ['hello', 'goodbye']; + * var other = ['hi', 'goodbye']; + * + * _.isEqualWith(array, other, customizer); + * // => true + */ + function isEqualWith(value, other, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + + /** + * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, + * `SyntaxError`, `TypeError`, or `URIError` object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an error object, else `false`. + * @example + * + * _.isError(new Error); + * // => true + * + * _.isError(Error); + * // => false + */ + function isError(value) { + if (!isObjectLike(value)) { + return false; + } + return (objectToString.call(value) == errorTag) || + (typeof value.message == 'string' && typeof value.name == 'string'); + } + + /** + * Checks if `value` is a finite primitive number. + * + * **Note:** This method is based on + * [`Number.isFinite`](https://mdn.io/Number/isFinite). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. + * @example + * + * _.isFinite(3); + * // => true + * + * _.isFinite(Number.MIN_VALUE); + * // => true + * + * _.isFinite(Infinity); + * // => false + * + * _.isFinite('3'); + * // => false + */ + function isFinite(value) { + return typeof value == 'number' && nativeIsFinite(value); + } + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed array and other constructors. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag || tag == proxyTag; + } + + /** + * Checks if `value` is an integer. + * + * **Note:** This method is based on + * [`Number.isInteger`](https://mdn.io/Number/isInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an integer, else `false`. + * @example + * + * _.isInteger(3); + * // => true + * + * _.isInteger(Number.MIN_VALUE); + * // => false + * + * _.isInteger(Infinity); + * // => false + * + * _.isInteger('3'); + * // => false + */ + function isInteger(value) { + return typeof value == 'number' && value == toInteger(value); + } + + /** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ + function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); + } + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return value != null && typeof value == 'object'; + } + + /** + * Checks if `value` is classified as a `Map` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + * @example + * + * _.isMap(new Map); + * // => true + * + * _.isMap(new WeakMap); + * // => false + */ + var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; + + /** + * Performs a partial deep comparison between `object` and `source` to + * determine if `object` contains equivalent property values. + * + * **Note:** This method is equivalent to `_.matches` when `source` is + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.isMatch(object, { 'b': 2 }); + * // => true + * + * _.isMatch(object, { 'b': 1 }); + * // => false + */ + function isMatch(object, source) { + return object === source || baseIsMatch(object, source, getMatchData(source)); + } + + /** + * This method is like `_.isMatch` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with five + * arguments: (objValue, srcValue, index|key, object, source). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, srcValue) { + * if (isGreeting(objValue) && isGreeting(srcValue)) { + * return true; + * } + * } + * + * var object = { 'greeting': 'hello' }; + * var source = { 'greeting': 'hi' }; + * + * _.isMatchWith(object, source, customizer); + * // => true + */ + function isMatchWith(object, source, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseIsMatch(object, source, getMatchData(source), customizer); + } + + /** + * Checks if `value` is `NaN`. + * + * **Note:** This method is based on + * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as + * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for + * `undefined` and other non-number values. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + function isNaN(value) { + // An `NaN` primitive is the only value that is not equal to itself. + // Perform the `toStringTag` check first to avoid errors with some + // ActiveX objects in IE. + return isNumber(value) && value != +value; + } + + /** + * Checks if `value` is a pristine native function. + * + * **Note:** This method can't reliably detect native functions in the presence + * of the core-js package because core-js circumvents this kind of detection. + * Despite multiple requests, the core-js maintainer has made it clear: any + * attempt to fix the detection will be obstructed. As a result, we're left + * with little choice but to throw an error. Unfortunately, this also affects + * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill), + * which rely on core-js. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + * @example + * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ + function isNative(value) { + if (isMaskable(value)) { + throw new Error(CORE_ERROR_TEXT); + } + return baseIsNative(value); + } + + /** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(void 0); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is `null` or `undefined`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is nullish, else `false`. + * @example + * + * _.isNil(null); + * // => true + * + * _.isNil(void 0); + * // => true + * + * _.isNil(NaN); + * // => false + */ + function isNil(value) { + return value == null; + } + + /** + * Checks if `value` is classified as a `Number` primitive or object. + * + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are + * classified as numbers, use the `_.isFinite` method. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a number, else `false`. + * @example + * + * _.isNumber(3); + * // => true + * + * _.isNumber(Number.MIN_VALUE); + * // => true + * + * _.isNumber(Infinity); + * // => true + * + * _.isNumber('3'); + * // => false + */ + function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && objectToString.call(value) == numberTag); + } + + /** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ + function isPlainObject(value) { + if (!isObjectLike(value) || objectToString.call(value) != objectTag) { + return false; + } + var proto = getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; + return (typeof Ctor == 'function' && + Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString); + } + + /** + * Checks if `value` is classified as a `RegExp` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + * @example + * + * _.isRegExp(/abc/); + * // => true + * + * _.isRegExp('/abc/'); + * // => false + */ + var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; + + /** + * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754 + * double precision number which isn't the result of a rounded unsafe integer. + * + * **Note:** This method is based on + * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. + * @example + * + * _.isSafeInteger(3); + * // => true + * + * _.isSafeInteger(Number.MIN_VALUE); + * // => false + * + * _.isSafeInteger(Infinity); + * // => false + * + * _.isSafeInteger('3'); + * // => false + */ + function isSafeInteger(value) { + return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is classified as a `Set` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + * @example + * + * _.isSet(new Set); + * // => true + * + * _.isSet(new WeakSet); + * // => false + */ + var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; + + /** + * Checks if `value` is classified as a `String` primitive or object. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. + * @example + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ + function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag); + } + + /** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ + function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); + } + + /** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ + var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + + /** + * Checks if `value` is `undefined`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false + */ + function isUndefined(value) { + return value === undefined; + } + + /** + * Checks if `value` is classified as a `WeakMap` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak map, else `false`. + * @example + * + * _.isWeakMap(new WeakMap); + * // => true + * + * _.isWeakMap(new Map); + * // => false + */ + function isWeakMap(value) { + return isObjectLike(value) && getTag(value) == weakMapTag; + } + + /** + * Checks if `value` is classified as a `WeakSet` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak set, else `false`. + * @example + * + * _.isWeakSet(new WeakSet); + * // => true + * + * _.isWeakSet(new Set); + * // => false + */ + function isWeakSet(value) { + return isObjectLike(value) && objectToString.call(value) == weakSetTag; + } + + /** + * Checks if `value` is less than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + * @see _.gt + * @example + * + * _.lt(1, 3); + * // => true + * + * _.lt(3, 3); + * // => false + * + * _.lt(3, 1); + * // => false + */ + var lt = createRelationalOperation(baseLt); + + /** + * Checks if `value` is less than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than or equal to + * `other`, else `false`. + * @see _.gte + * @example + * + * _.lte(1, 3); + * // => true + * + * _.lte(3, 3); + * // => true + * + * _.lte(3, 1); + * // => false + */ + var lte = createRelationalOperation(function(value, other) { + return value <= other; + }); + + /** + * Converts `value` to an array. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {Array} Returns the converted array. + * @example + * + * _.toArray({ 'a': 1, 'b': 2 }); + * // => [1, 2] + * + * _.toArray('abc'); + * // => ['a', 'b', 'c'] + * + * _.toArray(1); + * // => [] + * + * _.toArray(null); + * // => [] + */ + function toArray(value) { + if (!value) { + return []; + } + if (isArrayLike(value)) { + return isString(value) ? stringToArray(value) : copyArray(value); + } + if (iteratorSymbol && value[iteratorSymbol]) { + return iteratorToArray(value[iteratorSymbol]()); + } + var tag = getTag(value), + func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values); + + return func(value); + } + + /** + * Converts `value` to a finite number. + * + * @static + * @memberOf _ + * @since 4.12.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted number. + * @example + * + * _.toFinite(3.2); + * // => 3.2 + * + * _.toFinite(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toFinite(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toFinite('3.2'); + * // => 3.2 + */ + function toFinite(value) { + if (!value) { + return value === 0 ? value : 0; + } + value = toNumber(value); + if (value === INFINITY || value === -INFINITY) { + var sign = (value < 0 ? -1 : 1); + return sign * MAX_INTEGER; + } + return value === value ? value : 0; + } + + /** + * Converts `value` to an integer. + * + * **Note:** This method is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ + function toInteger(value) { + var result = toFinite(value), + remainder = result % 1; + + return result === result ? (remainder ? result - remainder : result) : 0; + } + + /** + * Converts `value` to an integer suitable for use as the length of an + * array-like object. + * + * **Note:** This method is based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toLength(3.2); + * // => 3 + * + * _.toLength(Number.MIN_VALUE); + * // => 0 + * + * _.toLength(Infinity); + * // => 4294967295 + * + * _.toLength('3.2'); + * // => 3 + */ + function toLength(value) { + return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0; + } + + /** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ + function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = value.replace(reTrim, ''); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); + } + + /** + * Converts `value` to a plain object flattening inherited enumerable string + * keyed properties of `value` to own properties of the plain object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {Object} Returns the converted plain object. + * @example + * + * function Foo() { + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.assign({ 'a': 1 }, new Foo); + * // => { 'a': 1, 'b': 2 } + * + * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); + * // => { 'a': 1, 'b': 2, 'c': 3 } + */ + function toPlainObject(value) { + return copyObject(value, keysIn(value)); + } + + /** + * Converts `value` to a safe integer. A safe integer can be compared and + * represented correctly. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toSafeInteger(3.2); + * // => 3 + * + * _.toSafeInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toSafeInteger(Infinity); + * // => 9007199254740991 + * + * _.toSafeInteger('3.2'); + * // => 3 + */ + function toSafeInteger(value) { + return baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER); + } + + /** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ + function toString(value) { + return value == null ? '' : baseToString(value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Assigns own enumerable string keyed properties of source objects to the + * destination object. Source objects are applied from left to right. + * Subsequent sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object` and is loosely based on + * [`Object.assign`](https://mdn.io/Object/assign). + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assignIn + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assign({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'c': 3 } + */ + var assign = createAssigner(function(object, source) { + if (isPrototype(source) || isArrayLike(source)) { + copyObject(source, keys(source), object); + return; + } + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + assignValue(object, key, source[key]); + } + } + }); + + /** + * This method is like `_.assign` except that it iterates over own and + * inherited source properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assign + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assignIn({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } + */ + var assignIn = createAssigner(function(object, source) { + copyObject(source, keysIn(source), object); + }); + + /** + * This method is like `_.assignIn` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extendWith + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignInWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keysIn(source), object, customizer); + }); + + /** + * This method is like `_.assign` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignInWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keys(source), object, customizer); + }); + + /** + * Creates an array of values corresponding to `paths` of `object`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {...(string|string[])} [paths] The property paths of elements to pick. + * @returns {Array} Returns the picked values. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _.at(object, ['a[0].b.c', 'a[1]']); + * // => [3, 4] + */ + var at = flatRest(baseAt); + + /** + * Creates an object that inherits from the `prototype` object. If a + * `properties` object is given, its own enumerable string keyed properties + * are assigned to the created object. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Object + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @returns {Object} Returns the new object. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { + * 'constructor': Circle + * }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true + */ + function create(prototype, properties) { + var result = baseCreate(prototype); + return properties ? baseAssign(result, properties) : result; + } + + /** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaultsDeep + * @example + * + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var defaults = baseRest(function(args) { + args.push(undefined, assignInDefaults); + return apply(assignInWith, undefined, args); + }); + + /** + * This method is like `_.defaults` except that it recursively assigns + * default properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaults + * @example + * + * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }); + * // => { 'a': { 'b': 2, 'c': 3 } } + */ + var defaultsDeep = baseRest(function(args) { + args.push(undefined, mergeDefaults); + return apply(mergeWith, undefined, args); + }); + + /** + * This method is like `_.find` except that it returns the key of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findKey(users, function(o) { return o.age < 40; }); + * // => 'barney' (iteration order is not guaranteed) + * + * // The `_.matches` iteratee shorthand. + * _.findKey(users, { 'age': 1, 'active': true }); + * // => 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findKey(users, 'active'); + * // => 'barney' + */ + function findKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwn); + } + + /** + * This method is like `_.findKey` except that it iterates over elements of + * a collection in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findLastKey(users, function(o) { return o.age < 40; }); + * // => returns 'pebbles' assuming `_.findKey` returns 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.findLastKey(users, { 'age': 36, 'active': true }); + * // => 'barney' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findLastKey(users, 'active'); + * // => 'pebbles' + */ + function findLastKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight); + } + + /** + * Iterates over own and inherited enumerable string keyed properties of an + * object and invokes `iteratee` for each property. The iteratee is invoked + * with three arguments: (value, key, object). Iteratee functions may exit + * iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forInRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forIn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed). + */ + function forIn(object, iteratee) { + return object == null + ? object + : baseFor(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * This method is like `_.forIn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forIn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forInRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'. + */ + function forInRight(object, iteratee) { + return object == null + ? object + : baseForRight(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * Iterates over own enumerable string keyed properties of an object and + * invokes `iteratee` for each property. The iteratee is invoked with three + * arguments: (value, key, object). Iteratee functions may exit iteration + * early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwnRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forOwn(object, iteratee) { + return object && baseForOwn(object, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forOwn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwnRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'. + */ + function forOwnRight(object, iteratee) { + return object && baseForOwnRight(object, getIteratee(iteratee, 3)); + } + + /** + * Creates an array of function property names from own enumerable properties + * of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functionsIn + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functions(new Foo); + * // => ['a', 'b'] + */ + function functions(object) { + return object == null ? [] : baseFunctions(object, keys(object)); + } + + /** + * Creates an array of function property names from own and inherited + * enumerable properties of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functions + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functionsIn(new Foo); + * // => ['a', 'b', 'c'] + */ + function functionsIn(object) { + return object == null ? [] : baseFunctions(object, keysIn(object)); + } + + /** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; + } + + /** + * Checks if `path` is a direct property of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = { 'a': { 'b': 2 } }; + * var other = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.has(object, 'a'); + * // => true + * + * _.has(object, 'a.b'); + * // => true + * + * _.has(object, ['a', 'b']); + * // => true + * + * _.has(other, 'a'); + * // => false + */ + function has(object, path) { + return object != null && hasPath(object, path, baseHas); + } + + /** + * Checks if `path` is a direct or inherited property of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.hasIn(object, 'a'); + * // => true + * + * _.hasIn(object, 'a.b'); + * // => true + * + * _.hasIn(object, ['a', 'b']); + * // => true + * + * _.hasIn(object, 'b'); + * // => false + */ + function hasIn(object, path) { + return object != null && hasPath(object, path, baseHasIn); + } + + /** + * Creates an object composed of the inverted keys and values of `object`. + * If `object` contains duplicate values, subsequent values overwrite + * property assignments of previous values. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Object + * @param {Object} object The object to invert. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invert(object); + * // => { '1': 'c', '2': 'b' } + */ + var invert = createInverter(function(result, value, key) { + result[value] = key; + }, constant(identity)); + + /** + * This method is like `_.invert` except that the inverted object is generated + * from the results of running each element of `object` thru `iteratee`. The + * corresponding inverted value of each inverted key is an array of keys + * responsible for generating the inverted value. The iteratee is invoked + * with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Object + * @param {Object} object The object to invert. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invertBy(object); + * // => { '1': ['a', 'c'], '2': ['b'] } + * + * _.invertBy(object, function(value) { + * return 'group' + value; + * }); + * // => { 'group1': ['a', 'c'], 'group2': ['b'] } + */ + var invertBy = createInverter(function(result, value, key) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [key]; + } + }, getIteratee); + + /** + * Invokes the method at `path` of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {...*} [args] The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + * @example + * + * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] }; + * + * _.invoke(object, 'a[0].b.c.slice', 1, 3); + * // => [2, 3] + */ + var invoke = baseRest(baseInvoke); + + /** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ + function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); + } + + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ + function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); + } + + /** + * The opposite of `_.mapValues`; this method creates an object with the + * same values as `object` and keys generated by running each own enumerable + * string keyed property of `object` thru `iteratee`. The iteratee is invoked + * with three arguments: (value, key, object). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapValues + * @example + * + * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { + * return key + value; + * }); + * // => { 'a1': 1, 'b2': 2 } + */ + function mapKeys(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, iteratee(value, key, object), value); + }); + return result; + } + + /** + * Creates an object with the same keys as `object` and values generated + * by running each own enumerable string keyed property of `object` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, key, object). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapKeys + * @example + * + * var users = { + * 'fred': { 'user': 'fred', 'age': 40 }, + * 'pebbles': { 'user': 'pebbles', 'age': 1 } + * }; + * + * _.mapValues(users, function(o) { return o.age; }); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + * + * // The `_.property` iteratee shorthand. + * _.mapValues(users, 'age'); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + */ + function mapValues(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, key, iteratee(value, key, object)); + }); + return result; + } + + /** + * This method is like `_.assign` except that it recursively merges own and + * inherited enumerable string keyed properties of source objects into the + * destination object. Source properties that resolve to `undefined` are + * skipped if a destination value exists. Array and plain object properties + * are merged recursively. Other objects and value types are overridden by + * assignment. Source objects are applied from left to right. Subsequent + * sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * var object = { + * 'a': [{ 'b': 2 }, { 'd': 4 }] + * }; + * + * var other = { + * 'a': [{ 'c': 3 }, { 'e': 5 }] + * }; + * + * _.merge(object, other); + * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } + */ + var merge = createAssigner(function(object, source, srcIndex) { + baseMerge(object, source, srcIndex); + }); + + /** + * This method is like `_.merge` except that it accepts `customizer` which + * is invoked to produce the merged values of the destination and source + * properties. If `customizer` returns `undefined`, merging is handled by the + * method instead. The `customizer` is invoked with six arguments: + * (objValue, srcValue, key, object, source, stack). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} customizer The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * function customizer(objValue, srcValue) { + * if (_.isArray(objValue)) { + * return objValue.concat(srcValue); + * } + * } + * + * var object = { 'a': [1], 'b': [2] }; + * var other = { 'a': [3], 'b': [4] }; + * + * _.mergeWith(object, other, customizer); + * // => { 'a': [1, 3], 'b': [2, 4] } + */ + var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { + baseMerge(object, source, srcIndex, customizer); + }); + + /** + * The opposite of `_.pick`; this method creates an object composed of the + * own and inherited enumerable string keyed properties of `object` that are + * not omitted. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [props] The property identifiers to omit. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omit(object, ['a', 'c']); + * // => { 'b': '2' } + */ + var omit = flatRest(function(object, props) { + if (object == null) { + return {}; + } + props = arrayMap(props, toKey); + return basePick(object, baseDifference(getAllKeysIn(object), props)); + }); + + /** + * The opposite of `_.pickBy`; this method creates an object composed of + * the own and inherited enumerable string keyed properties of `object` that + * `predicate` doesn't return truthy for. The predicate is invoked with two + * arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omitBy(object, _.isNumber); + * // => { 'b': '2' } + */ + function omitBy(object, predicate) { + return pickBy(object, negate(getIteratee(predicate))); + } + + /** + * Creates an object composed of the picked `object` properties. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [props] The property identifiers to pick. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pick(object, ['a', 'c']); + * // => { 'a': 1, 'c': 3 } + */ + var pick = flatRest(function(object, props) { + return object == null ? {} : basePick(object, arrayMap(props, toKey)); + }); + + /** + * Creates an object composed of the `object` properties `predicate` returns + * truthy for. The predicate is invoked with two arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pickBy(object, _.isNumber); + * // => { 'a': 1, 'c': 3 } + */ + function pickBy(object, predicate) { + return object == null ? {} : basePickBy(object, getAllKeysIn(object), getIteratee(predicate)); + } + + /** + * This method is like `_.get` except that if the resolved value is a + * function it's invoked with the `this` binding of its parent object and + * its result is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to resolve. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; + * + * _.result(object, 'a[0].b.c1'); + * // => 3 + * + * _.result(object, 'a[0].b.c2'); + * // => 4 + * + * _.result(object, 'a[0].b.c3', 'default'); + * // => 'default' + * + * _.result(object, 'a[0].b.c3', _.constant('default')); + * // => 'default' + */ + function result(object, path, defaultValue) { + path = isKey(path, object) ? [path] : castPath(path); + + var index = -1, + length = path.length; + + // Ensure the loop is entered when path is empty. + if (!length) { + object = undefined; + length = 1; + } + while (++index < length) { + var value = object == null ? undefined : object[toKey(path[index])]; + if (value === undefined) { + index = length; + value = defaultValue; + } + object = isFunction(value) ? value.call(object) : value; + } + return object; + } + + /** + * Sets the value at `path` of `object`. If a portion of `path` doesn't exist, + * it's created. Arrays are created for missing index properties while objects + * are created for all other missing properties. Use `_.setWith` to customize + * `path` creation. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.set(object, 'a[0].b.c', 4); + * console.log(object.a[0].b.c); + * // => 4 + * + * _.set(object, ['x', '0', 'y', 'z'], 5); + * console.log(object.x[0].y.z); + * // => 5 + */ + function set(object, path, value) { + return object == null ? object : baseSet(object, path, value); + } + + /** + * This method is like `_.set` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.setWith(object, '[0][1]', 'a', Object); + * // => { '0': { '1': 'a' } } + */ + function setWith(object, path, value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseSet(object, path, value, customizer); + } + + /** + * Creates an array of own enumerable string keyed-value pairs for `object` + * which can be consumed by `_.fromPairs`. If `object` is a map or set, its + * entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entries + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairs(new Foo); + * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) + */ + var toPairs = createToPairs(keys); + + /** + * Creates an array of own and inherited enumerable string keyed-value pairs + * for `object` which can be consumed by `_.fromPairs`. If `object` is a map + * or set, its entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entriesIn + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairsIn(new Foo); + * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed) + */ + var toPairsIn = createToPairs(keysIn); + + /** + * An alternative to `_.reduce`; this method transforms `object` to a new + * `accumulator` object which is the result of running each of its own + * enumerable string keyed properties thru `iteratee`, with each invocation + * potentially mutating the `accumulator` object. If `accumulator` is not + * provided, a new object with the same `[[Prototype]]` will be used. The + * iteratee is invoked with four arguments: (accumulator, value, key, object). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The custom accumulator value. + * @returns {*} Returns the accumulated value. + * @example + * + * _.transform([2, 3, 4], function(result, n) { + * result.push(n *= n); + * return n % 2 == 0; + * }, []); + * // => [4, 9] + * + * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } + */ + function transform(object, iteratee, accumulator) { + var isArr = isArray(object), + isArrLike = isArr || isBuffer(object) || isTypedArray(object); + + iteratee = getIteratee(iteratee, 4); + if (accumulator == null) { + var Ctor = object && object.constructor; + if (isArrLike) { + accumulator = isArr ? new Ctor : []; + } + else if (isObject(object)) { + accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {}; + } + else { + accumulator = {}; + } + } + (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + + /** + * Removes the property at `path` of `object`. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 7 } }] }; + * _.unset(object, 'a[0].b.c'); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + * + * _.unset(object, ['a', '0', 'b', 'c']); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + */ + function unset(object, path) { + return object == null ? true : baseUnset(object, path); + } + + /** + * This method is like `_.set` except that accepts `updater` to produce the + * value to set. Use `_.updateWith` to customize `path` creation. The `updater` + * is invoked with one argument: (value). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.update(object, 'a[0].b.c', function(n) { return n * n; }); + * console.log(object.a[0].b.c); + * // => 9 + * + * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; }); + * console.log(object.x[0].y.z); + * // => 0 + */ + function update(object, path, updater) { + return object == null ? object : baseUpdate(object, path, castFunction(updater)); + } + + /** + * This method is like `_.update` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.updateWith(object, '[0][1]', _.constant('a'), Object); + * // => { '0': { '1': 'a' } } + */ + function updateWith(object, path, updater, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer); + } + + /** + * Creates an array of the own enumerable string keyed property values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] + */ + function values(object) { + return object ? baseValues(object, keys(object)) : []; + } + + /** + * Creates an array of the own and inherited enumerable string keyed property + * values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.valuesIn(new Foo); + * // => [1, 2, 3] (iteration order is not guaranteed) + */ + function valuesIn(object) { + return object == null ? [] : baseValues(object, keysIn(object)); + } + + /*------------------------------------------------------------------------*/ + + /** + * Clamps `number` within the inclusive `lower` and `upper` bounds. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Number + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + * @example + * + * _.clamp(-10, -5, 5); + * // => -5 + * + * _.clamp(10, -5, 5); + * // => 5 + */ + function clamp(number, lower, upper) { + if (upper === undefined) { + upper = lower; + lower = undefined; + } + if (upper !== undefined) { + upper = toNumber(upper); + upper = upper === upper ? upper : 0; + } + if (lower !== undefined) { + lower = toNumber(lower); + lower = lower === lower ? lower : 0; + } + return baseClamp(toNumber(number), lower, upper); + } + + /** + * Checks if `n` is between `start` and up to, but not including, `end`. If + * `end` is not specified, it's set to `start` with `start` then set to `0`. + * If `start` is greater than `end` the params are swapped to support + * negative ranges. + * + * @static + * @memberOf _ + * @since 3.3.0 + * @category Number + * @param {number} number The number to check. + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + * @see _.range, _.rangeRight + * @example + * + * _.inRange(3, 2, 4); + * // => true + * + * _.inRange(4, 8); + * // => true + * + * _.inRange(4, 2); + * // => false + * + * _.inRange(2, 2); + * // => false + * + * _.inRange(1.2, 2); + * // => true + * + * _.inRange(5.2, 4); + * // => false + * + * _.inRange(-3, -2, -6); + * // => true + */ + function inRange(number, start, end) { + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + number = toNumber(number); + return baseInRange(number, start, end); + } + + /** + * Produces a random number between the inclusive `lower` and `upper` bounds. + * If only one argument is provided a number between `0` and the given number + * is returned. If `floating` is `true`, or either `lower` or `upper` are + * floats, a floating-point number is returned instead of an integer. + * + * **Note:** JavaScript follows the IEEE-754 standard for resolving + * floating-point values which can produce unexpected results. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Number + * @param {number} [lower=0] The lower bound. + * @param {number} [upper=1] The upper bound. + * @param {boolean} [floating] Specify returning a floating-point number. + * @returns {number} Returns the random number. + * @example + * + * _.random(0, 5); + * // => an integer between 0 and 5 + * + * _.random(5); + * // => also an integer between 0 and 5 + * + * _.random(5, true); + * // => a floating-point number between 0 and 5 + * + * _.random(1.2, 5.2); + * // => a floating-point number between 1.2 and 5.2 + */ + function random(lower, upper, floating) { + if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) { + upper = floating = undefined; + } + if (floating === undefined) { + if (typeof upper == 'boolean') { + floating = upper; + upper = undefined; + } + else if (typeof lower == 'boolean') { + floating = lower; + lower = undefined; + } + } + if (lower === undefined && upper === undefined) { + lower = 0; + upper = 1; + } + else { + lower = toFinite(lower); + if (upper === undefined) { + upper = lower; + lower = 0; + } else { + upper = toFinite(upper); + } + } + if (lower > upper) { + var temp = lower; + lower = upper; + upper = temp; + } + if (floating || lower % 1 || upper % 1) { + var rand = nativeRandom(); + return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper); + } + return baseRandom(lower, upper); + } + + /*------------------------------------------------------------------------*/ + + /** + * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the camel cased string. + * @example + * + * _.camelCase('Foo Bar'); + * // => 'fooBar' + * + * _.camelCase('--foo-bar--'); + * // => 'fooBar' + * + * _.camelCase('__FOO_BAR__'); + * // => 'fooBar' + */ + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? capitalize(word) : word); + }); + + /** + * Converts the first character of `string` to upper case and the remaining + * to lower case. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to capitalize. + * @returns {string} Returns the capitalized string. + * @example + * + * _.capitalize('FRED'); + * // => 'Fred' + */ + function capitalize(string) { + return upperFirst(toString(string).toLowerCase()); + } + + /** + * Deburrs `string` by converting + * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) + * letters to basic Latin letters and removing + * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to deburr. + * @returns {string} Returns the deburred string. + * @example + * + * _.deburr('déjà vu'); + * // => 'deja vu' + */ + function deburr(string) { + string = toString(string); + return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); + } + + /** + * Checks if `string` ends with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=string.length] The position to search up to. + * @returns {boolean} Returns `true` if `string` ends with `target`, + * else `false`. + * @example + * + * _.endsWith('abc', 'c'); + * // => true + * + * _.endsWith('abc', 'b'); + * // => false + * + * _.endsWith('abc', 'b', 2); + * // => true + */ + function endsWith(string, target, position) { + string = toString(string); + target = baseToString(target); + + var length = string.length; + position = position === undefined + ? length + : baseClamp(toInteger(position), 0, length); + + var end = position; + position -= target.length; + return position >= 0 && string.slice(position, end) == target; + } + + /** + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional + * characters use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't need escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. See + * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * When working with HTML you should always + * [quote attribute values](http://wonko.com/post/html-escaping) to reduce + * XSS vectors. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ + function escape(string) { + string = toString(string); + return (string && reHasUnescapedHtml.test(string)) + ? string.replace(reUnescapedHtml, escapeHtmlChar) + : string; + } + + /** + * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+", + * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escapeRegExp('[lodash](https://lodash.com/)'); + * // => '\[lodash\]\(https://lodash\.com/\)' + */ + function escapeRegExp(string) { + string = toString(string); + return (string && reHasRegExpChar.test(string)) + ? string.replace(reRegExpChar, '\\$&') + : string; + } + + /** + * Converts `string` to + * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the kebab cased string. + * @example + * + * _.kebabCase('Foo Bar'); + * // => 'foo-bar' + * + * _.kebabCase('fooBar'); + * // => 'foo-bar' + * + * _.kebabCase('__FOO_BAR__'); + * // => 'foo-bar' + */ + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? '-' : '') + word.toLowerCase(); + }); + + /** + * Converts `string`, as space separated words, to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the lower cased string. + * @example + * + * _.lowerCase('--Foo-Bar--'); + * // => 'foo bar' + * + * _.lowerCase('fooBar'); + * // => 'foo bar' + * + * _.lowerCase('__FOO_BAR__'); + * // => 'foo bar' + */ + var lowerCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + word.toLowerCase(); + }); + + /** + * Converts the first character of `string` to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.lowerFirst('Fred'); + * // => 'fred' + * + * _.lowerFirst('FRED'); + * // => 'fRED' + */ + var lowerFirst = createCaseFirst('toLowerCase'); + + /** + * Pads `string` on the left and right sides if it's shorter than `length`. + * Padding characters are truncated if they can't be evenly divided by `length`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.pad('abc', 8); + * // => ' abc ' + * + * _.pad('abc', 8, '_-'); + * // => '_-abc_-_' + * + * _.pad('abc', 3); + * // => 'abc' + */ + function pad(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + if (!length || strLength >= length) { + return string; + } + var mid = (length - strLength) / 2; + return ( + createPadding(nativeFloor(mid), chars) + + string + + createPadding(nativeCeil(mid), chars) + ); + } + + /** + * Pads `string` on the right side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padEnd('abc', 6); + * // => 'abc ' + * + * _.padEnd('abc', 6, '_-'); + * // => 'abc_-_' + * + * _.padEnd('abc', 3); + * // => 'abc' + */ + function padEnd(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (string + createPadding(length - strLength, chars)) + : string; + } + + /** + * Pads `string` on the left side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padStart('abc', 6); + * // => ' abc' + * + * _.padStart('abc', 6, '_-'); + * // => '_-_abc' + * + * _.padStart('abc', 3); + * // => 'abc' + */ + function padStart(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (createPadding(length - strLength, chars) + string) + : string; + } + + /** + * Converts `string` to an integer of the specified radix. If `radix` is + * `undefined` or `0`, a `radix` of `10` is used unless `value` is a + * hexadecimal, in which case a `radix` of `16` is used. + * + * **Note:** This method aligns with the + * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category String + * @param {string} string The string to convert. + * @param {number} [radix=10] The radix to interpret `value` by. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {number} Returns the converted integer. + * @example + * + * _.parseInt('08'); + * // => 8 + * + * _.map(['6', '08', '10'], _.parseInt); + * // => [6, 8, 10] + */ + function parseInt(string, radix, guard) { + if (guard || radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0); + } + + /** + * Repeats the given string `n` times. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to repeat. + * @param {number} [n=1] The number of times to repeat the string. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {string} Returns the repeated string. + * @example + * + * _.repeat('*', 3); + * // => '***' + * + * _.repeat('abc', 2); + * // => 'abcabc' + * + * _.repeat('abc', 0); + * // => '' + */ + function repeat(string, n, guard) { + if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + return baseRepeat(toString(string), n); + } + + /** + * Replaces matches for `pattern` in `string` with `replacement`. + * + * **Note:** This method is based on + * [`String#replace`](https://mdn.io/String/replace). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to modify. + * @param {RegExp|string} pattern The pattern to replace. + * @param {Function|string} replacement The match replacement. + * @returns {string} Returns the modified string. + * @example + * + * _.replace('Hi Fred', 'Fred', 'Barney'); + * // => 'Hi Barney' + */ + function replace() { + var args = arguments, + string = toString(args[0]); + + return args.length < 3 ? string : string.replace(args[1], args[2]); + } + + /** + * Converts `string` to + * [snake case](https://en.wikipedia.org/wiki/Snake_case). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the snake cased string. + * @example + * + * _.snakeCase('Foo Bar'); + * // => 'foo_bar' + * + * _.snakeCase('fooBar'); + * // => 'foo_bar' + * + * _.snakeCase('--FOO-BAR--'); + * // => 'foo_bar' + */ + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? '_' : '') + word.toLowerCase(); + }); + + /** + * Splits `string` by `separator`. + * + * **Note:** This method is based on + * [`String#split`](https://mdn.io/String/split). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to split. + * @param {RegExp|string} separator The separator pattern to split by. + * @param {number} [limit] The length to truncate results to. + * @returns {Array} Returns the string segments. + * @example + * + * _.split('a-b-c', '-', 2); + * // => ['a', 'b'] + */ + function split(string, separator, limit) { + if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) { + separator = limit = undefined; + } + limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0; + if (!limit) { + return []; + } + string = toString(string); + if (string && ( + typeof separator == 'string' || + (separator != null && !isRegExp(separator)) + )) { + separator = baseToString(separator); + if (!separator && hasUnicode(string)) { + return castSlice(stringToArray(string), 0, limit); + } + } + return string.split(separator, limit); + } + + /** + * Converts `string` to + * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). + * + * @static + * @memberOf _ + * @since 3.1.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the start cased string. + * @example + * + * _.startCase('--foo-bar--'); + * // => 'Foo Bar' + * + * _.startCase('fooBar'); + * // => 'Foo Bar' + * + * _.startCase('__FOO_BAR__'); + * // => 'FOO BAR' + */ + var startCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + upperFirst(word); + }); + + /** + * Checks if `string` starts with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=0] The position to search from. + * @returns {boolean} Returns `true` if `string` starts with `target`, + * else `false`. + * @example + * + * _.startsWith('abc', 'a'); + * // => true + * + * _.startsWith('abc', 'b'); + * // => false + * + * _.startsWith('abc', 'b', 1); + * // => true + */ + function startsWith(string, target, position) { + string = toString(string); + position = baseClamp(toInteger(position), 0, string.length); + target = baseToString(target); + return string.slice(position, position + target.length) == target; + } + + /** + * Creates a compiled template function that can interpolate data properties + * in "interpolate" delimiters, HTML-escape interpolated data properties in + * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data + * properties may be accessed as free variables in the template. If a setting + * object is given, it takes precedence over `_.templateSettings` values. + * + * **Note:** In the development build `_.template` utilizes + * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * for easier debugging. + * + * For more information on precompiling templates see + * [lodash's custom builds documentation](https://lodash.com/custom-builds). + * + * For more information on Chrome extension sandboxes see + * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The template string. + * @param {Object} [options={}] The options object. + * @param {RegExp} [options.escape=_.templateSettings.escape] + * The HTML "escape" delimiter. + * @param {RegExp} [options.evaluate=_.templateSettings.evaluate] + * The "evaluate" delimiter. + * @param {Object} [options.imports=_.templateSettings.imports] + * An object to import into the template as free variables. + * @param {RegExp} [options.interpolate=_.templateSettings.interpolate] + * The "interpolate" delimiter. + * @param {string} [options.sourceURL='lodash.templateSources[n]'] + * The sourceURL of the compiled template. + * @param {string} [options.variable='obj'] + * The data object variable name. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the compiled template function. + * @example + * + * // Use the "interpolate" delimiter to create a compiled template. + * var compiled = _.template('hello <%= user %>!'); + * compiled({ 'user': 'fred' }); + * // => 'hello fred!' + * + * // Use the HTML "escape" delimiter to escape data property values. + * var compiled = _.template('<b><%- value %></b>'); + * compiled({ 'value': '<script>' }); + * // => '<b><script></b>' + * + * // Use the "evaluate" delimiter to execute JavaScript and generate HTML. + * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>'); + * compiled({ 'users': ['fred', 'barney'] }); + * // => '<li>fred</li><li>barney</li>' + * + * // Use the internal `print` function in "evaluate" delimiters. + * var compiled = _.template('<% print("hello " + user); %>!'); + * compiled({ 'user': 'barney' }); + * // => 'hello barney!' + * + * // Use the ES template literal delimiter as an "interpolate" delimiter. + * // Disable support by replacing the "interpolate" delimiter. + * var compiled = _.template('hello ${ user }!'); + * compiled({ 'user': 'pebbles' }); + * // => 'hello pebbles!' + * + * // Use backslashes to treat delimiters as plain text. + * var compiled = _.template('<%= "\\<%- value %\\>" %>'); + * compiled({ 'value': 'ignored' }); + * // => '<%- value %>' + * + * // Use the `imports` option to import `jQuery` as `jq`. + * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>'; + * var compiled = _.template(text, { 'imports': { 'jq': jQuery } }); + * compiled({ 'users': ['fred', 'barney'] }); + * // => '<li>fred</li><li>barney</li>' + * + * // Use the `sourceURL` option to specify a custom sourceURL for the template. + * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' }); + * compiled(data); + * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector. + * + * // Use the `variable` option to ensure a with-statement isn't used in the compiled template. + * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' }); + * compiled.source; + * // => function(data) { + * // var __t, __p = ''; + * // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!'; + * // return __p; + * // } + * + * // Use custom template delimiters. + * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g; + * var compiled = _.template('hello {{ user }}!'); + * compiled({ 'user': 'mustache' }); + * // => 'hello mustache!' + * + * // Use the `source` property to inline compiled templates for meaningful + * // line numbers in error messages and stack traces. + * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\ + * var JST = {\ + * "main": ' + _.template(mainText).source + '\ + * };\ + * '); + */ + function template(string, options, guard) { + // Based on John Resig's `tmpl` implementation + // (http://ejohn.org/blog/javascript-micro-templating/) + // and Laura Doktorova's doT.js (https://github.com/olado/doT). + var settings = lodash.templateSettings; + + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + string = toString(string); + options = assignInWith({}, options, settings, assignInDefaults); + + var imports = assignInWith({}, options.imports, settings.imports, assignInDefaults), + importsKeys = keys(imports), + importsValues = baseValues(imports, importsKeys); + + var isEscaping, + isEvaluating, + index = 0, + interpolate = options.interpolate || reNoMatch, + source = "__p += '"; + + // Compile the regexp to match each delimiter. + var reDelimiters = RegExp( + (options.escape || reNoMatch).source + '|' + + interpolate.source + '|' + + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' + + (options.evaluate || reNoMatch).source + '|$' + , 'g'); + + // Use a sourceURL for easier debugging. + var sourceURL = '//# sourceURL=' + + ('sourceURL' in options + ? options.sourceURL + : ('lodash.templateSources[' + (++templateCounter) + ']') + ) + '\n'; + + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + + // Escape characters that can't be included in string literals. + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + + // Replace delimiters with snippets. + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + + // The JS engine embedded in Adobe products needs `match` returned in + // order to produce the correct `offset` value. + return match; + }); + + source += "';\n"; + + // If `variable` is not specified wrap a with-statement around the generated + // code to add the data object to the top of the scope chain. + var variable = options.variable; + if (!variable) { + source = 'with (obj) {\n' + source + '\n}\n'; + } + // Cleanup code by stripping empty strings. + source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source) + .replace(reEmptyStringMiddle, '$1') + .replace(reEmptyStringTrailing, '$1;'); + + // Frame code as the function body. + source = 'function(' + (variable || 'obj') + ') {\n' + + (variable + ? '' + : 'obj || (obj = {});\n' + ) + + "var __t, __p = ''" + + (isEscaping + ? ', __e = _.escape' + : '' + ) + + (isEvaluating + ? ', __j = Array.prototype.join;\n' + + "function print() { __p += __j.call(arguments, '') }\n" + : ';\n' + ) + + source + + 'return __p\n}'; + + var result = attempt(function() { + return Function(importsKeys, sourceURL + 'return ' + source) + .apply(undefined, importsValues); + }); + + // Provide the compiled function's source by its `toString` method or + // the `source` property as a convenience for inlining compiled templates. + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + + /** + * Converts `string`, as a whole, to lower case just like + * [String#toLowerCase](https://mdn.io/toLowerCase). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the lower cased string. + * @example + * + * _.toLower('--Foo-Bar--'); + * // => '--foo-bar--' + * + * _.toLower('fooBar'); + * // => 'foobar' + * + * _.toLower('__FOO_BAR__'); + * // => '__foo_bar__' + */ + function toLower(value) { + return toString(value).toLowerCase(); + } + + /** + * Converts `string`, as a whole, to upper case just like + * [String#toUpperCase](https://mdn.io/toUpperCase). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the upper cased string. + * @example + * + * _.toUpper('--foo-bar--'); + * // => '--FOO-BAR--' + * + * _.toUpper('fooBar'); + * // => 'FOOBAR' + * + * _.toUpper('__foo_bar__'); + * // => '__FOO_BAR__' + */ + function toUpper(value) { + return toString(value).toUpperCase(); + } + + /** + * Removes leading and trailing whitespace or specified characters from `string`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {string} Returns the trimmed string. + * @example + * + * _.trim(' abc '); + * // => 'abc' + * + * _.trim('-_-abc-_-', '_-'); + * // => 'abc' + * + * _.map([' foo ', ' bar '], _.trim); + * // => ['foo', 'bar'] + */ + function trim(string, chars, guard) { + string = toString(string); + if (string && (guard || chars === undefined)) { + return string.replace(reTrim, ''); + } + if (!string || !(chars = baseToString(chars))) { + return string; + } + var strSymbols = stringToArray(string), + chrSymbols = stringToArray(chars), + start = charsStartIndex(strSymbols, chrSymbols), + end = charsEndIndex(strSymbols, chrSymbols) + 1; + + return castSlice(strSymbols, start, end).join(''); + } + + /** + * Removes trailing whitespace or specified characters from `string`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {string} Returns the trimmed string. + * @example + * + * _.trimEnd(' abc '); + * // => ' abc' + * + * _.trimEnd('-_-abc-_-', '_-'); + * // => '-_-abc' + */ + function trimEnd(string, chars, guard) { + string = toString(string); + if (string && (guard || chars === undefined)) { + return string.replace(reTrimEnd, ''); + } + if (!string || !(chars = baseToString(chars))) { + return string; + } + var strSymbols = stringToArray(string), + end = charsEndIndex(strSymbols, stringToArray(chars)) + 1; + + return castSlice(strSymbols, 0, end).join(''); + } + + /** + * Removes leading whitespace or specified characters from `string`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to trim. + * @param {string} [chars=whitespace] The characters to trim. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {string} Returns the trimmed string. + * @example + * + * _.trimStart(' abc '); + * // => 'abc ' + * + * _.trimStart('-_-abc-_-', '_-'); + * // => 'abc-_-' + */ + function trimStart(string, chars, guard) { + string = toString(string); + if (string && (guard || chars === undefined)) { + return string.replace(reTrimStart, ''); + } + if (!string || !(chars = baseToString(chars))) { + return string; + } + var strSymbols = stringToArray(string), + start = charsStartIndex(strSymbols, stringToArray(chars)); + + return castSlice(strSymbols, start).join(''); + } + + /** + * Truncates `string` if it's longer than the given maximum string length. + * The last characters of the truncated string are replaced with the omission + * string which defaults to "...". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to truncate. + * @param {Object} [options={}] The options object. + * @param {number} [options.length=30] The maximum string length. + * @param {string} [options.omission='...'] The string to indicate text is omitted. + * @param {RegExp|string} [options.separator] The separator pattern to truncate to. + * @returns {string} Returns the truncated string. + * @example + * + * _.truncate('hi-diddly-ho there, neighborino'); + * // => 'hi-diddly-ho there, neighbo...' + * + * _.truncate('hi-diddly-ho there, neighborino', { + * 'length': 24, + * 'separator': ' ' + * }); + * // => 'hi-diddly-ho there,...' + * + * _.truncate('hi-diddly-ho there, neighborino', { + * 'length': 24, + * 'separator': /,? +/ + * }); + * // => 'hi-diddly-ho there...' + * + * _.truncate('hi-diddly-ho there, neighborino', { + * 'omission': ' [...]' + * }); + * // => 'hi-diddly-ho there, neig [...]' + */ + function truncate(string, options) { + var length = DEFAULT_TRUNC_LENGTH, + omission = DEFAULT_TRUNC_OMISSION; + + if (isObject(options)) { + var separator = 'separator' in options ? options.separator : separator; + length = 'length' in options ? toInteger(options.length) : length; + omission = 'omission' in options ? baseToString(options.omission) : omission; + } + string = toString(string); + + var strLength = string.length; + if (hasUnicode(string)) { + var strSymbols = stringToArray(string); + strLength = strSymbols.length; + } + if (length >= strLength) { + return string; + } + var end = length - stringSize(omission); + if (end < 1) { + return omission; + } + var result = strSymbols + ? castSlice(strSymbols, 0, end).join('') + : string.slice(0, end); + + if (separator === undefined) { + return result + omission; + } + if (strSymbols) { + end += (result.length - end); + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, + substring = result; + + if (!separator.global) { + separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g'); + } + separator.lastIndex = 0; + while ((match = separator.exec(substring))) { + var newEnd = match.index; + } + result = result.slice(0, newEnd === undefined ? end : newEnd); + } + } else if (string.indexOf(baseToString(separator), end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + + /** + * The inverse of `_.escape`; this method converts the HTML entities + * `&`, `<`, `>`, `"`, and `'` in `string` to + * their corresponding characters. + * + * **Note:** No other HTML entities are unescaped. To unescape additional + * HTML entities use a third-party library like [_he_](https://mths.be/he). + * + * @static + * @memberOf _ + * @since 0.6.0 + * @category String + * @param {string} [string=''] The string to unescape. + * @returns {string} Returns the unescaped string. + * @example + * + * _.unescape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ + function unescape(string) { + string = toString(string); + return (string && reHasEscapedHtml.test(string)) + ? string.replace(reEscapedHtml, unescapeHtmlChar) + : string; + } + + /** + * Converts `string`, as space separated words, to upper case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the upper cased string. + * @example + * + * _.upperCase('--foo-bar'); + * // => 'FOO BAR' + * + * _.upperCase('fooBar'); + * // => 'FOO BAR' + * + * _.upperCase('__foo_bar__'); + * // => 'FOO BAR' + */ + var upperCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + word.toUpperCase(); + }); + + /** + * Converts the first character of `string` to upper case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.upperFirst('fred'); + * // => 'Fred' + * + * _.upperFirst('FRED'); + * // => 'FRED' + */ + var upperFirst = createCaseFirst('toUpperCase'); + + /** + * Splits `string` into an array of its words. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {RegExp|string} [pattern] The pattern to match words. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the words of `string`. + * @example + * + * _.words('fred, barney, & pebbles'); + * // => ['fred', 'barney', 'pebbles'] + * + * _.words('fred, barney, & pebbles', /[^, ]+/g); + * // => ['fred', 'barney', '&', 'pebbles'] + */ + function words(string, pattern, guard) { + string = toString(string); + pattern = guard ? undefined : pattern; + + if (pattern === undefined) { + return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string); + } + return string.match(pattern) || []; + } + + /*------------------------------------------------------------------------*/ + + /** + * Attempts to invoke `func`, returning either the result or the caught error + * object. Any additional arguments are provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Util + * @param {Function} func The function to attempt. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {*} Returns the `func` result or error object. + * @example + * + * // Avoid throwing errors for invalid selectors. + * var elements = _.attempt(function(selector) { + * return document.querySelectorAll(selector); + * }, '>_>'); + * + * if (_.isError(elements)) { + * elements = []; + * } + */ + var attempt = baseRest(function(func, args) { + try { + return apply(func, undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + + /** + * Binds methods of an object to the object itself, overwriting the existing + * method. + * + * **Note:** This method doesn't set the "length" property of bound functions. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {Object} object The object to bind and assign the bound methods to. + * @param {...(string|string[])} methodNames The object method names to bind. + * @returns {Object} Returns `object`. + * @example + * + * var view = { + * 'label': 'docs', + * 'click': function() { + * console.log('clicked ' + this.label); + * } + * }; + * + * _.bindAll(view, ['click']); + * jQuery(element).on('click', view.click); + * // => Logs 'clicked docs' when clicked. + */ + var bindAll = flatRest(function(object, methodNames) { + arrayEach(methodNames, function(key) { + key = toKey(key); + baseAssignValue(object, key, bind(object[key], object)); + }); + return object; + }); + + /** + * Creates a function that iterates over `pairs` and invokes the corresponding + * function of the first predicate to return truthy. The predicate-function + * pairs are invoked with the `this` binding and arguments of the created + * function. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Util + * @param {Array} pairs The predicate-function pairs. + * @returns {Function} Returns the new composite function. + * @example + * + * var func = _.cond([ + * [_.matches({ 'a': 1 }), _.constant('matches A')], + * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')], + * [_.stubTrue, _.constant('no match')] + * ]); + * + * func({ 'a': 1, 'b': 2 }); + * // => 'matches A' + * + * func({ 'a': 0, 'b': 1 }); + * // => 'matches B' + * + * func({ 'a': '1', 'b': '2' }); + * // => 'no match' + */ + function cond(pairs) { + var length = pairs ? pairs.length : 0, + toIteratee = getIteratee(); + + pairs = !length ? [] : arrayMap(pairs, function(pair) { + if (typeof pair[1] != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return [toIteratee(pair[0]), pair[1]]; + }); + + return baseRest(function(args) { + var index = -1; + while (++index < length) { + var pair = pairs[index]; + if (apply(pair[0], this, args)) { + return apply(pair[1], this, args); + } + } + }); + } + + /** + * Creates a function that invokes the predicate properties of `source` with + * the corresponding property values of a given object, returning `true` if + * all predicates return truthy, else `false`. + * + * **Note:** The created function is equivalent to `_.conformsTo` with + * `source` partially applied. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Util + * @param {Object} source The object of property predicates to conform to. + * @returns {Function} Returns the new spec function. + * @example + * + * var objects = [ + * { 'a': 2, 'b': 1 }, + * { 'a': 1, 'b': 2 } + * ]; + * + * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } })); + * // => [{ 'a': 1, 'b': 2 }] + */ + function conforms(source) { + return baseConforms(baseClone(source, true)); + } + + /** + * Creates a function that returns `value`. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Util + * @param {*} value The value to return from the new function. + * @returns {Function} Returns the new constant function. + * @example + * + * var objects = _.times(2, _.constant({ 'a': 1 })); + * + * console.log(objects); + * // => [{ 'a': 1 }, { 'a': 1 }] + * + * console.log(objects[0] === objects[1]); + * // => true + */ + function constant(value) { + return function() { + return value; + }; + } + + /** + * Checks `value` to determine whether a default value should be returned in + * its place. The `defaultValue` is returned if `value` is `NaN`, `null`, + * or `undefined`. + * + * @static + * @memberOf _ + * @since 4.14.0 + * @category Util + * @param {*} value The value to check. + * @param {*} defaultValue The default value. + * @returns {*} Returns the resolved value. + * @example + * + * _.defaultTo(1, 10); + * // => 1 + * + * _.defaultTo(undefined, 10); + * // => 10 + */ + function defaultTo(value, defaultValue) { + return (value == null || value !== value) ? defaultValue : value; + } + + /** + * Creates a function that returns the result of invoking the given functions + * with the `this` binding of the created function, where each successive + * invocation is supplied the return value of the previous. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Util + * @param {...(Function|Function[])} [funcs] The functions to invoke. + * @returns {Function} Returns the new composite function. + * @see _.flowRight + * @example + * + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.flow([_.add, square]); + * addSquare(1, 2); + * // => 9 + */ + var flow = createFlow(); + + /** + * This method is like `_.flow` except that it creates a function that + * invokes the given functions from right to left. + * + * @static + * @since 3.0.0 + * @memberOf _ + * @category Util + * @param {...(Function|Function[])} [funcs] The functions to invoke. + * @returns {Function} Returns the new composite function. + * @see _.flow + * @example + * + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.flowRight([square, _.add]); + * addSquare(1, 2); + * // => 9 + */ + var flowRight = createFlow(true); + + /** + * This method returns the first argument it receives. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {*} value Any value. + * @returns {*} Returns `value`. + * @example + * + * var object = { 'a': 1 }; + * + * console.log(_.identity(object) === object); + * // => true + */ + function identity(value) { + return value; + } + + /** + * Creates a function that invokes `func` with the arguments of the created + * function. If `func` is a property name, the created function returns the + * property value for a given element. If `func` is an array or object, the + * created function returns `true` for elements that contain the equivalent + * source properties, otherwise it returns `false`. + * + * @static + * @since 4.0.0 + * @memberOf _ + * @category Util + * @param {*} [func=_.identity] The value to convert to a callback. + * @returns {Function} Returns the callback. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true })); + * // => [{ 'user': 'barney', 'age': 36, 'active': true }] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, _.iteratee(['user', 'fred'])); + * // => [{ 'user': 'fred', 'age': 40 }] + * + * // The `_.property` iteratee shorthand. + * _.map(users, _.iteratee('user')); + * // => ['barney', 'fred'] + * + * // Create custom iteratee shorthands. + * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) { + * return !_.isRegExp(func) ? iteratee(func) : function(string) { + * return func.test(string); + * }; + * }); + * + * _.filter(['abc', 'def'], /ef/); + * // => ['def'] + */ + function iteratee(func) { + return baseIteratee(typeof func == 'function' ? func : baseClone(func, true)); + } + + /** + * Creates a function that performs a partial deep comparison between a given + * object and `source`, returning `true` if the given object has equivalent + * property values, else `false`. + * + * **Note:** The created function is equivalent to `_.isMatch` with `source` + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Util + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + * @example + * + * var objects = [ + * { 'a': 1, 'b': 2, 'c': 3 }, + * { 'a': 4, 'b': 5, 'c': 6 } + * ]; + * + * _.filter(objects, _.matches({ 'a': 4, 'c': 6 })); + * // => [{ 'a': 4, 'b': 5, 'c': 6 }] + */ + function matches(source) { + return baseMatches(baseClone(source, true)); + } + + /** + * Creates a function that performs a partial deep comparison between the + * value at `path` of a given object to `srcValue`, returning `true` if the + * object value is equivalent, else `false`. + * + * **Note:** Partial comparisons will match empty array and empty object + * `srcValue` values against any array or object value, respectively. See + * `_.isEqual` for a list of supported value comparisons. + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Util + * @param {Array|string} path The path of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + * @example + * + * var objects = [ + * { 'a': 1, 'b': 2, 'c': 3 }, + * { 'a': 4, 'b': 5, 'c': 6 } + * ]; + * + * _.find(objects, _.matchesProperty('a', 4)); + * // => { 'a': 4, 'b': 5, 'c': 6 } + */ + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + + /** + * Creates a function that invokes the method at `path` of a given object. + * Any additional arguments are provided to the invoked method. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Util + * @param {Array|string} path The path of the method to invoke. + * @param {...*} [args] The arguments to invoke the method with. + * @returns {Function} Returns the new invoker function. + * @example + * + * var objects = [ + * { 'a': { 'b': _.constant(2) } }, + * { 'a': { 'b': _.constant(1) } } + * ]; + * + * _.map(objects, _.method('a.b')); + * // => [2, 1] + * + * _.map(objects, _.method(['a', 'b'])); + * // => [2, 1] + */ + var method = baseRest(function(path, args) { + return function(object) { + return baseInvoke(object, path, args); + }; + }); + + /** + * The opposite of `_.method`; this method creates a function that invokes + * the method at a given path of `object`. Any additional arguments are + * provided to the invoked method. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Util + * @param {Object} object The object to query. + * @param {...*} [args] The arguments to invoke the method with. + * @returns {Function} Returns the new invoker function. + * @example + * + * var array = _.times(3, _.constant), + * object = { 'a': array, 'b': array, 'c': array }; + * + * _.map(['a[2]', 'c[0]'], _.methodOf(object)); + * // => [2, 0] + * + * _.map([['a', '2'], ['c', '0']], _.methodOf(object)); + * // => [2, 0] + */ + var methodOf = baseRest(function(object, args) { + return function(path) { + return baseInvoke(object, path, args); + }; + }); + + /** + * Adds all own enumerable string keyed function properties of a source + * object to the destination object. If `object` is a function, then methods + * are added to its prototype as well. + * + * **Note:** Use `_.runInContext` to create a pristine `lodash` function to + * avoid conflicts caused by modifying the original. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {Function|Object} [object=lodash] The destination object. + * @param {Object} source The object of functions to add. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.chain=true] Specify whether mixins are chainable. + * @returns {Function|Object} Returns `object`. + * @example + * + * function vowels(string) { + * return _.filter(string, function(v) { + * return /[aeiou]/i.test(v); + * }); + * } + * + * _.mixin({ 'vowels': vowels }); + * _.vowels('fred'); + * // => ['e'] + * + * _('fred').vowels().value(); + * // => ['e'] + * + * _.mixin({ 'vowels': vowels }, { 'chain': false }); + * _('fred').vowels(); + * // => ['e'] + */ + function mixin(object, source, options) { + var props = keys(source), + methodNames = baseFunctions(source, props); + + if (options == null && + !(isObject(source) && (methodNames.length || !props.length))) { + options = source; + source = object; + object = this; + methodNames = baseFunctions(source, keys(source)); + } + var chain = !(isObject(options) && 'chain' in options) || !!options.chain, + isFunc = isFunction(object); + + arrayEach(methodNames, function(methodName) { + var func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), + actions = result.__actions__ = copyArray(this.__actions__); + + actions.push({ 'func': func, 'args': arguments, 'thisArg': object }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([this.value()], arguments)); + }; + } + }); + + return object; + } + + /** + * Reverts the `_` variable to its previous value and returns a reference to + * the `lodash` function. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @returns {Function} Returns the `lodash` function. + * @example + * + * var lodash = _.noConflict(); + */ + function noConflict() { + if (root._ === this) { + root._ = oldDash; + } + return this; + } + + /** + * This method returns `undefined`. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Util + * @example + * + * _.times(2, _.noop); + * // => [undefined, undefined] + */ + function noop() { + // No operation performed. + } + + /** + * Creates a function that gets the argument at index `n`. If `n` is negative, + * the nth argument from the end is returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Util + * @param {number} [n=0] The index of the argument to return. + * @returns {Function} Returns the new pass-thru function. + * @example + * + * var func = _.nthArg(1); + * func('a', 'b', 'c', 'd'); + * // => 'b' + * + * var func = _.nthArg(-2); + * func('a', 'b', 'c', 'd'); + * // => 'c' + */ + function nthArg(n) { + n = toInteger(n); + return baseRest(function(args) { + return baseNth(args, n); + }); + } + + /** + * Creates a function that invokes `iteratees` with the arguments it receives + * and returns their results. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Util + * @param {...(Function|Function[])} [iteratees=[_.identity]] + * The iteratees to invoke. + * @returns {Function} Returns the new function. + * @example + * + * var func = _.over([Math.max, Math.min]); + * + * func(1, 2, 3, 4); + * // => [4, 1] + */ + var over = createOver(arrayMap); + + /** + * Creates a function that checks if **all** of the `predicates` return + * truthy when invoked with the arguments it receives. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Util + * @param {...(Function|Function[])} [predicates=[_.identity]] + * The predicates to check. + * @returns {Function} Returns the new function. + * @example + * + * var func = _.overEvery([Boolean, isFinite]); + * + * func('1'); + * // => true + * + * func(null); + * // => false + * + * func(NaN); + * // => false + */ + var overEvery = createOver(arrayEvery); + + /** + * Creates a function that checks if **any** of the `predicates` return + * truthy when invoked with the arguments it receives. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Util + * @param {...(Function|Function[])} [predicates=[_.identity]] + * The predicates to check. + * @returns {Function} Returns the new function. + * @example + * + * var func = _.overSome([Boolean, isFinite]); + * + * func('1'); + * // => true + * + * func(null); + * // => true + * + * func(NaN); + * // => false + */ + var overSome = createOver(arraySome); + + /** + * Creates a function that returns the value at `path` of a given object. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Util + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new accessor function. + * @example + * + * var objects = [ + * { 'a': { 'b': 2 } }, + * { 'a': { 'b': 1 } } + * ]; + * + * _.map(objects, _.property('a.b')); + * // => [2, 1] + * + * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b'); + * // => [1, 2] + */ + function property(path) { + return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path); + } + + /** + * The opposite of `_.property`; this method creates a function that returns + * the value at a given path of `object`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Util + * @param {Object} object The object to query. + * @returns {Function} Returns the new accessor function. + * @example + * + * var array = [0, 1, 2], + * object = { 'a': array, 'b': array, 'c': array }; + * + * _.map(['a[2]', 'c[0]'], _.propertyOf(object)); + * // => [2, 0] + * + * _.map([['a', '2'], ['c', '0']], _.propertyOf(object)); + * // => [2, 0] + */ + function propertyOf(object) { + return function(path) { + return object == null ? undefined : baseGet(object, path); + }; + } + + /** + * Creates an array of numbers (positive and/or negative) progressing from + * `start` up to, but not including, `end`. A step of `-1` is used if a negative + * `start` is specified without an `end` or `step`. If `end` is not specified, + * it's set to `start` with `start` then set to `0`. + * + * **Note:** JavaScript follows the IEEE-754 standard for resolving + * floating-point values which can produce unexpected results. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @param {number} [step=1] The value to increment or decrement by. + * @returns {Array} Returns the range of numbers. + * @see _.inRange, _.rangeRight + * @example + * + * _.range(4); + * // => [0, 1, 2, 3] + * + * _.range(-4); + * // => [0, -1, -2, -3] + * + * _.range(1, 5); + * // => [1, 2, 3, 4] + * + * _.range(0, 20, 5); + * // => [0, 5, 10, 15] + * + * _.range(0, -4, -1); + * // => [0, -1, -2, -3] + * + * _.range(1, 4, 0); + * // => [1, 1, 1] + * + * _.range(0); + * // => [] + */ + var range = createRange(); + + /** + * This method is like `_.range` except that it populates values in + * descending order. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Util + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @param {number} [step=1] The value to increment or decrement by. + * @returns {Array} Returns the range of numbers. + * @see _.inRange, _.range + * @example + * + * _.rangeRight(4); + * // => [3, 2, 1, 0] + * + * _.rangeRight(-4); + * // => [-3, -2, -1, 0] + * + * _.rangeRight(1, 5); + * // => [4, 3, 2, 1] + * + * _.rangeRight(0, 20, 5); + * // => [15, 10, 5, 0] + * + * _.rangeRight(0, -4, -1); + * // => [-3, -2, -1, 0] + * + * _.rangeRight(1, 4, 0); + * // => [1, 1, 1] + * + * _.rangeRight(0); + * // => [] + */ + var rangeRight = createRange(true); + + /** + * This method returns a new empty array. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {Array} Returns the new empty array. + * @example + * + * var arrays = _.times(2, _.stubArray); + * + * console.log(arrays); + * // => [[], []] + * + * console.log(arrays[0] === arrays[1]); + * // => false + */ + function stubArray() { + return []; + } + + /** + * This method returns `false`. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `false`. + * @example + * + * _.times(2, _.stubFalse); + * // => [false, false] + */ + function stubFalse() { + return false; + } + + /** + * This method returns a new empty object. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {Object} Returns the new empty object. + * @example + * + * var objects = _.times(2, _.stubObject); + * + * console.log(objects); + * // => [{}, {}] + * + * console.log(objects[0] === objects[1]); + * // => false + */ + function stubObject() { + return {}; + } + + /** + * This method returns an empty string. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {string} Returns the empty string. + * @example + * + * _.times(2, _.stubString); + * // => ['', ''] + */ + function stubString() { + return ''; + } + + /** + * This method returns `true`. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `true`. + * @example + * + * _.times(2, _.stubTrue); + * // => [true, true] + */ + function stubTrue() { + return true; + } + + /** + * Invokes the iteratee `n` times, returning an array of the results of + * each invocation. The iteratee is invoked with one argument; (index). + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the array of results. + * @example + * + * _.times(3, String); + * // => ['0', '1', '2'] + * + * _.times(4, _.constant(0)); + * // => [0, 0, 0, 0] + */ + function times(n, iteratee) { + n = toInteger(n); + if (n < 1 || n > MAX_SAFE_INTEGER) { + return []; + } + var index = MAX_ARRAY_LENGTH, + length = nativeMin(n, MAX_ARRAY_LENGTH); + + iteratee = getIteratee(iteratee); + n -= MAX_ARRAY_LENGTH; + + var result = baseTimes(length, iteratee); + while (++index < n) { + iteratee(index); + } + return result; + } + + /** + * Converts `value` to a property path array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Util + * @param {*} value The value to convert. + * @returns {Array} Returns the new property path array. + * @example + * + * _.toPath('a.b.c'); + * // => ['a', 'b', 'c'] + * + * _.toPath('a[0].b.c'); + * // => ['a', '0', 'b', 'c'] + */ + function toPath(value) { + if (isArray(value)) { + return arrayMap(value, toKey); + } + return isSymbol(value) ? [value] : copyArray(stringToPath(value)); + } + + /** + * Generates a unique ID. If `prefix` is given, the ID is appended to it. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {string} [prefix=''] The value to prefix the ID with. + * @returns {string} Returns the unique ID. + * @example + * + * _.uniqueId('contact_'); + * // => 'contact_104' + * + * _.uniqueId(); + * // => '105' + */ + function uniqueId(prefix) { + var id = ++idCounter; + return toString(prefix) + id; + } + + /*------------------------------------------------------------------------*/ + + /** + * Adds two numbers. + * + * @static + * @memberOf _ + * @since 3.4.0 + * @category Math + * @param {number} augend The first number in an addition. + * @param {number} addend The second number in an addition. + * @returns {number} Returns the total. + * @example + * + * _.add(6, 4); + * // => 10 + */ + var add = createMathOperation(function(augend, addend) { + return augend + addend; + }, 0); + + /** + * Computes `number` rounded up to `precision`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Math + * @param {number} number The number to round up. + * @param {number} [precision=0] The precision to round up to. + * @returns {number} Returns the rounded up number. + * @example + * + * _.ceil(4.006); + * // => 5 + * + * _.ceil(6.004, 2); + * // => 6.01 + * + * _.ceil(6040, -2); + * // => 6100 + */ + var ceil = createRound('ceil'); + + /** + * Divide two numbers. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Math + * @param {number} dividend The first number in a division. + * @param {number} divisor The second number in a division. + * @returns {number} Returns the quotient. + * @example + * + * _.divide(6, 4); + * // => 1.5 + */ + var divide = createMathOperation(function(dividend, divisor) { + return dividend / divisor; + }, 1); + + /** + * Computes `number` rounded down to `precision`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Math + * @param {number} number The number to round down. + * @param {number} [precision=0] The precision to round down to. + * @returns {number} Returns the rounded down number. + * @example + * + * _.floor(4.006); + * // => 4 + * + * _.floor(0.046, 2); + * // => 0.04 + * + * _.floor(4060, -2); + * // => 4000 + */ + var floor = createRound('floor'); + + /** + * Computes the maximum value of `array`. If `array` is empty or falsey, + * `undefined` is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Math + * @param {Array} array The array to iterate over. + * @returns {*} Returns the maximum value. + * @example + * + * _.max([4, 2, 8, 6]); + * // => 8 + * + * _.max([]); + * // => undefined + */ + function max(array) { + return (array && array.length) + ? baseExtremum(array, identity, baseGt) + : undefined; + } + + /** + * This method is like `_.max` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the criterion by which + * the value is ranked. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Math + * @param {Array} array The array to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {*} Returns the maximum value. + * @example + * + * var objects = [{ 'n': 1 }, { 'n': 2 }]; + * + * _.maxBy(objects, function(o) { return o.n; }); + * // => { 'n': 2 } + * + * // The `_.property` iteratee shorthand. + * _.maxBy(objects, 'n'); + * // => { 'n': 2 } + */ + function maxBy(array, iteratee) { + return (array && array.length) + ? baseExtremum(array, getIteratee(iteratee, 2), baseGt) + : undefined; + } + + /** + * Computes the mean of the values in `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Math + * @param {Array} array The array to iterate over. + * @returns {number} Returns the mean. + * @example + * + * _.mean([4, 2, 8, 6]); + * // => 5 + */ + function mean(array) { + return baseMean(array, identity); + } + + /** + * This method is like `_.mean` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the value to be averaged. + * The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Math + * @param {Array} array The array to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the mean. + * @example + * + * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }]; + * + * _.meanBy(objects, function(o) { return o.n; }); + * // => 5 + * + * // The `_.property` iteratee shorthand. + * _.meanBy(objects, 'n'); + * // => 5 + */ + function meanBy(array, iteratee) { + return baseMean(array, getIteratee(iteratee, 2)); + } + + /** + * Computes the minimum value of `array`. If `array` is empty or falsey, + * `undefined` is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Math + * @param {Array} array The array to iterate over. + * @returns {*} Returns the minimum value. + * @example + * + * _.min([4, 2, 8, 6]); + * // => 2 + * + * _.min([]); + * // => undefined + */ + function min(array) { + return (array && array.length) + ? baseExtremum(array, identity, baseLt) + : undefined; + } + + /** + * This method is like `_.min` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the criterion by which + * the value is ranked. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Math + * @param {Array} array The array to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {*} Returns the minimum value. + * @example + * + * var objects = [{ 'n': 1 }, { 'n': 2 }]; + * + * _.minBy(objects, function(o) { return o.n; }); + * // => { 'n': 1 } + * + * // The `_.property` iteratee shorthand. + * _.minBy(objects, 'n'); + * // => { 'n': 1 } + */ + function minBy(array, iteratee) { + return (array && array.length) + ? baseExtremum(array, getIteratee(iteratee, 2), baseLt) + : undefined; + } + + /** + * Multiply two numbers. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Math + * @param {number} multiplier The first number in a multiplication. + * @param {number} multiplicand The second number in a multiplication. + * @returns {number} Returns the product. + * @example + * + * _.multiply(6, 4); + * // => 24 + */ + var multiply = createMathOperation(function(multiplier, multiplicand) { + return multiplier * multiplicand; + }, 1); + + /** + * Computes `number` rounded to `precision`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Math + * @param {number} number The number to round. + * @param {number} [precision=0] The precision to round to. + * @returns {number} Returns the rounded number. + * @example + * + * _.round(4.006); + * // => 4 + * + * _.round(4.006, 2); + * // => 4.01 + * + * _.round(4060, -2); + * // => 4100 + */ + var round = createRound('round'); + + /** + * Subtract two numbers. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Math + * @param {number} minuend The first number in a subtraction. + * @param {number} subtrahend The second number in a subtraction. + * @returns {number} Returns the difference. + * @example + * + * _.subtract(6, 4); + * // => 2 + */ + var subtract = createMathOperation(function(minuend, subtrahend) { + return minuend - subtrahend; + }, 0); + + /** + * Computes the sum of the values in `array`. + * + * @static + * @memberOf _ + * @since 3.4.0 + * @category Math + * @param {Array} array The array to iterate over. + * @returns {number} Returns the sum. + * @example + * + * _.sum([4, 2, 8, 6]); + * // => 20 + */ + function sum(array) { + return (array && array.length) + ? baseSum(array, identity) + : 0; + } + + /** + * This method is like `_.sum` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the value to be summed. + * The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Math + * @param {Array} array The array to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the sum. + * @example + * + * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }]; + * + * _.sumBy(objects, function(o) { return o.n; }); + * // => 20 + * + * // The `_.property` iteratee shorthand. + * _.sumBy(objects, 'n'); + * // => 20 + */ + function sumBy(array, iteratee) { + return (array && array.length) + ? baseSum(array, getIteratee(iteratee, 2)) + : 0; + } + + /*------------------------------------------------------------------------*/ + + // Add methods that return wrapped values in chain sequences. + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.assignIn = assignIn; + lodash.assignInWith = assignInWith; + lodash.assignWith = assignWith; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.castArray = castArray; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.concat = concat; + lodash.cond = cond; + lodash.conforms = conforms; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.differenceBy = differenceBy; + lodash.differenceWith = differenceWith; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatMap = flatMap; + lodash.flatMapDeep = flatMapDeep; + lodash.flatMapDepth = flatMapDepth; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flattenDepth = flattenDepth; + lodash.flip = flip; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.fromPairs = fromPairs; + lodash.functions = functions; + lodash.functionsIn = functionsIn; + lodash.groupBy = groupBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.intersectionBy = intersectionBy; + lodash.intersectionWith = intersectionWith; + lodash.invert = invert; + lodash.invertBy = invertBy; + lodash.invokeMap = invokeMap; + lodash.iteratee = iteratee; + lodash.keyBy = keyBy; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.mergeWith = mergeWith; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.negate = negate; + lodash.nthArg = nthArg; + lodash.omit = omit; + lodash.omitBy = omitBy; + lodash.once = once; + lodash.orderBy = orderBy; + lodash.over = over; + lodash.overArgs = overArgs; + lodash.overEvery = overEvery; + lodash.overSome = overSome; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pickBy = pickBy; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAll = pullAll; + lodash.pullAllBy = pullAllBy; + lodash.pullAllWith = pullAllWith; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rangeRight = rangeRight; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.reverse = reverse; + lodash.sampleSize = sampleSize; + lodash.set = set; + lodash.setWith = setWith; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortedUniq = sortedUniq; + lodash.sortedUniqBy = sortedUniqBy; + lodash.split = split; + lodash.spread = spread; + lodash.tail = tail; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.toArray = toArray; + lodash.toPairs = toPairs; + lodash.toPairsIn = toPairsIn; + lodash.toPath = toPath; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.unary = unary; + lodash.union = union; + lodash.unionBy = unionBy; + lodash.unionWith = unionWith; + lodash.uniq = uniq; + lodash.uniqBy = uniqBy; + lodash.uniqWith = uniqWith; + lodash.unset = unset; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.update = update; + lodash.updateWith = updateWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.without = without; + lodash.words = words; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.xorBy = xorBy; + lodash.xorWith = xorWith; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipObjectDeep = zipObjectDeep; + lodash.zipWith = zipWith; + + // Add aliases. + lodash.entries = toPairs; + lodash.entriesIn = toPairsIn; + lodash.extend = assignIn; + lodash.extendWith = assignInWith; + + // Add methods to `lodash.prototype`. + mixin(lodash, lodash); + + /*------------------------------------------------------------------------*/ + + // Add methods that return unwrapped values in chain sequences. + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clamp = clamp; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.cloneDeepWith = cloneDeepWith; + lodash.cloneWith = cloneWith; + lodash.conformsTo = conformsTo; + lodash.deburr = deburr; + lodash.defaultTo = defaultTo; + lodash.divide = divide; + lodash.endsWith = endsWith; + lodash.eq = eq; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.floor = floor; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.hasIn = hasIn; + lodash.head = head; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.invoke = invoke; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isArrayBuffer = isArrayBuffer; + lodash.isArrayLike = isArrayLike; + lodash.isArrayLikeObject = isArrayLikeObject; + lodash.isBoolean = isBoolean; + lodash.isBuffer = isBuffer; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isEqualWith = isEqualWith; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isInteger = isInteger; + lodash.isLength = isLength; + lodash.isMap = isMap; + lodash.isMatch = isMatch; + lodash.isMatchWith = isMatchWith; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNil = isNil; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isObjectLike = isObjectLike; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isSafeInteger = isSafeInteger; + lodash.isSet = isSet; + lodash.isString = isString; + lodash.isSymbol = isSymbol; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.isWeakMap = isWeakMap; + lodash.isWeakSet = isWeakSet; + lodash.join = join; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lowerCase = lowerCase; + lodash.lowerFirst = lowerFirst; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.maxBy = maxBy; + lodash.mean = mean; + lodash.meanBy = meanBy; + lodash.min = min; + lodash.minBy = minBy; + lodash.stubArray = stubArray; + lodash.stubFalse = stubFalse; + lodash.stubObject = stubObject; + lodash.stubString = stubString; + lodash.stubTrue = stubTrue; + lodash.multiply = multiply; + lodash.nth = nth; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padEnd = padEnd; + lodash.padStart = padStart; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.replace = replace; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.sample = sample; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedIndexBy = sortedIndexBy; + lodash.sortedIndexOf = sortedIndexOf; + lodash.sortedLastIndex = sortedLastIndex; + lodash.sortedLastIndexBy = sortedLastIndexBy; + lodash.sortedLastIndexOf = sortedLastIndexOf; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.subtract = subtract; + lodash.sum = sum; + lodash.sumBy = sumBy; + lodash.template = template; + lodash.times = times; + lodash.toFinite = toFinite; + lodash.toInteger = toInteger; + lodash.toLength = toLength; + lodash.toLower = toLower; + lodash.toNumber = toNumber; + lodash.toSafeInteger = toSafeInteger; + lodash.toString = toString; + lodash.toUpper = toUpper; + lodash.trim = trim; + lodash.trimEnd = trimEnd; + lodash.trimStart = trimStart; + lodash.truncate = truncate; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.upperCase = upperCase; + lodash.upperFirst = upperFirst; + + // Add aliases. + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.first = head; + + mixin(lodash, (function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!hasOwnProperty.call(lodash.prototype, methodName)) { + source[methodName] = func; + } + }); + return source; + }()), { 'chain': false }); + + /*------------------------------------------------------------------------*/ + + /** + * The semantic version number. + * + * @static + * @memberOf _ + * @type {string} + */ + lodash.VERSION = VERSION; + + // Assign default placeholders. + arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + + // Add `LazyWrapper` methods for `_.drop` and `_.take` variants. + arrayEach(['drop', 'take'], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n === undefined ? 1 : nativeMax(toInteger(n), 0); + + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(n, result.__takeCount__); + } else { + result.__views__.push({ + 'size': nativeMin(n, MAX_ARRAY_LENGTH), + 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') + }); + } + return result; + }; + + LazyWrapper.prototype[methodName + 'Right'] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + + // Add `LazyWrapper` methods that accept an `iteratee` value. + arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) { + var type = index + 1, + isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG; + + LazyWrapper.prototype[methodName] = function(iteratee) { + var result = this.clone(); + result.__iteratees__.push({ + 'iteratee': getIteratee(iteratee, 3), + 'type': type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + + // Add `LazyWrapper` methods for `_.head` and `_.last`. + arrayEach(['head', 'last'], function(methodName, index) { + var takeName = 'take' + (index ? 'Right' : ''); + + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + + // Add `LazyWrapper` methods for `_.initial` and `_.tail`. + arrayEach(['initial', 'tail'], function(methodName, index) { + var dropName = 'drop' + (index ? '' : 'Right'); + + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + + LazyWrapper.prototype.find = function(predicate) { + return this.filter(predicate).head(); + }; + + LazyWrapper.prototype.findLast = function(predicate) { + return this.reverse().find(predicate); + }; + + LazyWrapper.prototype.invokeMap = baseRest(function(path, args) { + if (typeof path == 'function') { + return new LazyWrapper(this); + } + return this.map(function(value) { + return baseInvoke(value, path, args); + }); + }); + + LazyWrapper.prototype.reject = function(predicate) { + return this.filter(negate(getIteratee(predicate))); + }; + + LazyWrapper.prototype.slice = function(start, end) { + start = toInteger(start); + + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = toInteger(end); + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; + }; + + LazyWrapper.prototype.takeRightWhile = function(predicate) { + return this.reverse().takeWhile(predicate).reverse(); + }; + + LazyWrapper.prototype.toArray = function() { + return this.take(MAX_ARRAY_LENGTH); + }; + + // Add `LazyWrapper` methods to `lodash.prototype`. + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName), + isTaker = /^(?:head|last)$/.test(methodName), + lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName], + retUnwrapped = isTaker || /^find/.test(methodName); + + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var value = this.__wrapped__, + args = isTaker ? [1] : arguments, + isLazy = value instanceof LazyWrapper, + iteratee = args[0], + useLazy = isLazy || isArray(value); + + var interceptor = function(value) { + var result = lodashFunc.apply(lodash, arrayPush([value], args)); + return (isTaker && chainAll) ? result[0] : result; + }; + + if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) { + // Avoid lazy use if the iteratee has a "length" value other than `1`. + isLazy = useLazy = false; + } + var chainAll = this.__chain__, + isHybrid = !!this.__actions__.length, + isUnwrapped = retUnwrapped && !chainAll, + onlyLazy = isLazy && !isHybrid; + + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined }); + return new LodashWrapper(result, chainAll); + } + if (isUnwrapped && onlyLazy) { + return func.apply(this, args); + } + result = this.thru(interceptor); + return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result; + }; + }); + + // Add `Array` methods to `lodash.prototype`. + arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) { + var func = arrayProto[methodName], + chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', + retUnwrapped = /^(?:pop|shift)$/.test(methodName); + + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + var value = this.value(); + return func.apply(isArray(value) ? value : [], args); + } + return this[chainName](function(value) { + return func.apply(isArray(value) ? value : [], args); + }); + }; + }); + + // Map minified method names to their real names. + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = (lodashFunc.name + ''), + names = realNames[key] || (realNames[key] = []); + + names.push({ 'name': methodName, 'func': lodashFunc }); + } + }); + + realNames[createHybrid(undefined, BIND_KEY_FLAG).name] = [{ + 'name': 'wrapper', + 'func': undefined + }]; + + // Add methods to `LazyWrapper`. + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + + // Add chain sequence methods to the `lodash` wrapper. + lodash.prototype.at = wrapperAt; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.next = wrapperNext; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + + // Add lazy aliases. + lodash.prototype.first = lodash.prototype.head; + + if (iteratorSymbol) { + lodash.prototype[iteratorSymbol] = wrapperToIterator; + } + return lodash; + }); + + /*--------------------------------------------------------------------------*/ + + // Export lodash. + var _ = runInContext(); + + // Some AMD build optimizers, like r.js, check for condition patterns like: + if (true) { + // Expose Lodash on the global object to prevent errors when Lodash is + // loaded by a script tag in the presence of an AMD loader. + // See http://requirejs.org/docs/errors.html#mismatch for more details. + // Use `_.noConflict` to remove Lodash from the global object. + root._ = _; + + // Define as an anonymous module so, through path mapping, it can be + // referenced as the "underscore" module. + !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { + return _; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } + // Check for `exports` after `define` in case a build optimizer adds it. + else if (freeModule) { + // Export for Node.js. + (freeModule.exports = _)._ = _; + // Export for CommonJS support. + freeExports._ = _; + } + else { + // Export to the global object. + root._ = _; + } + }.call(this)); + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(77)(module))) + +/***/ }, +/* 409 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 410 */, +/* 411 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + + + var ReactDOM = __webpack_require__(16); + + function renderConditionalPanel(_ref) { + var condition = _ref.condition; + var closePanel = _ref.closePanel; + var setBreakpoint = _ref.setBreakpoint; + + var panel = document.createElement("div"); + + function onKey(e) { + if (e.key != "Enter") { + return; + } + + setBreakpoint(e.target.value); + closePanel(); + } + + ReactDOM.render(dom.div({ className: "conditional-breakpoint-panel" }, dom.input({ + defaultValue: condition, + placeholder: "This breakpoint will pause when the expression is true", + onKeyPress: onKey + })), panel); + + return panel; + } + + module.exports = { + renderConditionalPanel + }; + +/***/ }, +/* 412 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var ReactDOM = __webpack_require__(16); + + var PropTypes = React.PropTypes; + + var classnames = __webpack_require__(211); + var Svg = __webpack_require__(310); + + var breakpointSvg = document.createElement("div"); + ReactDOM.render(Svg("breakpoint"), breakpointSvg); + + function makeMarker(isDisabled) { + var bp = breakpointSvg.cloneNode(true); + bp.className = classnames("editor new-breakpoint", { "breakpoint-disabled": isDisabled }); + + return bp; + } + + var Breakpoint = React.createClass({ + propTypes: { + breakpoint: PropTypes.object, + editor: PropTypes.object + }, + + displayName: "Breakpoint", + + addBreakpoint() { + var bp = this.props.breakpoint; + var line = bp.location.line - 1; + + this.props.editor.setGutterMarker(line, "breakpoints", makeMarker(bp.disabled)); + this.props.editor.addLineClass(line, "line", "new-breakpoint"); + if (bp.condition) { + this.props.editor.addLineClass(line, "line", "has-condition"); + } + }, + + shouldComponentUpdate(nextProps) { + return this.props.editor !== nextProps.editor || this.props.breakpoint.disabled !== nextProps.breakpoint.disabled || this.props.breakpoint.condition !== nextProps.breakpoint.condition; + }, + + componentDidMount() { + if (!this.props.editor) { + return; + } + + this.addBreakpoint(); + }, + + componentDidUpdate() { + this.addBreakpoint(); + }, + + componentWillUnmount() { + if (!this.props.editor) { + return; + } + + var bp = this.props.breakpoint; + var line = bp.location.line - 1; + + this.props.editor.setGutterMarker(line, "breakpoints", null); + this.props.editor.removeLineClass(line, "line", "new-breakpoint"); + this.props.editor.removeLineClass(line, "line", "has-condition"); + }, + + render() { + return null; + } + }); + + module.exports = Breakpoint; + +/***/ }, +/* 413 */ +/***/ function(module, exports, __webpack_require__) { + + var _require = __webpack_require__(28); + + var Menu = _require.Menu; + var MenuItem = _require.MenuItem; + + var _require2 = __webpack_require__(89); + + var isFirefoxPanel = _require2.isFirefoxPanel; + + + function createPopup(doc) { + var popup = doc.createElement("menupopup"); + + if (popup.openPopupAtScreen) { + return popup; + } + + function preventDefault(e) { + e.preventDefault(); + e.returnValue = false; + } + + var mask = document.querySelector("#contextmenu-mask"); + if (!mask) { + mask = doc.createElement("div"); + mask.id = "contextmenu-mask"; + document.body.appendChild(mask); + } + + mask.onclick = () => popup.hidePopup(); + + popup.openPopupAtScreen = function (clientX, clientY) { + this.style.setProperty("left", clientX + "px"); + this.style.setProperty("top", clientY + "px"); + mask = document.querySelector("#contextmenu-mask"); + window.onwheel = preventDefault; + mask.classList.add("show"); + this.dispatchEvent(new Event("popupshown")); + this.popupshown; + }; + + popup.hidePopup = function () { + this.remove(); + mask = document.querySelector("#contextmenu-mask"); + mask.classList.remove("show"); + window.onwheel = null; + }; + + return popup; + } + + if (!isFirefoxPanel()) { + Menu.prototype.createPopup = createPopup; + } + + function onShown(menu, popup) { + popup.childNodes.forEach((menuitem, index) => { + var item = menu.items[index]; + menuitem.onclick = () => { + item.click(); + popup.hidePopup(); + }; + }); + } + + function showMenu(e, items) { + var menu = new Menu(); + items.forEach(item => menu.append(new MenuItem(item))); + + if (isFirefoxPanel()) { + return menu.popup(e.screenX, e.screenY, { doc: window.parent.document }); + } + + menu.on("open", (_, popup) => onShown(menu, popup)); + return menu.popup(e.clientX, e.clientY, { doc: document }); + } + + function buildMenu(items) { + return items.map(itm => { + var hide = typeof itm.hidden === "function" ? itm.hidden() : itm.hidden; + return hide ? null : itm.item; + }).filter(itm => itm !== null); + } + + module.exports = { + showMenu, + buildMenu + }; + +/***/ }, +/* 414 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 415 */, +/* 416 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + var _require = __webpack_require__(19); + + var connect = _require.connect; + + var _require2 = __webpack_require__(3); + + var bindActionCreators = _require2.bindActionCreators; + + var _require3 = __webpack_require__(259); + + var getPause = _require3.getPause; + var getIsWaitingOnBreak = _require3.getIsWaitingOnBreak; + var getBreakpointsDisabled = _require3.getBreakpointsDisabled; + var getShouldPauseOnExceptions = _require3.getShouldPauseOnExceptions; + var getShouldIgnoreCaughtExceptions = _require3.getShouldIgnoreCaughtExceptions; + var getBreakpoints = _require3.getBreakpoints; + var getBreakpointsLoading = _require3.getBreakpointsLoading; + + var _require4 = __webpack_require__(89); + + var isEnabled = _require4.isEnabled; + + var Svg = __webpack_require__(310); + var ImPropTypes = __webpack_require__(235); + + var _require5 = __webpack_require__(30); + + var appinfo = _require5.Services.appinfo; + + var shiftKey = appinfo.OS === "Darwin" ? "\u21E7" : "Shift+"; + var ctrlKey = appinfo.OS === "Linux" ? "Ctrl+" : ""; + + var actions = __webpack_require__(262); + var Breakpoints = React.createFactory(__webpack_require__(417)); + var Expressions = React.createFactory(__webpack_require__(420)); + var Scopes = React.createFactory(__webpack_require__(424)); + var Frames = React.createFactory(__webpack_require__(444)); + var Accordion = React.createFactory(__webpack_require__(447)); + __webpack_require__(450); + + function debugBtn(onClick, type, className, tooltip) { + className = `${ type } ${ className }`; + return dom.span({ onClick, className, key: type }, Svg(type, { title: tooltip })); + } + + var RightSidebar = React.createClass({ + propTypes: { + sources: PropTypes.object, + selectedSource: PropTypes.object, + resume: PropTypes.func, + stepIn: PropTypes.func, + stepOut: PropTypes.func, + stepOver: PropTypes.func, + toggleAllBreakpoints: PropTypes.func, + breakOnNext: PropTypes.func, + pause: ImPropTypes.map, + pauseOnExceptions: PropTypes.func, + shouldPauseOnExceptions: PropTypes.bool, + shouldIgnoreCaughtExceptions: PropTypes.bool, + breakpoints: ImPropTypes.map, + isWaitingOnBreak: PropTypes.bool, + breakpointsDisabled: PropTypes.bool, + breakpointsLoading: PropTypes.bool, + evaluateExpressions: PropTypes.func + }, + + contextTypes: { + shortcuts: PropTypes.object + }, + + displayName: "RightSidebar", + + getInitialState() { + return { + expressionInputVisibility: true + }; + }, + + resume() { + if (this.props.pause) { + this.props.resume(); + } else if (!this.props.isWaitingOnBreak) { + this.props.breakOnNext(); + } + }, + + stepOver() { + if (!this.props.pause) { + return; + } + this.props.stepOver(); + }, + + stepIn() { + if (!this.props.pause) { + return; + } + this.props.stepIn(); + }, + + stepOut() { + if (!this.props.pause) { + return; + } + this.props.stepOut(); + }, + + componentWillUnmount() { + var shortcuts = this.context.shortcuts; + shortcuts.off("F8", this.resume); + shortcuts.off("F10", this.stepOver); + shortcuts.off(`${ ctrlKey }F11`, this.stepIn); + shortcuts.off(`${ ctrlKey }Shift+F11`, this.stepOut); + }, + + componentDidMount() { + var shortcuts = this.context.shortcuts; + shortcuts.on("F8", this.resume); + shortcuts.on("F10", this.stepOver); + shortcuts.on(`${ ctrlKey }F11`, this.stepIn); + shortcuts.on(`${ ctrlKey }Shift+F11`, this.stepOut); + }, + + renderStepButtons() { + var className = this.props.pause ? "active" : "disabled"; + return [debugBtn(this.stepOver, "stepOver", className, L10N.getStr("stepOverTooltip")), debugBtn(this.stepIn, "stepIn", className, L10N.getFormatStr("stepInTooltip", ctrlKey)), debugBtn(this.stepOut, "stepOut", className, L10N.getFormatStr("stepOutTooltip", ctrlKey + shiftKey))]; + }, + + renderPauseButton() { + var _props = this.props; + var pause = _props.pause; + var breakOnNext = _props.breakOnNext; + var isWaitingOnBreak = _props.isWaitingOnBreak; + + + if (pause) { + return debugBtn(this.resume, "resume", "active", L10N.getStr("resumeButtonTooltip")); + } + + if (isWaitingOnBreak) { + return debugBtn(null, "pause", "disabled", L10N.getStr("pausePendingButtonTooltip")); + } + + return debugBtn(breakOnNext, "pause", "active", L10N.getStr("pauseButtonTooltip")); + }, + + /* + * The pause on exception button has three states in this order: + * 1. don't pause on exceptions [false, false] + * 2. pause on uncaught exceptions [true, true] + * 3. pause on all exceptions [true, false] + */ + renderPauseOnExceptions() { + var _props2 = this.props; + var shouldPauseOnExceptions = _props2.shouldPauseOnExceptions; + var shouldIgnoreCaughtExceptions = _props2.shouldIgnoreCaughtExceptions; + var pauseOnExceptions = _props2.pauseOnExceptions; + + + if (!shouldPauseOnExceptions && !shouldIgnoreCaughtExceptions) { + return debugBtn(() => pauseOnExceptions(true, true), "pause-exceptions", "enabled", L10N.getStr("ignoreExceptions")); + } + + if (shouldPauseOnExceptions && shouldIgnoreCaughtExceptions) { + return debugBtn(() => pauseOnExceptions(true, false), "pause-exceptions", "uncaught enabled", L10N.getStr("pauseOnUncaughtExceptions")); + } + + return debugBtn(() => pauseOnExceptions(false, false), "pause-exceptions", "all enabled", L10N.getStr("pauseOnExceptions")); + }, + + renderDisableBreakpoints() { + var _props3 = this.props; + var toggleAllBreakpoints = _props3.toggleAllBreakpoints; + var breakpoints = _props3.breakpoints; + var breakpointsDisabled = _props3.breakpointsDisabled; + var breakpointsLoading = _props3.breakpointsLoading; + + + if (breakpoints.size == 0 || breakpointsLoading) { + return debugBtn(null, "toggleBreakpoints", "disabled", "Disable Breakpoints"); + } + + return debugBtn(() => toggleAllBreakpoints(!breakpointsDisabled), "toggleBreakpoints", breakpointsDisabled ? "breakpoints-disabled" : "", "Disable Breakpoints"); + }, + + getItems() { + var expressionInputVisibility = this.state.expressionInputVisibility; + + var items = [{ header: L10N.getStr("breakpoints.header"), + component: Breakpoints, + opened: true }, { header: L10N.getStr("callStack.header"), + component: Frames }, { header: L10N.getStr("scopes.header"), + component: Scopes }]; + if (isEnabled("watchExpressions")) { + items.unshift({ header: L10N.getStr("watchExpressions.header"), + buttons: [debugBtn(evt => { + evt.stopPropagation(); + this.props.evaluateExpressions(); + }, "domain", "accordion-button", "Refresh"), debugBtn(evt => { + evt.stopPropagation(); + this.setState({ + expressionInputVisibility: !expressionInputVisibility + }); + }, "file", "accordion-button", "Add Watch Expression")], + component: Expressions, + componentProps: { expressionInputVisibility }, + opened: true + }); + } + return items; + }, + + render() { + return dom.div({ className: "right-sidebar", + style: { overflowX: "hidden" } }, dom.div({ className: "command-bar" }, this.renderPauseButton(), this.renderStepButtons(), this.renderDisableBreakpoints(), this.renderPauseOnExceptions()), Accordion({ + items: this.getItems() + })); + } + + }); + + module.exports = connect(state => { + return { + pause: getPause(state), + isWaitingOnBreak: getIsWaitingOnBreak(state), + shouldPauseOnExceptions: getShouldPauseOnExceptions(state), + shouldIgnoreCaughtExceptions: getShouldIgnoreCaughtExceptions(state), + breakpointsDisabled: getBreakpointsDisabled(state), + breakpoints: getBreakpoints(state), + breakpointsLoading: getBreakpointsLoading(state) + }; + }, dispatch => bindActionCreators(actions, dispatch))(RightSidebar); + +/***/ }, +/* 417 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + + var _require = __webpack_require__(19); + + var connect = _require.connect; + + var _require2 = __webpack_require__(3); + + var bindActionCreators = _require2.bindActionCreators; + + var ImPropTypes = __webpack_require__(235); + var classnames = __webpack_require__(211); + var actions = __webpack_require__(262); + + var _require3 = __webpack_require__(259); + + var getSource = _require3.getSource; + var getPause = _require3.getPause; + var getBreakpoints = _require3.getBreakpoints; + + var _require4 = __webpack_require__(255); + + var makeLocationId = _require4.makeLocationId; + + var _require5 = __webpack_require__(244); + + var truncateStr = _require5.truncateStr; + var dom = React.DOM; + var PropTypes = React.PropTypes; + + var _require6 = __webpack_require__(244); + + var endTruncateStr = _require6.endTruncateStr; + + var _require7 = __webpack_require__(278); + + var basename = _require7.basename; + + var CloseButton = __webpack_require__(336); + + __webpack_require__(418); + + function isCurrentlyPausedAtBreakpoint(state, breakpoint) { + var pause = getPause(state); + if (!pause || pause.get("isInterrupted")) { + return false; + } + + var bpId = makeLocationId(breakpoint.location); + var pausedId = makeLocationId(pause.getIn(["frame", "location"]).toJS()); + + return bpId === pausedId; + } + + function renderSourceLocation(source, line) { + var url = source.get("url") ? basename(source.get("url")) : null; + // const line = url !== "" ? `: ${line}` : ""; + return url ? dom.div({ className: "location" }, `${ endTruncateStr(url, 30) }: ${ line }`) : null; + } + + var Breakpoints = React.createClass({ + propTypes: { + breakpoints: ImPropTypes.map.isRequired, + enableBreakpoint: PropTypes.func.isRequired, + disableBreakpoint: PropTypes.func.isRequired, + selectSource: PropTypes.func.isRequired, + removeBreakpoint: PropTypes.func.isRequired + }, + + displayName: "Breakpoints", + + handleCheckbox(breakpoint) { + if (breakpoint.loading) { + return; + } + + if (breakpoint.disabled) { + this.props.enableBreakpoint(breakpoint.location); + } else { + this.props.disableBreakpoint(breakpoint.location); + } + }, + + selectBreakpoint(breakpoint) { + var sourceId = breakpoint.location.sourceId; + var line = breakpoint.location.line; + this.props.selectSource(sourceId, { line }); + }, + + removeBreakpoint(event, breakpoint) { + event.stopPropagation(); + this.props.removeBreakpoint(breakpoint.location); + }, + + renderBreakpoint(breakpoint) { + var snippet = truncateStr(breakpoint.text || "", 30); + var locationId = breakpoint.locationId; + var line = breakpoint.location.line; + var isCurrentlyPaused = breakpoint.isCurrentlyPaused; + var isDisabled = breakpoint.disabled; + + return dom.div({ + className: classnames({ + breakpoint, + paused: isCurrentlyPaused, + disabled: isDisabled + }), + key: locationId, + onClick: () => this.selectBreakpoint(breakpoint) + }, dom.input({ + type: "checkbox", + className: "breakpoint-checkbox", + checked: !isDisabled, + onChange: () => this.handleCheckbox(breakpoint), + // Prevent clicking on the checkbox from triggering the onClick of + // the surrounding div + onClick: ev => ev.stopPropagation() + }), dom.div({ className: "breakpoint-label", title: breakpoint.text }, dom.div({}, renderSourceLocation(breakpoint.location.source, line))), dom.div({ className: "breakpoint-snippet" }, snippet), CloseButton({ + handleClick: ev => this.removeBreakpoint(ev, breakpoint) + })); + }, + + render() { + var breakpoints = this.props.breakpoints; + + return dom.div({ className: "pane breakpoints-list" }, breakpoints.size === 0 ? dom.div({ className: "pane-info" }, "No Breakpoints") : breakpoints.valueSeq().map(bp => { + return this.renderBreakpoint(bp); + })); + } + }); + + function _getBreakpoints(state) { + return getBreakpoints(state).map(bp => { + var source = getSource(state, bp.location.sourceId); + var isCurrentlyPaused = isCurrentlyPausedAtBreakpoint(state, bp); + var locationId = makeLocationId(bp.location); + + bp = Object.assign({}, bp); + bp.location.source = source; + bp.locationId = locationId; + bp.isCurrentlyPaused = isCurrentlyPaused; + return bp; + }).filter(bp => bp.location.source); + } + + module.exports = connect((state, props) => ({ + breakpoints: _getBreakpoints(state) + }), dispatch => bindActionCreators(actions, dispatch))(Breakpoints); + +/***/ }, +/* 418 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 419 */, +/* 420 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + + var _require = __webpack_require__(19); + + var connect = _require.connect; + + var _require2 = __webpack_require__(3); + + var bindActionCreators = _require2.bindActionCreators; + + var ImPropTypes = __webpack_require__(235); + var actions = __webpack_require__(262); + + var _require3 = __webpack_require__(259); + + var getExpressions = _require3.getExpressions; + var getPause = _require3.getPause; + + var Rep = React.createFactory(__webpack_require__(421)); + var CloseButton = React.createFactory(__webpack_require__(336)); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + + __webpack_require__(422); + + var Expressions = React.createClass({ + propTypes: { + expressions: ImPropTypes.list, + addExpression: PropTypes.func, + updateExpression: PropTypes.func, + deleteExpression: PropTypes.func, + expressionInputVisibility: PropTypes.bool, + loadObjectProperties: PropTypes.func, + loadedObjects: ImPropTypes.map + }, + + displayName: "Expressions", + + inputKeyPress(e, _ref) { + var id = _ref.id; + + if (e.key !== "Enter") { + return; + } + var addExpression = this.props.addExpression; + + var expression = { + input: e.target.value + }; + if (id !== undefined) { + expression.id = id; + } + e.target.value = ""; + addExpression(expression); + }, + + updateExpression(e, _ref2) { + var id = _ref2.id; + + e.stopPropagation(); + var updateExpression = this.props.updateExpression; + + var expression = { + id, + input: e.target.textContent + }; + updateExpression(expression); + }, + + renderExpressionValue(value) { + if (!value) { + return dom.span({ className: "expression-error" }, "<not available>"); + } + if (value.exception) { + return Rep({ object: value.exception }); + } + return Rep({ object: value.result }); + }, + + deleteExpression(e, expression) { + e.stopPropagation(); + var deleteExpression = this.props.deleteExpression; + + deleteExpression(expression); + }, + + renderExpressionUpdating(expression) { + return dom.span({ className: "expression-input-container" }, dom.input({ type: "text", + className: "input-expression", + onKeyPress: e => this.inputKeyPress(e, expression), + defaultValue: expression.input, + ref: c => { + this._input = c; + } + })); + }, + + renderExpression(expression) { + return dom.span({ className: "expression-output-container", + key: expression.id }, dom.span({ className: "expression-input", + onClick: e => this.updateExpression(e, expression) }, expression.input), dom.span({ className: "expression-seperator" }, ": "), dom.span({ className: "expression-value" }, this.renderExpressionValue(expression.value)), CloseButton({ handleClick: e => this.deleteExpression(e, expression) })); + }, + + renderExpressionContainer(expression) { + return dom.div({ className: "expression-container", + key: expression.id + expression.input }, expression.updating ? this.renderExpressionUpdating(expression) : this.renderExpression(expression)); + }, + + componentDidUpdate() { + if (this._input) { + this._input.focus(); + } + }, + + render() { + var expressions = this.props.expressions; + + return dom.span({ className: "pane expressions-list" }, this.props.expressionInputVisibility ? dom.input({ type: "text", + className: "input-expression", + placeholder: "Add Watch Expression", + onKeyPress: e => this.inputKeyPress(e, {}) }) : null, expressions.toSeq().map(expression => this.renderExpressionContainer(expression))); + } + }); + + module.exports = connect(state => ({ pauseInfo: getPause(state), + expressions: getExpressions(state) + }), dispatch => bindActionCreators(actions, dispatch))(Expressions); + +/***/ }, +/* 421 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + + var _require = __webpack_require__(30); + + var rep = _require.rep; + var Grip = _require.Grip; + + var Rep = React.createFactory(rep); + + function renderRep(_ref) { + var object = _ref.object; + var mode = _ref.mode; + + return Rep({ object, defaultRep: Grip, mode }); + } + + module.exports = renderRep; + +/***/ }, +/* 422 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 423 */, +/* 424 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + + var _require = __webpack_require__(3); + + var bindActionCreators = _require.bindActionCreators; + + var _require2 = __webpack_require__(19); + + var connect = _require2.connect; + + var ImPropTypes = __webpack_require__(235); + var actions = __webpack_require__(262); + + var _require3 = __webpack_require__(259); + + var getSelectedFrame = _require3.getSelectedFrame; + var getLoadedObjects = _require3.getLoadedObjects; + var getPause = _require3.getPause; + + var ObjectInspector = React.createFactory(__webpack_require__(425)); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + var toPairs = __webpack_require__(428); + + __webpack_require__(442); + + function info(text) { + return dom.div({ className: "pane-info" }, text); + } + + // Create the tree nodes representing all the variables and arguments + // for the bindings from a scope. + function getBindingVariables(bindings, parentName) { + var args = bindings.arguments.map(arg => toPairs(arg)[0]); + var variables = toPairs(bindings.variables); + + return args.concat(variables).filter(binding => !(binding[1].value.missingArguments || binding[1].value.optimizedOut)).map(binding => ({ + name: binding[0], + path: parentName + "/" + binding[0], + contents: binding[1] + })); + } + + function getSpecialVariables(pauseInfo, path) { + var thrown = pauseInfo.getIn(["why", "frameFinished", "throw"]); + var returned = pauseInfo.getIn(["why", "frameFinished", "return"]); + var vars = []; + + if (thrown) { + // handle dehydrating exception strings and errors. + thrown = thrown.toJS ? thrown.toJS() : thrown; + + vars.push({ + name: "<exception>", + path: path + "/<exception>", + contents: { value: thrown } + }); + } + + if (returned) { + vars.push({ + name: "<return>", + path: path + "/<return>", + contents: { value: returned.toJS() } + }); + } + + return vars; + } + + function getThisVariable(frame, path) { + var this_ = frame.this; + + if (!this_) { + return null; + } + + return { + name: "<this>", + path: path + "/<this>", + contents: { value: this_ } + }; + } + + function getScopes(pauseInfo, selectedFrame) { + if (!pauseInfo || !selectedFrame) { + return null; + } + + var selectedScope = selectedFrame.scope; + + if (!selectedScope) { + return null; + } + + var scopes = []; + + var scope = selectedScope; + var pausedScopeActor = pauseInfo.getIn(["frame", "scope"]).get("actor"); + + do { + var type = scope.type; + var key = scope.actor; + if (type === "function" || type === "block") { + var bindings = scope.bindings; + var title = void 0; + if (type === "function") { + title = scope.function.displayName || "(anonymous)"; + } else { + title = "Block"; + } + + var vars = getBindingVariables(bindings, title); + + // show exception, return, and this variables in innermost scope + if (scope.actor === pausedScopeActor) { + vars = vars.concat(getSpecialVariables(pauseInfo, key)); + } + + if (scope.actor === selectedScope.actor) { + var this_ = getThisVariable(selectedFrame, key); + + if (this_) { + vars.push(this_); + } + } + + if (vars && vars.length) { + vars.sort((a, b) => a.name.localeCompare(b.name)); + scopes.push({ name: title, path: key, contents: vars }); + } + } else if (type === "object") { + var value = scope.object; + // If this is the global window scope, mark it as such so that it will + // preview Window: Global instead of Window: Window + if (value.class === "Window") { + value = Object.assign({}, scope.object, { isGlobal: true }); + } + scopes.push({ + name: scope.object.class, + path: key, + contents: { value } + }); + } + } while (scope = scope.parent); // eslint-disable-line no-cond-assign + + return scopes; + } + + var Scopes = React.createClass({ + propTypes: { + pauseInfo: ImPropTypes.map, + loadedObjects: ImPropTypes.map, + loadObjectProperties: PropTypes.func, + selectedFrame: PropTypes.object + }, + + displayName: "Scopes", + + getInitialState() { + var _props = this.props; + var pauseInfo = _props.pauseInfo; + var selectedFrame = _props.selectedFrame; + + return { scopes: getScopes(pauseInfo, selectedFrame) }; + }, + + componentWillReceiveProps(nextProps) { + var _props2 = this.props; + var pauseInfo = _props2.pauseInfo; + var selectedFrame = _props2.selectedFrame; + + var pauseInfoChanged = pauseInfo !== nextProps.pauseInfo; + var selectedFrameChange = selectedFrame !== nextProps.selectedFrame; + + if (pauseInfoChanged || selectedFrameChange) { + this.setState({ + scopes: getScopes(nextProps.pauseInfo, nextProps.selectedFrame) + }); + } + }, + + render() { + var _props3 = this.props; + var pauseInfo = _props3.pauseInfo; + var loadObjectProperties = _props3.loadObjectProperties; + var loadedObjects = _props3.loadedObjects; + var scopes = this.state.scopes; + + + var scopeInspector = info(L10N.getStr("scopes.notAvailable")); + if (scopes) { + scopeInspector = ObjectInspector({ + roots: scopes, + getObjectProperties: id => loadedObjects.get(id), + loadObjectProperties: loadObjectProperties + }); + } + + return dom.div({ className: "pane scopes-list" }, pauseInfo ? scopeInspector : info(L10N.getStr("scopes.notPaused"))); + } + }); + + module.exports = connect(state => ({ + pauseInfo: getPause(state), + selectedFrame: getSelectedFrame(state), + loadedObjects: getLoadedObjects(state) + }), dispatch => bindActionCreators(actions, dispatch))(Scopes); + +/***/ }, +/* 425 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var classnames = __webpack_require__(211); + var ManagedTree = React.createFactory(__webpack_require__(394)); + var Svg = __webpack_require__(310); + var Rep = __webpack_require__(421); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + + __webpack_require__(426); + + // This implements a component that renders an interactive inspector + // for looking at JavaScript objects. It expects descriptions of + // objects from the protocol, and will dynamically fetch child + // properties as objects are expanded. + // + // If you want to inspect a single object, pass the name and the + // protocol descriptor of it: + // + // ObjectInspector({ + // name: "foo", + // desc: { writable: true, ..., { value: { actor: "1", ... }}}, + // ... + // }) + // + // If you want multiple top-level objects (like scopes), you can pass + // an array of manually constructed nodes as `roots`: + // + // ObjectInspector({ + // roots: [{ name: ... }, ...], + // ... + // }); + + // There are 3 types of nodes: a simple node with a children array, an + // object that has properties that should be children when they are + // fetched, and a primitive value that should be displayed with no + // children. + + function nodeHasChildren(item) { + return Array.isArray(item.contents); + } + + function nodeHasProperties(item) { + return !nodeHasChildren(item) && item.contents.value.type === "object"; + } + + function nodeIsPrimitive(item) { + return !nodeHasChildren(item) && !nodeHasProperties(item); + } + + function createNode(name, path, contents) { + // The path is important to uniquely identify the item in the entire + // tree. This helps debugging & optimizes React's rendering of large + // lists. The path will be separated by property name, + // i.e. `{ foo: { bar: { baz: 5 }}}` will have a path of `foo/bar/baz` + // for the inner object. + return { name, path, contents }; + } + + var ObjectInspector = React.createClass({ + propTypes: { + name: PropTypes.string, + desc: PropTypes.object, + roots: PropTypes.array, + getObjectProperties: PropTypes.func.isRequired, + loadObjectProperties: PropTypes.func.isRequired + }, + + displayName: "ObjectInspector", + + getInitialState() { + // Cache of dynamically built nodes. We shouldn't need to clear + // this out ever, since we don't ever "switch out" the object + // being inspected. + this.actorCache = {}; + return {}; + }, + + makeNodesForProperties(objProps, parentPath) { + var ownProperties = objProps.ownProperties; + var prototype = objProps.prototype; + + + var nodes = Object.keys(ownProperties).filter(name => { + // Ignore non-concrete values like getters and setters + // for now by making sure we have a value. + return "value" in ownProperties[name]; + }).map(name => { + return createNode(name, parentPath + "/" + name, ownProperties[name]); + }); + + // Add the prototype if it exists and is not null + if (prototype && prototype.type !== "null") { + nodes.push(createNode("__proto__", parentPath + "/__proto__", { value: prototype })); + } + + return nodes; + }, + + getChildren(item) { + var getObjectProperties = this.props.getObjectProperties; + + var obj = item.contents; + + // Nodes can either have children already, or be an object with + // properties that we need to go and fetch. + if (nodeHasChildren(item)) { + return item.contents; + } else if (nodeHasProperties(item)) { + var actor = obj.value.actor; + + // Because we are dynamically creating the tree as the user + // expands it (not precalcuated tree structure), we cache child + // arrays. This not only helps performance, but is necessary + // because the expanded state depends on instances of nodes + // being the same across renders. If we didn't do this, each + // node would be a new instance every render. + var key = item.path; + if (this.actorCache[key]) { + return this.actorCache[key]; + } + + var loadedProps = getObjectProperties(actor); + if (loadedProps) { + var children = this.makeNodesForProperties(loadedProps, item.path); + this.actorCache[actor] = children; + return children; + } + return []; + } + return []; + }, + + renderItem(item, depth, focused, _, expanded, _ref) { + var setExpanded = _ref.setExpanded; + + var objectValue = void 0; + if (nodeHasProperties(item) || nodeIsPrimitive(item)) { + var object = item.contents.value; + objectValue = Rep({ object, mode: "tiny" }); + } + + return dom.div({ className: classnames("node", { focused }), + style: { marginLeft: depth * 15 }, + onClick: e => { + e.stopPropagation(); + setExpanded(item, !expanded); + } + }, Svg("arrow", { + className: classnames({ + expanded: expanded, + hidden: nodeIsPrimitive(item) + }) + }), dom.span({ className: "object-label" }, item.name), dom.span({ className: "object-delimiter" }, objectValue ? ": " : ""), dom.span({ className: "object-value" }, objectValue || "")); + }, + + render() { + var _props = this.props; + var name = _props.name; + var desc = _props.desc; + var loadObjectProperties = _props.loadObjectProperties; + + + var roots = this.props.roots; + if (!roots) { + roots = [createNode(name, name, desc)]; + } + + return ManagedTree({ + itemHeight: 20, + getParent: item => null, + getChildren: this.getChildren, + getRoots: () => roots, + getKey: item => item.path, + autoExpand: 0, + disabledFocus: true, + onExpand: item => { + if (nodeHasProperties(item)) { + loadObjectProperties(item.contents.value); + } + }, + + renderItem: this.renderItem + }); + } + }); + + module.exports = ObjectInspector; + +/***/ }, +/* 426 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 427 */, +/* 428 */ +/***/ function(module, exports, __webpack_require__) { + + var createToPairs = __webpack_require__(429), + keys = __webpack_require__(439); + + /** + * Creates an array of own enumerable string keyed-value pairs for `object` + * which can be consumed by `_.fromPairs`. If `object` is a map or set, its + * entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entries + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairs(new Foo); + * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) + */ + var toPairs = createToPairs(keys); + + module.exports = toPairs; + + +/***/ }, +/* 429 */ +/***/ function(module, exports, __webpack_require__) { + + var baseToPairs = __webpack_require__(430), + getTag = __webpack_require__(431), + mapToArray = __webpack_require__(437), + setToPairs = __webpack_require__(438); + + /** `Object#toString` result references. */ + var mapTag = '[object Map]', + setTag = '[object Set]'; + + /** + * Creates a `_.toPairs` or `_.toPairsIn` function. + * + * @private + * @param {Function} keysFunc The function to get the keys of a given object. + * @returns {Function} Returns the new pairs function. + */ + function createToPairs(keysFunc) { + return function(object) { + var tag = getTag(object); + if (tag == mapTag) { + return mapToArray(object); + } + if (tag == setTag) { + return setToPairs(object); + } + return baseToPairs(object, keysFunc(object)); + }; + } + + module.exports = createToPairs; + + +/***/ }, +/* 430 */ +/***/ function(module, exports, __webpack_require__) { + + var arrayMap = __webpack_require__(135); + + /** + * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array + * of key-value pairs for `object` corresponding to the property names of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the key-value pairs. + */ + function baseToPairs(object, props) { + return arrayMap(props, function(key) { + return [key, object[key]]; + }); + } + + module.exports = baseToPairs; + + +/***/ }, +/* 431 */ +/***/ function(module, exports, __webpack_require__) { + + var DataView = __webpack_require__(432), + Map = __webpack_require__(125), + Promise = __webpack_require__(433), + Set = __webpack_require__(434), + WeakMap = __webpack_require__(435), + baseGetTag = __webpack_require__(436), + toSource = __webpack_require__(111); + + /** `Object#toString` result references. */ + var mapTag = '[object Map]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + setTag = '[object Set]', + weakMapTag = '[object WeakMap]'; + + var dataViewTag = '[object DataView]'; + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var objectToString = objectProto.toString; + + /** Used to detect maps, sets, and weakmaps. */ + var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); + + /** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + var getTag = baseGetTag; + + // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. + if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = objectToString.call(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : undefined; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; + } + + module.exports = getTag; + + +/***/ }, +/* 432 */ +/***/ function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(103), + root = __webpack_require__(109); + + /* Built-in method references that are verified to be native. */ + var DataView = getNative(root, 'DataView'); + + module.exports = DataView; + + +/***/ }, +/* 433 */ +/***/ function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(103), + root = __webpack_require__(109); + + /* Built-in method references that are verified to be native. */ + var Promise = getNative(root, 'Promise'); + + module.exports = Promise; + + +/***/ }, +/* 434 */ +/***/ function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(103), + root = __webpack_require__(109); + + /* Built-in method references that are verified to be native. */ + var Set = getNative(root, 'Set'); + + module.exports = Set; + + +/***/ }, +/* 435 */ +/***/ function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(103), + root = __webpack_require__(109); + + /* Built-in method references that are verified to be native. */ + var WeakMap = getNative(root, 'WeakMap'); + + module.exports = WeakMap; + + +/***/ }, +/* 436 */ +/***/ function(module, exports) { + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var objectToString = objectProto.toString; + + /** + * The base implementation of `getTag`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + return objectToString.call(value); + } + + module.exports = baseGetTag; + + +/***/ }, +/* 437 */ +/***/ function(module, exports) { + + /** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ + function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; + } + + module.exports = mapToArray; + + +/***/ }, +/* 438 */ +/***/ function(module, exports) { + + /** + * Converts `set` to its value-value pairs. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the value-value pairs. + */ + function setToPairs(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = [value, value]; + }); + return result; + } + + module.exports = setToPairs; + + +/***/ }, +/* 439 */ +/***/ function(module, exports, __webpack_require__) { + + var arrayLikeKeys = __webpack_require__(379), + baseKeys = __webpack_require__(440), + isArrayLike = __webpack_require__(367); + + /** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ + function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); + } + + module.exports = keys; + + +/***/ }, +/* 440 */ +/***/ function(module, exports, __webpack_require__) { + + var isPrototype = __webpack_require__(363), + nativeKeys = __webpack_require__(441); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; + } + + module.exports = baseKeys; + + +/***/ }, +/* 441 */ +/***/ function(module, exports, __webpack_require__) { + + var overArg = __webpack_require__(7); + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeKeys = overArg(Object.keys, Object); + + module.exports = nativeKeys; + + +/***/ }, +/* 442 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 443 */, +/* 444 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + var div = dom.div; + + var _require = __webpack_require__(3); + + var bindActionCreators = _require.bindActionCreators; + + var _require2 = __webpack_require__(19); + + var connect = _require2.connect; + + var ImPropTypes = __webpack_require__(235); + var actions = __webpack_require__(262); + + var _require3 = __webpack_require__(244); + + var endTruncateStr = _require3.endTruncateStr; + + var _require4 = __webpack_require__(277); + + var getFilename = _require4.getFilename; + + var _require5 = __webpack_require__(259); + + var getFrames = _require5.getFrames; + var getSelectedFrame = _require5.getSelectedFrame; + var getSource = _require5.getSource; + + + if (typeof window == "object") { + __webpack_require__(445); + } + + var NUM_FRAMES_SHOWN = 7; + + function renderFrameTitle(frame) { + return div({ className: "title" }, endTruncateStr(frame.displayName, 40)); + } + + function renderFrameLocation(frame) { + var filename = getFilename(frame.source); + return div({ className: "location" }, `${ filename }: ${ frame.location.line }`); + } + + var Frames = React.createClass({ + propTypes: { + frames: ImPropTypes.list, + selectedFrame: PropTypes.object, + selectFrame: PropTypes.func.isRequired + }, + + displayName: "Frames", + + getInitialState() { + return { showAllFrames: false }; + }, + + toggleFramesDisplay() { + this.setState({ + showAllFrames: !this.state.showAllFrames + }); + }, + + renderFrame(frame) { + var _props = this.props; + var selectedFrame = _props.selectedFrame; + var selectFrame = _props.selectFrame; + + + var selectedClass = selectedFrame && (selectedFrame.id === frame.id ? "selected" : ""); + + return dom.li({ key: frame.id, + className: `frame ${ selectedClass }`, + onMouseDown: () => selectFrame(frame), + tabIndex: 0 + }, renderFrameTitle(frame), renderFrameLocation(frame)); + }, + + renderFrames() { + var frames = this.props.frames; + + if (!frames) { + return null; + } + + var numFramesToShow = this.state.showAllFrames ? frames.size : NUM_FRAMES_SHOWN; + frames = frames.slice(0, numFramesToShow); + + return dom.ul({}, frames.map(frame => this.renderFrame(frame))); + }, + + renderToggleButton() { + var frames = this.props.frames; + + var buttonMessage = this.state.showAllFrames ? L10N.getStr("callStack.collapse") : L10N.getStr("callStack.expand"); + + if (frames.size < NUM_FRAMES_SHOWN) { + return null; + } + + return dom.div({ className: "show-more", onClick: this.toggleFramesDisplay }, buttonMessage); + }, + + render() { + var frames = this.props.frames; + + + if (!frames) { + return div({ className: "pane frames" }, div({ className: "pane-info empty" }, L10N.getStr("callStack.notPaused"))); + } + + return div({ className: "pane frames" }, this.renderFrames(), this.renderToggleButton()); + } + }); + + function getAndProcessFrames(state) { + var frames = getFrames(state); + if (!frames) { + return null; + } + return frames.filter(frame => getSource(state, frame.location.sourceId)).map(frame => Object.assign({}, frame, { + source: getSource(state, frame.location.sourceId).toJS() + })); + } + + module.exports = connect(state => ({ + frames: getAndProcessFrames(state), + selectedFrame: getSelectedFrame(state) + }), dispatch => bindActionCreators(actions, dispatch))(Frames); + +/***/ }, +/* 445 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 446 */, +/* 447 */ +/***/ function(module, exports, __webpack_require__) { + + function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + var div = dom.div; + var span = dom.span; + + var Svg = __webpack_require__(310); + + __webpack_require__(448); + + var Accordion = React.createClass({ + propTypes: { + items: PropTypes.array + }, + + displayName: "Accordion", + + getInitialState: function () { + return { opened: this.props.items.map(item => item.opened), + created: [] }; + }, + + handleHeaderClick: function (i) { + var opened = [].concat(_toConsumableArray(this.state.opened)); + var created = [].concat(_toConsumableArray(this.state.created)); + var item = this.props.items[i]; + + opened[i] = !opened[i]; + created[i] = true; + + if (opened[i] && item.onOpened) { + item.onOpened(); + } + + this.setState({ opened, created }); + }, + + renderContainer: function (item, i) { + var _state = this.state; + var opened = _state.opened; + var created = _state.created; + + var containerClassName = item.header.toLowerCase().replace(/\s/g, "-") + "-pane"; + + return div({ className: containerClassName, key: i }, div({ className: "_header", + onClick: () => this.handleHeaderClick(i) }, Svg("arrow", { className: opened[i] ? "expanded" : "" }), item.header, item.buttons ? dom.span({ className: "header-buttons" }, item.buttons.map((button, id) => span({ key: id }, button))) : null), created[i] || opened[i] ? div({ className: "_content", + style: { display: opened[i] ? "block" : "none" } + }, React.createElement(item.component, item.componentProps || {})) : null); + }, + + render: function () { + return div({ className: "accordion" }, this.props.items.map(this.renderContainer)); + } + }); + + module.exports = Accordion; + +/***/ }, +/* 448 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 449 */, +/* 450 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 451 */, +/* 452 */ +/***/ function(module, exports, __webpack_require__) { + + function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + var ImPropTypes = __webpack_require__(235); + + var _require = __webpack_require__(19); + + var connect = _require.connect; + + var _require2 = __webpack_require__(3); + + var bindActionCreators = _require2.bindActionCreators; + + var _require3 = __webpack_require__(259); + + var getSelectedSource = _require3.getSelectedSource; + var getSourceTabs = _require3.getSourceTabs; + var getFileSearchState = _require3.getFileSearchState; + + var _require4 = __webpack_require__(277); + + var getFilename = _require4.getFilename; + + var classnames = __webpack_require__(211); + var actions = __webpack_require__(262); + + var _require5 = __webpack_require__(89); + + var isEnabled = _require5.isEnabled; + + var CloseButton = __webpack_require__(336); + var Svg = __webpack_require__(310); + var Dropdown = React.createFactory(__webpack_require__(453)); + + var _require6 = __webpack_require__(413); + + var showMenu = _require6.showMenu; + var buildMenu = _require6.buildMenu; + + + __webpack_require__(454); + __webpack_require__(456); + + /* + * Finds the hidden tabs by comparing the tabs' top offset. + * hidden tabs will have a great top offset. + * + * @param sourceTabs Immutable.list + * @param sourceTabEls HTMLCollection + * + * @returns Immutable.list + */ + function getHiddenTabs(sourceTabs, sourceTabEls) { + sourceTabEls = [].slice.call(sourceTabEls); + function getTopOffset() { + var topOffsets = sourceTabEls.map(t => t.getBoundingClientRect().top); + return Math.min.apply(Math, _toConsumableArray(topOffsets)); + } + + var tabTopOffset = getTopOffset(); + return sourceTabs.filter((tab, index) => { + return sourceTabEls[index].getBoundingClientRect().top > tabTopOffset; + }); + } + + var SourceTabs = React.createClass({ + propTypes: { + sourceTabs: ImPropTypes.list, + selectedSource: ImPropTypes.map, + selectSource: PropTypes.func.isRequired, + closeTab: PropTypes.func.isRequired, + toggleFileSearch: PropTypes.func.isRequired + }, + + displayName: "SourceTabs", + + getInitialState() { + return { + dropdownShown: false, + hiddenSourceTabs: null + }; + }, + + componentDidUpdate() { + this.updateHiddenSourceTabs(this.props.sourceTabs); + }, + + onTabContextMenu(event, tab) { + event.preventDefault(); + this.showContextMenu(event, tab); + }, + + showContextMenu(e, tab) { + var _props = this.props; + var closeTab = _props.closeTab; + var sourceTabs = _props.sourceTabs; + + + var closeTabLabel = L10N.getStr("sourceTabs.closeTab"); + var closeOtherTabsLabel = L10N.getStr("sourceTabs.closeOtherTabs"); + var closeTabsToRightLabel = L10N.getStr("sourceTabs.closeTabsToRight"); + var closeAllTabsLabel = L10N.getStr("sourceTabs.closeAllTabs"); + + var tabs = sourceTabs.map(t => t.get("id")); + + var closeTabMenuItem = { + id: "node-menu-close-tab", + label: closeTabLabel, + accesskey: "C", + disabled: false, + click: () => closeTab(tab) + }; + + var closeOtherTabsMenuItem = { + id: "node-menu-close-other-tabs", + label: closeOtherTabsLabel, + accesskey: "O", + disabled: false, + click: () => { + tabs.forEach(t => { + if (t !== tab) { + closeTab(t); + } + }); + } + }; + + var closeTabsToRightMenuItem = { + id: "node-menu-close-tabs-to-right", + label: closeTabsToRightLabel, + accesskey: "R", + disabled: false, + click: () => { + tabs.reverse().every(t => { + if (t === tab) { + return false; + } + closeTab(t); + return true; + }); + } + }; + + var closeAllTabsMenuItem = { + id: "node-menu-close-all-tabs", + label: closeAllTabsLabel, + accesskey: "A", + disabled: false, + click: () => tabs.forEach(closeTab) + }; + + showMenu(e, buildMenu([{ item: closeTabMenuItem }, { item: closeOtherTabsMenuItem, hidden: () => tabs.size === 1 }, { item: closeTabsToRightMenuItem, hidden: () => tabs.some((t, i) => t === tab && tabs.size - 1 === i) }, { item: closeAllTabsMenuItem }])); + }, + + /* + * Updates the hiddenSourceTabs state, by + * finding the source tabs who have wrapped and are not on the top row. + */ + updateHiddenSourceTabs(sourceTabs) { + if (!this.refs.sourceTabs) { + return; + } + + var sourceTabEls = this.refs.sourceTabs.children; + var hiddenSourceTabs = getHiddenTabs(sourceTabs, sourceTabEls); + + if (!hiddenSourceTabs.equals(this.state.hiddenSourceTabs)) { + this.setState({ hiddenSourceTabs }); + } + }, + + toggleSourcesDropdown(e) { + this.setState({ + dropdownShown: !this.state.dropdownShown + }); + }, + + renderDropdownSource(source) { + var selectSource = this.props.selectSource; + + var filename = getFilename(source.toJS()); + + return dom.li({ + key: source.get("id"), + onClick: () => { + // const tabIndex = getLastVisibleTabIndex(sourceTabs, sourceTabEls); + var tabIndex = 0; + selectSource(source.get("id"), { tabIndex }); + } + }, filename); + }, + + renderTabs() { + var sourceTabs = this.props.sourceTabs; + return dom.div({ className: "source-tabs", ref: "sourceTabs" }, sourceTabs.map(this.renderTab)); + }, + + renderTab(source) { + var _props2 = this.props; + var selectedSource = _props2.selectedSource; + var selectSource = _props2.selectSource; + var closeTab = _props2.closeTab; + + var filename = getFilename(source.toJS()); + var active = source.get("id") == selectedSource.get("id"); + + function onClickClose(ev) { + ev.stopPropagation(); + closeTab(source.get("id")); + } + + return dom.div({ + className: classnames("source-tab", { active }), + key: source.get("id"), + onClick: () => selectSource(source.get("id")), + onContextMenu: e => this.onTabContextMenu(e, source.get("id")), + title: source.get("url") + }, dom.div({ className: "filename" }, filename), CloseButton({ handleClick: onClickClose })); + }, + + renderNewButton() { + return dom.div({ + className: "new-tab-btn", + onClick: () => this.props.toggleFileSearch(true) + }, Svg("plus")); + }, + + renderDropdown() { + var hiddenSourceTabs = this.state.hiddenSourceTabs; + if (!hiddenSourceTabs || hiddenSourceTabs.size == 0) { + return dom.div({}); + } + + return Dropdown({ + panel: dom.ul({}, this.state.hiddenSourceTabs.map(this.renderDropdownSource)) + }); + }, + + render() { + if (!isEnabled("tabs")) { + return dom.div({ className: "source-header" }); + } + + return dom.div({ className: "source-header" }, this.renderTabs(), this.renderNewButton(), this.renderDropdown()); + } + }); + + module.exports = connect(state => ({ + selectedSource: getSelectedSource(state), + sourceTabs: getSourceTabs(state), + searchOn: getFileSearchState(state) + }), dispatch => bindActionCreators(actions, dispatch))(SourceTabs); + +/***/ }, +/* 453 */ +/***/ function(module, exports, __webpack_require__) { + + var React = __webpack_require__(2); + var dom = React.DOM; + var PropTypes = React.PropTypes; + + + var Dropdown = React.createClass({ + propTypes: { + panel: PropTypes.object + }, + + displayName: "Dropdown", + + getInitialState() { + return { + dropdownShown: false + }; + }, + + toggleDropdown(e) { + this.setState({ + dropdownShown: !this.state.dropdownShown + }); + }, + + renderPanel() { + return dom.div({ + className: "dropdown", + onClick: this.toggleDropdown, + style: { display: this.state.dropdownShown ? "block" : "none" } + }, this.props.panel); + }, + + renderButton() { + return dom.span({ + className: "dropdown-button", + onClick: this.toggleDropdown + }, "»"); + }, + + renderMask() { + return dom.div({ + className: "dropdown-mask", + onClick: this.toggleDropdown, + style: { display: this.state.dropdownShown ? "block" : "none" } + }); + }, + + render() { + return dom.div({}, this.renderPanel(), this.renderButton(), this.renderMask()); + } + + }); + + module.exports = Dropdown; + +/***/ }, +/* 454 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 455 */, +/* 456 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ }, +/* 457 */, +/* 458 */ +/***/ function(module, exports) { + + module.exports = { + "breakpoints.header": "Breakpoints", + "callStack.header": "Call Stack", + "callStack.notPaused": "Not Paused", + "callStack.collapse": "Collapse Rows", + "callStack.expand": "Expand Rows", + "editor.searchResults": "%d of %d results", + "editor.noResults": "no results", + "editor.addBreakpoint": "Add Breakpoint", + "editor.removeBreakpoint": "Remove Breakpoint", + "editor.editBreakpoint": "Edit Breakpoint", + "editor.addConditionalBreakpoint": "Add Conditional Breakpoint", + "scopes.header": "Scopes", + "scopes.notAvailable": "Scopes Unavailable", + "scopes.notPaused": "Not Paused", + "sources.header": "Sources", + "sources.search": "%S to search", + "watchExpressions.header": "Watch Expressions", + "welcome.search": "%S to search for files", + "sourceSearch.search": "Search...", + "sourceSearch.resultsSummary": "%d instances of \"%S\"", + "sourceSearch.noResults": "No files matching %S found", + "ignoreExceptions": "Ignore exceptions. Click to pause on uncaught exceptions", + "pauseOnUncaughtExceptions": "Pause on uncaught exceptions. Click to pause on all exceptions", + "pauseOnExceptions": "Pause on all exceptions. Click to ignore exceptions", + "stepOutTooltip": "Step Out (%SF11)", + "stepInTooltip": "Step In (%SF11)", + "stepOverTooltip": "Step Over (F10)", + "resumeButtonTooltip": "Click to resume (F8)", + "pausePendingButtonTooltip": "Waiting for next execution", + "pauseButtonTooltip": "Click to pause (F8)", + "sourceTabs.closeTab": "Close tab", + "sourceTabs.closeOtherTabs": "Close others", + "sourceTabs.closeTabsToRight": "Close tabs to the right", + "sourceTabs.closeAllTabs": "Close all tabs" + }; + +/***/ }, +/* 459 */ +/***/ function(module, exports, __webpack_require__) { + + function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + + var _require = __webpack_require__(30); + + var sprintf = _require.sprintf; + + var strings = {}; + + function setBundle(bundle) { + strings = bundle; + } + + function getStr(key) { + if (!strings[key]) { + throw new Error(`L10N key ${ key } cannot be found.`); + } + return strings[key]; + } + + function getFormatStr(name) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + return sprintf.apply(undefined, [getStr(name)].concat(_toConsumableArray(args))); + } + + module.exports = { + getStr, + getFormatStr, + setBundle + }; + +/***/ } +/******/ ]); +//# sourceMappingURL=bundle.js.map diff --git a/devtools/client/debugger/new/images/Icons.js b/devtools/client/debugger/new/images/Icons.js new file mode 100644 index 000000000..bda48ef93 --- /dev/null +++ b/devtools/client/debugger/new/images/Icons.js @@ -0,0 +1,46 @@ +const React = require("react"); +const InlineSVG = require("svg-inline-react"); +const { DOM: dom } = React; + +const DomainIcon = props => { + return dom.span( + props, + React.createElement(InlineSVG, { + src: require("./domain.svg") + }) + ); +}; + +const FileIcon = props => { + return dom.span( + props, + React.createElement(InlineSVG, { + src: require("./file.svg") + }) + ); +}; + +const FolderIcon = props => { + return dom.span( + props, + React.createElement(InlineSVG, { + src: require("./folder.svg") + }) + ); +}; + +const WorkerIcon = props => { + return dom.span( + props, + React.createElement(InlineSVG, { + src: require("./worker.svg") + }) + ); +}; + +module.exports = { + DomainIcon, + FileIcon, + FolderIcon, + WorkerIcon +}; diff --git a/devtools/client/debugger/new/images/Svg.js b/devtools/client/debugger/new/images/Svg.js new file mode 100644 index 000000000..775aecfc0 --- /dev/null +++ b/devtools/client/debugger/new/images/Svg.js @@ -0,0 +1,43 @@ +const React = require("react"); +const InlineSVG = require("svg-inline-react"); + +const svg = { + "angle-brackets": require("./angle-brackets.svg"), + "arrow": require("./arrow.svg"), + "blackBox": require("./blackBox.svg"), + "breakpoint": require("./breakpoint.svg"), + "close": require("./close.svg"), + "domain": require("./domain.svg"), + "file": require("./file.svg"), + "folder": require("./folder.svg"), + "globe": require("./globe.svg"), + "magnifying-glass": require("./magnifying-glass.svg"), + "pause": require("./pause.svg"), + "pause-exceptions": require("./pause-exceptions.svg"), + "plus": require("./plus.svg"), + "prettyPrint": require("./prettyPrint.svg"), + "resume": require("./resume.svg"), + "settings": require("./settings.svg"), + "stepIn": require("./stepIn.svg"), + "stepOut": require("./stepOut.svg"), + "stepOver": require("./stepOver.svg"), + "subSettings": require("./subSettings.svg"), + "toggleBreakpoints": require("./toggle-breakpoints.svg"), + "worker": require("./worker.svg"), + "sad-face": require("./sad-face.svg") +}; + +module.exports = function(name, props) { // eslint-disable-line + if (!svg[name]) { + throw new Error("Unknown SVG: " + name); + } + let className = name; + if (props && props.className) { + className = `${name} ${props.className}`; + } + if (name === "subSettings") { + className = ""; + } + props = Object.assign({}, props, { className, src: svg[name] }); + return React.createElement(InlineSVG, props); +}; diff --git a/devtools/client/debugger/new/images/angle-brackets.svg b/devtools/client/debugger/new/images/angle-brackets.svg new file mode 100644 index 000000000..b353bee9e --- /dev/null +++ b/devtools/client/debugger/new/images/angle-brackets.svg @@ -0,0 +1,9 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16px" height="11px" viewBox="-1 73 16 11" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <g id="Shape-Copy-3-+-Shape-Copy-4" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 74.000000)"> + <path d="M0.749321284,4.16081709 L4.43130681,0.242526751 C4.66815444,-0.00952143591 5.06030999,-0.0211407611 5.30721074,0.216574262 C5.55411149,0.454289284 5.56226116,0.851320812 5.32541353,1.103369 L1.95384971,4.69131519 L5.48809879,8.09407556 C5.73499955,8.33179058 5.74314922,8.72882211 5.50630159,8.9808703 C5.26945396,9.23291849 4.87729841,9.24453781 4.63039766,9.00682279 L0.827097345,5.34502101 C0.749816996,5.31670099 0.677016974,5.27216098 0.613753508,5.21125118 C0.427367989,5.03179997 0.377040713,4.7615583 0.465458792,4.53143559 C0.492371834,4.43667624 0.541703274,4.34676528 0.613628034,4.27022448 C0.654709457,4.22650651 0.70046335,4.19002189 0.749321284,4.16081709 Z" id="Shape-Copy-3" stroke="#FFFFFF" stroke-width="0.05" fill="#DDE1E4"></path> + <path d="M13.7119065,5.44453032 L9.77062746,9.09174784 C9.51677479,9.3266604 9.12476399,9.31089603 8.89504684,9.05653714 C8.66532968,8.80217826 8.68489539,8.40554539 8.93874806,8.17063283 L12.5546008,4.82456128 L9.26827469,1.18571135 C9.03855754,0.931352463 9.05812324,0.534719593 9.31197591,0.299807038 C9.56582858,0.0648944831 9.95783938,0.0806588502 10.1875565,0.335017737 L13.72891,4.25625178 C13.8013755,4.28980469 13.8684335,4.3382578 13.9254821,4.40142604 C14.0883019,4.58171146 14.1258883,4.83347168 14.0435812,5.04846202 C14.0126705,5.15680232 13.9526426,5.2583679 13.8641331,5.34027361 C13.8174417,5.38348136 13.7660763,5.41820853 13.7119065,5.44453032 Z" id="Shape-Copy-4" stroke="#FFFFFF" stroke-width="0.05" fill="#DDE1E4"></path> + </g> +</svg> diff --git a/devtools/client/debugger/new/images/arrow.svg b/devtools/client/debugger/new/images/arrow.svg new file mode 100644 index 000000000..33a107797 --- /dev/null +++ b/devtools/client/debugger/new/images/arrow.svg @@ -0,0 +1,6 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16"> + <path d="M8 13.4c-.5 0-.9-.2-1.2-.6L.4 5.2C0 4.7-.1 4.3.2 3.7S1 3 1.6 3h12.8c.6 0 1.2.1 1.4.7.3.6.2 1.1-.2 1.6l-6.4 7.6c-.3.4-.7.5-1.2.5z"/> +</svg>
\ No newline at end of file diff --git a/devtools/client/debugger/new/images/blackBox.svg b/devtools/client/debugger/new/images/blackBox.svg new file mode 100644 index 000000000..b98d62f13 --- /dev/null +++ b/devtools/client/debugger/new/images/blackBox.svg @@ -0,0 +1,9 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <g fill-rule="evenodd"> + <circle cx="8" cy="8.5" r="1.5"/> + <path d="M15.498 8.28l-.001-.03v-.002-.004l-.002-.018-.004-.031c0-.002 0-.002 0 0l-.004-.035.006.082c-.037-.296-.133-.501-.28-.661-.4-.522-.915-1.042-1.562-1.604-1.36-1.182-2.74-1.975-4.178-2.309a6.544 6.544 0 0 0-2.755-.042c-.78.153-1.565.462-2.369.91C3.252 5.147 2.207 6 1.252 7.035c-.216.233-.36.398-.499.577-.338.437-.338 1 0 1.437.428.552.941 1.072 1.59 1.635 1.359 1.181 2.739 1.975 4.177 2.308.907.21 1.829.223 2.756.043.78-.153 1.564-.462 2.369-.91 1.097-.612 2.141-1.464 3.097-2.499.217-.235.36-.398.498-.578.12-.128.216-.334.248-.554 0 .01 0 .01-.008.04l.013-.079-.001.011.003-.031.001-.017v.005l.001-.02v.008l.002-.03.001-.05-.001-.044v-.004-.004zm-.954.045v.007l.001.004V8.33v.012l-.001.01v-.005-.005l.002-.015-.001.008c-.002.014-.002.014 0 0l-.007.084c.003-.057-.004-.041-.014-.031-.143.182-.27.327-.468.543-.89.963-1.856 1.752-2.86 2.311-.724.404-1.419.677-2.095.81a5.63 5.63 0 0 1-2.374-.036c-1.273-.295-2.523-1.014-3.774-2.101-.604-.525-1.075-1.001-1.457-1.496-.054-.07-.054-.107 0-.177.117-.152.244-.298.442-.512.89-.963 1.856-1.752 2.86-2.311.724-.404 1.419-.678 2.095-.81a5.631 5.631 0 0 1 2.374.036c1.272.295 2.523 1.014 3.774 2.101.603.524 1.074 1 1.457 1.496.035.041.043.057.046.076 0 .01 0 .01.008.043l-.009-.047.003.02-.002-.013v-.008.016c0-.004 0-.004 0 0v-.004z"/> + </g> +</svg> diff --git a/devtools/client/debugger/new/images/breakpoint.svg b/devtools/client/debugger/new/images/breakpoint.svg new file mode 100644 index 000000000..f0e5de106 --- /dev/null +++ b/devtools/client/debugger/new/images/breakpoint.svg @@ -0,0 +1,6 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 60 12"> + <path id="base-path" d="M53.9,0H1C0.4,0,0,0.4,0,1v10c0,0.6,0.4,1,1,1h52.9c0.6,0,1.2-0.3,1.5-0.7L60,6l-4.4-5.3C55,0.3,54.5,0,53.9,0z"/> +</svg> diff --git a/devtools/client/debugger/new/images/close.svg b/devtools/client/debugger/new/images/close.svg new file mode 100644 index 000000000..7efd07f80 --- /dev/null +++ b/devtools/client/debugger/new/images/close.svg @@ -0,0 +1,7 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16px" height="16px" viewBox="0 0 6 6" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <path d="M1.35191454,5.27895256 L5.31214367,1.35518468 C5.50830675,1.16082764 5.50977084,0.844248536 5.3154138,0.648085456 C5.12105677,0.451922377 4.80447766,0.450458288 4.60831458,0.644815324 L0.648085456,4.56858321 C0.451922377,4.76294025 0.450458288,5.07951935 0.644815324,5.27568243 C0.83917236,5.47184551 1.15575146,5.4733096 1.35191454,5.27895256 L1.35191454,5.27895256 Z" id="Line" stroke="none" fill="#696969" fill-rule="evenodd"></path> + <path d="M5.31214367,4.56858321 L1.35191454,0.644815324 C1.15575146,0.450458288 0.83917236,0.451922377 0.644815324,0.648085456 C0.450458288,0.844248536 0.451922377,1.16082764 0.648085456,1.35518468 L4.60831458,5.27895256 C4.80447766,5.4733096 5.12105677,5.47184551 5.3154138,5.27568243 C5.50977084,5.07951935 5.50830675,4.76294025 5.31214367,4.56858321 L5.31214367,4.56858321 Z" id="Line-Copy-2" stroke="none" fill="#696969" fill-rule="evenodd"></path> +</svg> diff --git a/devtools/client/debugger/new/images/disableBreakpoints.svg b/devtools/client/debugger/new/images/disableBreakpoints.svg new file mode 100644 index 000000000..bdf28ffcf --- /dev/null +++ b/devtools/client/debugger/new/images/disableBreakpoints.svg @@ -0,0 +1,8 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="##4A464C"> + <g fill-rule="evenodd"> + <path d="M3.233 11.25l-.417 1H1.712C.763 12.25 0 11.574 0 10.747V6.503C0 5.675.755 5 1.712 5h4.127l-.417 1H1.597C1.257 6 1 6.225 1 6.503v4.244c0 .277.267.503.597.503h1.636zM7.405 11.27L7 12.306c.865.01 2.212-.024 2.315-.04.112-.016.112-.016.185-.035.075-.02.156-.046.251-.082.152-.056.349-.138.592-.244.415-.182.962-.435 1.612-.744l.138-.066a179.35 179.35 0 0 0 2.255-1.094c1.191-.546 1.191-2.074-.025-2.632l-.737-.34a3547.554 3547.554 0 0 0-3.854-1.78c-.029.11-.065.222-.11.336l-.232.596c.894.408 4.56 2.107 4.56 2.107.458.21.458.596 0 .806L9.197 11.27H7.405zM4.462 14.692l5-12a.5.5 0 1 0-.924-.384l-5 12a.5.5 0 1 0 .924.384z"/> + </g> +</svg> diff --git a/devtools/client/debugger/new/images/domain.svg b/devtools/client/debugger/new/images/domain.svg new file mode 100644 index 000000000..f00c9b37d --- /dev/null +++ b/devtools/client/debugger/new/images/domain.svg @@ -0,0 +1,7 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <path d="M9.05 4.634l-2.144.003-.116.116v1.445l.92.965.492.034.116-.116v-.617L9.13 5.7l.035-.95M12.482 10.38l-1.505-1.462H9.362l-.564.516-.034 1.108.72.768 1.323.034-.117-.116v1.2l.972 1.02.315.034.116-.116v-1.154l.422-.374.034-.927-.117.117h.26l.408-.36V10.5l-.125-.124-.575-.033"/> + <path d="M8.47 15.073c-3.088 0-5.6-2.513-5.6-5.602V9.4v-.003c0-.018 0-.018.002-.034l.182-.088.724.587.49.033.497.543-.034.9.317.383h.47l.114.096-.032 1.9.524.553h.105l.025-.338 1.004-.95.054-.474.53-.462v-.888l-.588-.038-1.118-1.155H4.48l-.154-.09V9.01l.155-.1h1.164v-.273l.12-.115.7.033.494-.443.034-.746-.624-.655h-.724v.28l-.11.07H4.64l-.114-.09.025-.64.48-.43v-.244h-.382c-.102 0-.152-.128-.08-.2 1.04-1.01 2.428-1.59 3.903-1.59 1.374 0 2.672.5 3.688 1.39.08.068.03.198-.075.198l-1.144-.034-.81.803.52.523v.16l-.382.388h-.158l-.176-.177v-.16l.076-.074-.252-.252-.37.362.53.53c.072.072.005.194-.096.194l-.752-.005v.844h.783L9.885 8l.16-.143h.16l.62.61v.267l.58.027.003.002V8.76l.18-.03 1.234 1.24.753-.708h.382l.116.108c0 .02.003.016.003.036v.065c0 3.09-2.515 5.603-5.605 5.603M8.47 3C4.904 3 2 5.903 2 9.47c0 3.57 2.903 6.472 6.47 6.472 3.57 0 6.472-2.903 6.472-6.47C14.942 5.9 12.04 3 8.472 3"/> +</svg> diff --git a/devtools/client/debugger/new/images/favicon.png b/devtools/client/debugger/new/images/favicon.png new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/devtools/client/debugger/new/images/favicon.png diff --git a/devtools/client/debugger/new/images/file.svg b/devtools/client/debugger/new/images/file.svg new file mode 100644 index 000000000..7f5a70855 --- /dev/null +++ b/devtools/client/debugger/new/images/file.svg @@ -0,0 +1,7 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <path d="M4 2v12h9V4.775L9.888 2H4zm0-1h5.888c.246 0 .483.09.666.254l3.112 2.774c.212.19.334.462.334.747V14c0 .552-.448 1-1 1H4c-.552 0-1-.448-1-1V2c0-.552.448-1 1-1z"/> + <path d="M9 1.5v4c0 .325.306.564.62.485l4-1c.27-.067.432-.338.365-.606-.067-.27-.338-.432-.606-.365l-4 1L10 5.5v-4c0-.276-.224-.5-.5-.5s-.5.224-.5.5z"/> +</svg> diff --git a/devtools/client/debugger/new/images/folder.svg b/devtools/client/debugger/new/images/folder.svg new file mode 100644 index 000000000..6b8ef6ac3 --- /dev/null +++ b/devtools/client/debugger/new/images/folder.svg @@ -0,0 +1,6 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <path d="M2 5.193v7.652c0 .003-.002 0 .007 0H14v-7.69c0-.003.002 0-.007 0h-7.53v-2.15c0-.002-.004-.005-.01-.005H2.01C2 3 2 3 2 3.005V5.193zm-1 0V3.005C1 2.45 1.444 2 2.01 2h4.442c.558 0 1.01.45 1.01 1.005v1.15h6.53c.557 0 1.008.44 1.008 1v7.69c0 .553-.45 1-1.007 1H2.007c-.556 0-1.007-.44-1.007-1V5.193zM6.08 4.15H2v1h4.46v-1h-.38z" fill-rule="evenodd"/> +</svg> diff --git a/devtools/client/debugger/new/images/globe.svg b/devtools/client/debugger/new/images/globe.svg new file mode 100644 index 000000000..d513a659f --- /dev/null +++ b/devtools/client/debugger/new/images/globe.svg @@ -0,0 +1,10 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="13px" height="12px" viewBox="14 6 13 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <g id="world" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(14.000000, 6.000000)" stroke-linecap="round" stroke-linejoin="round"> + <path d="M6.35076107,0.354 C3.25095418,0.354 0.729,2.87582735 0.729,5.9758879 C0.729,9.07544113 3.25082735,11.5972685 6.35076107,11.5972685 C9.45044113,11.5972685 11.9723953,9.07544113 11.9723953,5.97576107 C11.9723953,2.87582735 9.45044113,0.354 6.35076107,0.354 L6.35076107,0.354 Z M6.35076107,10.8289121 C3.67445071,10.8289121 1.49722956,8.65181776 1.49722956,5.97576107 C1.49722956,5.9443064 1.49900522,5.91335907 1.49976622,5.88215806 L2.20090094,6.4213266 L2.56313696,6.4213266 L2.97268183,6.8306178 L2.97268183,7.68217686 L3.32324919,8.03287105 L3.73926255,8.03287105 L3.73926255,9.79940584 L4.27386509,10.3361645 L4.4591686,10.3361645 L4.4591686,10.000183 L5.37655417,9.08343163 L5.37655417,8.73400577 L5.85585737,8.25203907 L5.85585737,7.37206934 L5.32518666,7.37206934 L4.28439226,6.33140176 L2.82225748,6.33140176 L2.82225748,5.56938704 L3.96286973,5.56938704 L3.96286973,5.23949352 L4.65068695,5.23949352 L5.11477015,4.77667865 L5.11477015,4.03001076 L4.49087694,3.40662489 L3.75359472,3.40662489 L3.75359472,3.78725175 L2.96228149,3.78725175 L2.96228149,3.28385021 L3.42217919,2.82319151 L3.42217919,2.49786399 L2.97001833,2.49786399 C3.84466106,1.64744643 5.03714814,1.12222956 6.35063424,1.12222956 C7.57292716,1.12222956 8.69020207,1.57730759 9.54442463,2.32587797 L8.46164839,2.32587797 L7.680355,3.10666403 L8.21508437,3.64088607 L7.87238068,3.98257509 L7.7165025,3.82669692 L7.85297518,3.68946324 L7.78930484,3.62566607 L7.78943167,3.62566607 L7.56011699,3.39559038 L7.55986332,3.39571722 L7.49758815,3.33318838 L7.01904595,3.78585658 L7.55910232,4.32654712 L6.8069806,4.32198112 L6.8069806,5.25864535 L7.66716433,5.25864535 L7.6723645,4.72112565 L7.81289584,4.57996014 L8.31819988,5.08653251 L8.31819988,5.41921636 L9.00703176,5.41921636 L9.03366676,5.39321553 L9.03430093,5.39194719 L10.195587,6.55259911 L10.8637451,5.88520206 L11.2018828,5.88520206 C11.2023901,5.9153884 11.2041658,5.94532107 11.2041658,5.97563424 C11.2040389,8.65181776 9.0269446,10.8289121 6.35076107,10.8289121 L6.35076107,10.8289121 Z" id="Shape" stroke="#DDE1E5" stroke-width="0.25" fill="#DDE1E5"></path> + <polygon id="Shape" stroke="#DDE1E5" stroke-width="0.25" fill="#DDE1E5" points="6.50676608 1.61523076 4.52892694 1.61789426 4.52892694 2.95192735 5.34560683 3.76733891 5.72496536 3.76733891 5.72496536 3.1967157 6.50676608 2.41592965"></polygon> + <polygon id="Shape" stroke="#DDE1E5" stroke-width="0.25" fill="#DDE1E5" points="9.59959714 6.88718547 8.28623788 5.57268471 8.28623788 5.57002121 6.79607294 5.57002121 6.35101474 6.01469891 6.35101474 6.96201714 6.98429362 7.59466185 8.12909136 7.59466185 8.12909136 8.70343893 8.99434843 9.56882283 9.20971144 9.56882283 9.20971144 8.50329592 9.63029081 8.08271655 9.63029081 7.3026915 9.87025949 7.3026915 10.1711082 7.00082814 10.0558167 6.88718547"></polygon> + </g> +</svg> diff --git a/devtools/client/debugger/new/images/magnifying-glass.svg b/devtools/client/debugger/new/images/magnifying-glass.svg new file mode 100644 index 000000000..856013283 --- /dev/null +++ b/devtools/client/debugger/new/images/magnifying-glass.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> + <path class="st0" d="M9 9.3l3.6 3.6"/> + <ellipse fill="transparent" cx="5.9" cy="6.2" rx="4.5" ry="4.5"/> +</svg> diff --git a/devtools/client/debugger/new/images/pause-circle.svg b/devtools/client/debugger/new/images/pause-circle.svg new file mode 100644 index 000000000..2d4c116e5 --- /dev/null +++ b/devtools/client/debugger/new/images/pause-circle.svg @@ -0,0 +1,10 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16px" height="15px" viewBox="975 569 11 11" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <g id="Pause-circle" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(976.000000, 570.000000)"> + <path d="M4.5,0.538639227 C2.3152037,0.538639227 0.538639227,2.31614868 0.538639227,4.5 C0.538639227,6.6847963 2.3152037,8.46136077 4.5,8.46136077 C6.6847963,8.46136077 8.46136077,6.6847963 8.46136077,4.5 C8.46136077,2.31614868 6.6847963,0.538639227 4.5,0.538639227 M4.5,9 C2.01847963,9 0,6.98152037 0,4.5 C0,2.01847963 2.01847963,0 4.5,0 C6.98152037,0 9,2.01847963 9,4.5 C9,6.98152037 6.98152037,9 4.5,9" id="Fill-1-Copy" stroke="#4990E2" stroke-width="0.5" fill="#4990E2"></path> + <path d="M3,3 L3,6.5" id="Line" stroke="#4990E2" stroke-width="1.15" stroke-linecap="round"></path> + <path d="M6,3 L6,6.5" id="Line" stroke="#4990E2" stroke-width="1.15" stroke-linecap="round"></path> + </g> +</svg> diff --git a/devtools/client/debugger/new/images/pause-exceptions.svg b/devtools/client/debugger/new/images/pause-exceptions.svg new file mode 100644 index 000000000..8a0eb2c83 --- /dev/null +++ b/devtools/client/debugger/new/images/pause-exceptions.svg @@ -0,0 +1,7 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <path d="M10.483 13.995H5.517l-3.512-3.512V5.516l3.512-3.512h4.966l3.512 3.512v4.967l-3.512 3.512zm4.37-9.042l-3.807-3.805A.503.503 0 0 0 10.691 1H5.309a.503.503 0 0 0-.356.148L1.147 4.953A.502.502 0 0 0 1 5.308v5.383c0 .134.053.262.147.356l3.806 3.806a.503.503 0 0 0 .356.147h5.382a.503.503 0 0 0 .355-.147l3.806-3.806A.502.502 0 0 0 15 10.69V5.308a.502.502 0 0 0-.147-.355z"/> + <path d="M10 10.5a.5.5 0 1 0 1 0v-5a.5.5 0 1 0-1 0v5zM5 10.5a.5.5 0 1 0 1 0v-5a.5.5 0 0 0-1 0v5z"/> +</svg> diff --git a/devtools/client/debugger/new/images/pause.svg b/devtools/client/debugger/new/images/pause.svg new file mode 100644 index 000000000..b27bf2a85 --- /dev/null +++ b/devtools/client/debugger/new/images/pause.svg @@ -0,0 +1,8 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <g fill-rule="evenodd"> + <path d="M6.5 12.003l.052-9a.5.5 0 1 0-1-.006l-.052 9a.5.5 0 1 0 1 .006zM13 11.997l-.05-9a.488.488 0 0 0-.477-.497.488.488 0 0 0-.473.503l.05 9a.488.488 0 0 0 .477.497.488.488 0 0 0 .473-.503z"/> + </g> +</svg> diff --git a/devtools/client/debugger/new/images/play.svg b/devtools/client/debugger/new/images/play.svg new file mode 100644 index 000000000..21ffb0fe5 --- /dev/null +++ b/devtools/client/debugger/new/images/play.svg @@ -0,0 +1,6 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#696969"> + <path d="M4 13l7.778-5L4 3v10zm-1 0V3a1 1 0 0 1 1.54-.841l7.779 5a1 1 0 0 1 0 1.682l-7.778 5A1 1 0 0 1 3 13z" fill-rule="evenodd"/> +</svg> diff --git a/devtools/client/debugger/new/images/plus.svg b/devtools/client/debugger/new/images/plus.svg new file mode 100644 index 000000000..ae7a69dfd --- /dev/null +++ b/devtools/client/debugger/new/images/plus.svg @@ -0,0 +1,6 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <path d="M8.5 8.5V14a.5.5 0 1 1-1 0V8.5H2a.5.5 0 0 1 0-1h5.5V2a.5.5 0 0 1 1 0v5.5H14a.5.5 0 1 1 0 1H8.5z" fill-rule="evenodd"/> +</svg> diff --git a/devtools/client/debugger/new/images/prettyPrint.svg b/devtools/client/debugger/new/images/prettyPrint.svg new file mode 100644 index 000000000..62e2707f9 --- /dev/null +++ b/devtools/client/debugger/new/images/prettyPrint.svg @@ -0,0 +1,6 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <path d="M4.525 13.21h-.472c-.574 0-.987-.154-1.24-.463-.253-.31-.38-.882-.38-1.719v-.573c0-.746-.097-1.265-.292-1.557-.196-.293-.51-.44-.945-.44v-.974c.435 0 .75-.146.945-.44.195-.292.293-.811.293-1.556v-.58c0-.833.126-1.404.379-1.712.253-.31.666-.464 1.24-.464h.472v.783h-.179c-.37 0-.628.08-.774.24-.145.159-.218.54-.218 1.141v.383c0 .824-.096 1.432-.287 1.823-.191.39-.516.679-.974.866.458.191.783.482.974.873.191.39.287.998.287 1.823v.382c0 .602.073.982.218 1.142.146.16.404.239.774.239h.18v.783zm9.502-4.752c-.43 0-.744.147-.942.44-.197.292-.296.811-.296 1.557v.573c0 .837-.125 1.41-.376 1.719-.251.309-.664.463-1.237.463h-.478v-.783h.185c.37 0 .628-.08.774-.24.145-.159.218-.539.218-1.14v-.383c0-.825.096-1.433.287-1.823.191-.39.516-.682.974-.873-.458-.187-.783-.476-.974-.866-.191-.391-.287-.999-.287-1.823v-.383c0-.602-.073-.982-.218-1.142-.146-.159-.404-.239-.774-.239h-.185v-.783h.478c.573 0 .986.155 1.237.464.25.308.376.88.376 1.712v.58c0 .673.088 1.174.263 1.503.176.329.5.493.975.493v.974z" fill-rule="evenodd"/> +</svg> diff --git a/devtools/client/debugger/new/images/resume.svg b/devtools/client/debugger/new/images/resume.svg new file mode 100644 index 000000000..4a8b7fcd4 --- /dev/null +++ b/devtools/client/debugger/new/images/resume.svg @@ -0,0 +1,6 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <path d="M6.925 12.5l7.4-5-7.4-5v10zM6 12.5v-10c0-.785.8-1.264 1.415-.848l7.4 5c.58.392.58 1.304 0 1.696l-7.4 5C6.8 13.764 6 13.285 6 12.5z" fill-rule="evenodd"/> +</svg> diff --git a/devtools/client/debugger/new/images/sad-face.svg b/devtools/client/debugger/new/images/sad-face.svg new file mode 100644 index 000000000..6c42ca43b --- /dev/null +++ b/devtools/client/debugger/new/images/sad-face.svg @@ -0,0 +1,9 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="#D92215"> + <path d="M8 14.5c-3.6 0-6.5-2.9-6.5-6.5S4.4 1.5 8 1.5s6.5 2.9 6.5 6.5-2.9 6.5-6.5 6.5zm0-12C5 2.5 2.5 5 2.5 8S5 13.5 8 13.5 13.5 11 13.5 8 11 2.5 8 2.5z"/> + <circle cx="5" cy="6" r="1" transform="translate(1 1)"/> + <circle cx="9" cy="6" r="1" transform="translate(1 1)"/> + <path d="M5.5 11c-.1 0-.2 0-.3-.1-.2-.1-.3-.4-.1-.7C6 9 7 8.5 8.1 8.5c1.7.1 2.8 1.7 2.8 1.8.2.2.1.5-.1.7-.2.1-.6 0-.7-.2 0 0-.9-1.3-2-1.3-.7 0-1.4.4-2.1 1.3-.2.2-.4.2-.5.2z"/> +</svg> diff --git a/devtools/client/debugger/new/images/settings.svg b/devtools/client/debugger/new/images/settings.svg new file mode 100644 index 000000000..310438f7e --- /dev/null +++ b/devtools/client/debugger/new/images/settings.svg @@ -0,0 +1,6 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="33" height="12" viewBox="0 0 33 12"> + <path id="base-path" d="M27.1,0H1C0.4,0,0,0.4,0,1v10c0,0.6,0.4,1,1,1h26.1 c0.6,0,1.2-0.3,1.5-0.7L33,6l-4.4-5.3C28.2,0.3,27.7,0,27.1,0z"/> +</svg> diff --git a/devtools/client/debugger/new/images/stepIn.svg b/devtools/client/debugger/new/images/stepIn.svg new file mode 100644 index 000000000..eff11c0c9 --- /dev/null +++ b/devtools/client/debugger/new/images/stepIn.svg @@ -0,0 +1,8 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <g fill-rule="evenodd"> + <path d="M1.5 14.042h4.095a.5.5 0 0 0 0-1H1.5a.5.5 0 1 0 0 1zM7.983 2a.5.5 0 0 1 .517.5v7.483l3.136-3.326a.5.5 0 1 1 .728.686l-4 4.243a.499.499 0 0 1-.73-.004L3.635 7.343a.5.5 0 0 1 .728-.686L7.5 9.983V3H1.536C1.24 3 1 2.776 1 2.5s.24-.5.536-.5h6.447zM10.5 14.042h4.095a.5.5 0 0 0 0-1H10.5a.5.5 0 1 0 0 1z"/> + </g> +</svg> diff --git a/devtools/client/debugger/new/images/stepOut.svg b/devtools/client/debugger/new/images/stepOut.svg new file mode 100644 index 000000000..4e5457141 --- /dev/null +++ b/devtools/client/debugger/new/images/stepOut.svg @@ -0,0 +1,8 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <g fill-rule="evenodd"> + <path d="M5 13.5H1a.5.5 0 1 0 0 1h4a.5.5 0 1 0 0-1zM12 13.5H8a.5.5 0 1 0 0 1h4a.5.5 0 1 0 0-1zM6.11 5.012A.427.427 0 0 1 6.21 5h7.083L9.646 1.354a.5.5 0 1 1 .708-.708l4.5 4.5a.498.498 0 0 1 0 .708l-4.5 4.5a.5.5 0 0 1-.708-.708L13.293 6H6.5v5.5a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .61-.488z"/> + </g> +</svg> diff --git a/devtools/client/debugger/new/images/stepOver.svg b/devtools/client/debugger/new/images/stepOver.svg new file mode 100644 index 000000000..c1d30c051 --- /dev/null +++ b/devtools/client/debugger/new/images/stepOver.svg @@ -0,0 +1,9 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <g fill-rule="evenodd"> + <path d="M13.297 6.912C12.595 4.39 10.167 2.5 7.398 2.5A5.898 5.898 0 0 0 1.5 8.398a.5.5 0 0 0 1 0A4.898 4.898 0 0 1 7.398 3.5c2.75 0 5.102 2.236 5.102 4.898v.004L8.669 7.029a.5.5 0 0 0-.338.942l4.462 1.598a.5.5 0 0 0 .651-.34.506.506 0 0 0 .02-.043l2-5a.5.5 0 1 0-.928-.372l-1.24 3.098z"/> + <circle cx="7" cy="12" r="1"/> + </g> +</svg> diff --git a/devtools/client/debugger/new/images/subSettings.svg b/devtools/client/debugger/new/images/subSettings.svg new file mode 100644 index 000000000..6b2355584 --- /dev/null +++ b/devtools/client/debugger/new/images/subSettings.svg @@ -0,0 +1,6 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <path d="M12.219 7c.345 0 .635.117.869.352.234.234.351.524.351.869 0 .351-.118.652-.356.903-.238.25-.526.376-.864.376-.332 0-.615-.125-.85-.376a1.276 1.276 0 0 1-.351-.903A1.185 1.185 0 0 1 12.218 7zM8.234 7c.345 0 .635.117.87.352.234.234.351.524.351.869 0 .351-.119.652-.356.903-.238.25-.526.376-.865.376-.332 0-.613-.125-.844-.376a1.286 1.286 0 0 1-.347-.903c0-.352.114-.643.342-.874.228-.231.51-.347.85-.347zM4.201 7c.339 0 .627.117.864.352.238.234.357.524.357.869 0 .351-.119.652-.357.903-.237.25-.525.376-.864.376-.338 0-.623-.125-.854-.376A1.286 1.286 0 0 1 3 8.221 1.185 1.185 0 0 1 4.201 7z" fill-rule="evenodd"/> +</svg> diff --git a/devtools/client/debugger/new/images/toggle-breakpoints.svg b/devtools/client/debugger/new/images/toggle-breakpoints.svg new file mode 100644 index 000000000..9b2cccf82 --- /dev/null +++ b/devtools/client/debugger/new/images/toggle-breakpoints.svg @@ -0,0 +1,8 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <g fill-rule="evenodd"> + <path d="M3.233 11.25l-.417 1H1.712C.763 12.25 0 11.574 0 10.747V6.503C0 5.675.755 5 1.712 5h4.127l-.417 1H1.597C1.257 6 1 6.225 1 6.503v4.244c0 .277.267.503.597.503h1.636zM7.405 11.27L7 12.306c.865.01 2.212-.024 2.315-.04.112-.016.112-.016.185-.035.075-.02.156-.046.251-.082.152-.056.349-.138.592-.244.415-.182.962-.435 1.612-.744l.138-.066a179.35 179.35 0 0 0 2.255-1.094c1.191-.546 1.191-2.074-.025-2.632l-.737-.34a3547.554 3547.554 0 0 0-3.854-1.78c-.029.11-.065.222-.11.336l-.232.596c.894.408 4.56 2.107 4.56 2.107.458.21.458.596 0 .806L9.197 11.27H7.405zM4.462 14.692l5-12a.5.5 0 1 0-.924-.384l-5 12a.5.5 0 1 0 .924.384z"/> + </g> +</svg> diff --git a/devtools/client/debugger/new/images/worker.svg b/devtools/client/debugger/new/images/worker.svg new file mode 100644 index 000000000..4a9874efb --- /dev/null +++ b/devtools/client/debugger/new/images/worker.svg @@ -0,0 +1,6 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <path fill-rule="evenodd" d="M8.5 8.793L5.854 6.146l-.04-.035L7.5 4.426c.2-.2.3-.4.3-.6 0-.2-.1-.4-.2-.6l-1-1c-.4-.3-.9-.3-1.2 0l-4.1 4.1c-.2.2-.3.4-.3.6 0 .2.1.4.2.6l1 1c.3.3.9.3 1.2 0l1.71-1.71.036.04L7.793 9.5l-3.647 3.646c-.195.196-.195.512 0 .708.196.195.512.195.708 0L8.5 10.207l3.646 3.647c.196.195.512.195.708 0 .195-.196.195-.512 0-.708L9.207 9.5l2.565-2.565L13.3 8.5c.1.1 2.3 1.1 2.7.7.4-.4-.3-2.7-.5-2.9l-1.1-1.1c.1-.1.2-.4.2-.6 0-.2-.1-.4-.2-.6l-.4-.4c-.3-.3-.8-.3-1.1 0l-1.5-1.4c-.2-.2-.3-.2-.5-.2s-.3.1-.5.2L9.2 3.4c-.2.1-.2.2-.2.4s.1.4.2.5l1.874 1.92L8.5 8.792z"/> +</svg> diff --git a/devtools/client/debugger/new/index.html b/devtools/client/debugger/new/index.html new file mode 100644 index 000000000..ed4c976fc --- /dev/null +++ b/devtools/client/debugger/new/index.html @@ -0,0 +1,31 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<!DOCTYPE html> +<html dir=""> + <head> + <link rel="stylesheet" + type="text/css" + href="chrome://devtools/content/sourceeditor/codemirror/lib/codemirror.css" /> + <link rel="stylesheet" + type="text/css" + href="chrome://devtools/content/sourceeditor/codemirror/addon/dialog/dialog.css" /> + <link rel="stylesheet" + type="text/css" + href="chrome://devtools/content/sourceeditor/codemirror/mozilla.css" /> + <link rel="stylesheet" type="text/css" href="resource://devtools/client/debugger/new/styles.css" /> + </head> + <body> + <div id="mount"></div> + <script type="application/javascript;version=1.8" + src="chrome://devtools/content/shared/theme-switching.js"></script> + <script type="text/javascript"> + const { BrowserLoader } = Components.utils.import("resource://devtools/client/shared/browser-loader.js", {}); + const { require: devtoolsRequire } = BrowserLoader({ + baseURI: "resource://devtools/client/debugger/new/", + window, + }); + </script> + <script type="text/javascript" src="resource://devtools/client/debugger/new/bundle.js"></script> + </body> +</html> diff --git a/devtools/client/debugger/new/moz.build b/devtools/client/debugger/new/moz.build new file mode 100644 index 000000000..09d1f908e --- /dev/null +++ b/devtools/client/debugger/new/moz.build @@ -0,0 +1,12 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DevToolsModules( + 'bundle.js', + 'panel.js', + 'pretty-print-worker.js', + 'source-map-worker.js', + 'styles.css' +) diff --git a/devtools/client/debugger/new/panel.js b/devtools/client/debugger/new/panel.js new file mode 100644 index 000000000..62d4a9f4f --- /dev/null +++ b/devtools/client/debugger/new/panel.js @@ -0,0 +1,77 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { Task } = require("devtools/shared/task"); +var {LocalizationHelper} = require("devtools/shared/l10n"); + +const DBG_STRINGS_URI = "devtools/client/locales/debugger.properties"; +var L10N = new LocalizationHelper(DBG_STRINGS_URI); + +function DebuggerPanel(iframeWindow, toolbox) { + this.panelWin = iframeWindow; + this.panelWin.L10N = L10N; + this.toolbox = toolbox; +} + +DebuggerPanel.prototype = { + open: Task.async(function* () { + if (!this.toolbox.target.isRemote) { + yield this.toolbox.target.makeRemote(); + } + + yield this.panelWin.Debugger.bootstrap({ + threadClient: this.toolbox.threadClient, + tabTarget: this.toolbox.target + }); + + this.isReady = true; + return this; + }), + + _store: function () { + return this.panelWin.Debugger.store; + }, + + _getState: function () { + return this._store().getState(); + }, + + _actions: function () { + return this.panelWin.Debugger.actions; + }, + + _selectors: function () { + return this.panelWin.Debugger.selectors; + }, + + getFrames: function () { + let frames = this._selectors().getFrames(this._getState()); + + // Frames is null when the debugger is not paused. + if (!frames) { + return { + frames: [], + selected: -1 + }; + } + + frames = frames.toJS(); + const selectedFrame = this._selectors().getSelectedFrame(this._getState()); + const selected = frames.findIndex(frame => frame.id == selectedFrame.id); + + frames.forEach(frame => { + frame.actor = frame.id; + }); + + return { frames, selected }; + }, + + destroy: function () { + this.panelWin.Debugger.destroy(); + this.emit("destroyed"); + } +}; + +exports.DebuggerPanel = DebuggerPanel; diff --git a/devtools/client/debugger/new/pretty-print-worker.js b/devtools/client/debugger/new/pretty-print-worker.js new file mode 100644 index 000000000..4fa735e16 --- /dev/null +++ b/devtools/client/debugger/new/pretty-print-worker.js @@ -0,0 +1,5904 @@ +var Debugger = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; +/******/ +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = "/public/build"; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ function(module, exports, __webpack_require__) { + + var prettyFast = __webpack_require__(460); + var assert = __webpack_require__(247); + + function prettyPrint(_ref) { + var url = _ref.url; + var indent = _ref.indent; + var source = _ref.source; + + try { + var prettified = prettyFast(source, { + url: url, + indent: " ".repeat(indent) + }); + + return { + code: prettified.code, + mappings: prettified.map._mappings + }; + } catch (e) { + return new Error(e.message + "\n" + e.stack); + } + } + + function invertMappings(mappings) { + return mappings._array.map(m => { + var mapping = { + generated: { + line: m.originalLine, + column: m.originalColumn + } + }; + if (m.source) { + mapping.source = m.source; + mapping.original = { + line: m.generatedLine, + column: m.generatedColumn + }; + mapping.name = m.name; + } + return mapping; + }); + } + + self.onmessage = function (msg) { + var _msg$data = msg.data; + var id = _msg$data.id; + var args = _msg$data.args; + + assert(msg.data.method === "prettyPrint", "Method must be `prettyPrint`"); + + try { + var _prettyPrint = prettyPrint(args[0]); + + var code = _prettyPrint.code; + var mappings = _prettyPrint.mappings; + + self.postMessage({ id, response: { + code, mappings: invertMappings(mappings) + } }); + } catch (e) { + self.postMessage({ id, error: e }); + } + }; + +/***/ }, + +/***/ 247: +/***/ function(module, exports) { + + function assert(condition, message) { + if (!condition) { + throw new Error("Assertion failure: " + message); + } + } + + module.exports = assert; + +/***/ }, + +/***/ 460: +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/* -*- indent-tabs-mode: nil; js-indent-level: 2; fill-column: 80 -*- */ + /* + * Copyright 2013 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.md or: + * http://opensource.org/licenses/BSD-2-Clause + */ + (function (root, factory) { + "use strict"; + + if (true) { + !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (typeof exports === "object") { + module.exports = factory(); + } else { + root.prettyFast = factory(); + } + }(this, function () { + "use strict"; + + var acorn = this.acorn || __webpack_require__(461); + var sourceMap = this.sourceMap || __webpack_require__(462); + var SourceNode = sourceMap.SourceNode; + + // If any of these tokens are seen before a "[" token, we know that "[" token + // is the start of an array literal, rather than a property access. + // + // The only exception is "}", which would need to be disambiguated by + // parsing. The majority of the time, an open bracket following a closing + // curly is going to be an array literal, so we brush the complication under + // the rug, and handle the ambiguity by always assuming that it will be an + // array literal. + var PRE_ARRAY_LITERAL_TOKENS = { + "typeof": true, + "void": true, + "delete": true, + "case": true, + "do": true, + "=": true, + "in": true, + "{": true, + "*": true, + "/": true, + "%": true, + "else": true, + ";": true, + "++": true, + "--": true, + "+": true, + "-": true, + "~": true, + "!": true, + ":": true, + "?": true, + ">>": true, + ">>>": true, + "<<": true, + "||": true, + "&&": true, + "<": true, + ">": true, + "<=": true, + ">=": true, + "instanceof": true, + "&": true, + "^": true, + "|": true, + "==": true, + "!=": true, + "===": true, + "!==": true, + ",": true, + + "}": true + }; + + /** + * Determines if we think that the given token starts an array literal. + * + * @param Object token + * The token we want to determine if it is an array literal. + * @param Object lastToken + * The last token we added to the pretty printed results. + * + * @returns Boolean + * True if we believe it is an array literal, false otherwise. + */ + function isArrayLiteral(token, lastToken) { + if (token.type.type != "[") { + return false; + } + if (!lastToken) { + return true; + } + if (lastToken.type.isAssign) { + return true; + } + return !!PRE_ARRAY_LITERAL_TOKENS[ + lastToken.type.keyword || lastToken.type.type + ]; + } + + // If any of these tokens are followed by a token on a new line, we know that + // ASI cannot happen. + var PREVENT_ASI_AFTER_TOKENS = { + // Binary operators + "*": true, + "/": true, + "%": true, + "+": true, + "-": true, + "<<": true, + ">>": true, + ">>>": true, + "<": true, + ">": true, + "<=": true, + ">=": true, + "instanceof": true, + "in": true, + "==": true, + "!=": true, + "===": true, + "!==": true, + "&": true, + "^": true, + "|": true, + "&&": true, + "||": true, + ",": true, + ".": true, + "=": true, + "*=": true, + "/=": true, + "%=": true, + "+=": true, + "-=": true, + "<<=": true, + ">>=": true, + ">>>=": true, + "&=": true, + "^=": true, + "|=": true, + // Unary operators + "delete": true, + "void": true, + "typeof": true, + "~": true, + "!": true, + "new": true, + // Function calls and grouped expressions + "(": true + }; + + // If any of these tokens are on a line after the token before it, we know + // that ASI cannot happen. + var PREVENT_ASI_BEFORE_TOKENS = { + // Binary operators + "*": true, + "/": true, + "%": true, + "<<": true, + ">>": true, + ">>>": true, + "<": true, + ">": true, + "<=": true, + ">=": true, + "instanceof": true, + "in": true, + "==": true, + "!=": true, + "===": true, + "!==": true, + "&": true, + "^": true, + "|": true, + "&&": true, + "||": true, + ",": true, + ".": true, + "=": true, + "*=": true, + "/=": true, + "%=": true, + "+=": true, + "-=": true, + "<<=": true, + ">>=": true, + ">>>=": true, + "&=": true, + "^=": true, + "|=": true, + // Function calls + "(": true + }; + + /** + * Determines if Automatic Semicolon Insertion (ASI) occurs between these + * tokens. + * + * @param Object token + * The current token. + * @param Object lastToken + * The last token we added to the pretty printed results. + * + * @returns Boolean + * True if we believe ASI occurs. + */ + function isASI(token, lastToken) { + if (!lastToken) { + return false; + } + if (token.startLoc.line === lastToken.startLoc.line) { + return false; + } + if (PREVENT_ASI_AFTER_TOKENS[ + lastToken.type.type || lastToken.type.keyword + ]) { + return false; + } + if (PREVENT_ASI_BEFORE_TOKENS[token.type.type || token.type.keyword]) { + return false; + } + return true; + } + + /** + * Determine if we have encountered a getter or setter. + * + * @param Object token + * The current token. If this is a getter or setter, it would be the + * property name. + * @param Object lastToken + * The last token we added to the pretty printed results. If this is a + * getter or setter, it would be the `get` or `set` keyword + * respectively. + * @param Array stack + * The stack of open parens/curlies/brackets/etc. + * + * @returns Boolean + * True if this is a getter or setter. + */ + function isGetterOrSetter(token, lastToken, stack) { + return stack[stack.length - 1] == "{" + && lastToken + && lastToken.type.type == "name" + && (lastToken.value == "get" || lastToken.value == "set") + && token.type.type == "name"; + } + + /** + * Determine if we should add a newline after the given token. + * + * @param Object token + * The token we are looking at. + * @param Array stack + * The stack of open parens/curlies/brackets/etc. + * + * @returns Boolean + * True if we should add a newline. + */ + function isLineDelimiter(token, stack) { + if (token.isArrayLiteral) { + return true; + } + var ttt = token.type.type; + var top = stack[stack.length - 1]; + return ttt == ";" && top != "(" + || ttt == "{" + || ttt == "," && top != "(" + || ttt == ":" && (top == "case" || top == "default"); + } + + /** + * Append the necessary whitespace to the result after we have added the given + * token. + * + * @param Object token + * The token that was just added to the result. + * @param Function write + * The function to write to the pretty printed results. + * @param Array stack + * The stack of open parens/curlies/brackets/etc. + * + * @returns Boolean + * Returns true if we added a newline to result, false in all other + * cases. + */ + function appendNewline(token, write, stack) { + if (isLineDelimiter(token, stack)) { + write("\n", token.startLoc.line, token.startLoc.column); + return true; + } + return false; + } + + /** + * Determines if we need to add a space between the last token we added and + * the token we are about to add. + * + * @param Object token + * The token we are about to add to the pretty printed code. + * @param Object lastToken + * The last token added to the pretty printed code. + */ + function needsSpaceAfter(token, lastToken) { + if (lastToken) { + if (lastToken.type.isLoop) { + return true; + } + if (lastToken.type.isAssign) { + return true; + } + if (lastToken.type.binop != null) { + return true; + } + + var ltt = lastToken.type.type; + if (ltt == "?") { + return true; + } + if (ltt == ":") { + return true; + } + if (ltt == ",") { + return true; + } + if (ltt == ";") { + return true; + } + + var ltk = lastToken.type.keyword; + if (ltk != null) { + if (ltk == "break" || ltk == "continue" || ltk == "return") { + return token.type.type != ";"; + } + if (ltk != "debugger" + && ltk != "null" + && ltk != "true" + && ltk != "false" + && ltk != "this" + && ltk != "default") { + return true; + } + } + + if (ltt == ")" && (token.type.type != ")" + && token.type.type != "]" + && token.type.type != ";" + && token.type.type != "," + && token.type.type != ".")) { + return true; + } + } + + if (token.type.isAssign) { + return true; + } + if (token.type.binop != null) { + return true; + } + if (token.type.type == "?") { + return true; + } + + return false; + } + + /** + * Add the required whitespace before this token, whether that is a single + * space, newline, and/or the indent on fresh lines. + * + * @param Object token + * The token we are about to add to the pretty printed code. + * @param Object lastToken + * The last token we added to the pretty printed code. + * @param Boolean addedNewline + * Whether we added a newline after adding the last token to the pretty + * printed code. + * @param Function write + * The function to write pretty printed code to the result SourceNode. + * @param Object options + * The options object. + * @param Number indentLevel + * The number of indents deep we are. + * @param Array stack + * The stack of open curlies, brackets, etc. + */ + function prependWhiteSpace(token, lastToken, addedNewline, write, options, + indentLevel, stack) { + var ttk = token.type.keyword; + var ttt = token.type.type; + var newlineAdded = addedNewline; + var ltt = lastToken ? lastToken.type.type : null; + + // Handle whitespace and newlines after "}" here instead of in + // `isLineDelimiter` because it is only a line delimiter some of the + // time. For example, we don't want to put "else if" on a new line after + // the first if's block. + if (lastToken && ltt == "}") { + if (ttk == "while" && stack[stack.length - 1] == "do") { + write(" ", + lastToken.startLoc.line, + lastToken.startLoc.column); + } else if (ttk == "else" || + ttk == "catch" || + ttk == "finally") { + write(" ", + lastToken.startLoc.line, + lastToken.startLoc.column); + } else if (ttt != "(" && + ttt != ";" && + ttt != "," && + ttt != ")" && + ttt != ".") { + write("\n", + lastToken.startLoc.line, + lastToken.startLoc.column); + newlineAdded = true; + } + } + + if (isGetterOrSetter(token, lastToken, stack)) { + write(" ", + lastToken.startLoc.line, + lastToken.startLoc.column); + } + + if (ttt == ":" && stack[stack.length - 1] == "?") { + write(" ", + lastToken.startLoc.line, + lastToken.startLoc.column); + } + + if (lastToken && ltt != "}" && ttk == "else") { + write(" ", + lastToken.startLoc.line, + lastToken.startLoc.column); + } + + function ensureNewline() { + if (!newlineAdded) { + write("\n", + lastToken.startLoc.line, + lastToken.startLoc.column); + newlineAdded = true; + } + } + + if (isASI(token, lastToken)) { + ensureNewline(); + } + + if (decrementsIndent(ttt, stack)) { + ensureNewline(); + } + + if (newlineAdded) { + if (ttk == "case" || ttk == "default") { + write(repeat(options.indent, indentLevel - 1), + token.startLoc.line, + token.startLoc.column); + } else { + write(repeat(options.indent, indentLevel), + token.startLoc.line, + token.startLoc.column); + } + } else if (needsSpaceAfter(token, lastToken)) { + write(" ", + lastToken.startLoc.line, + lastToken.startLoc.column); + } + } + + /** + * Repeat the `str` string `n` times. + * + * @param String str + * The string to be repeated. + * @param Number n + * The number of times to repeat the string. + * + * @returns String + * The repeated string. + */ + function repeat(str, n) { + var result = ""; + while (n > 0) { + if (n & 1) { + result += str; + } + n >>= 1; + str += str; + } + return result; + } + + /** + * Make sure that we output the escaped character combination inside string + * literals instead of various problematic characters. + */ + var sanitize = (function () { + var escapeCharacters = { + // Backslash + "\\": "\\\\", + // Newlines + "\n": "\\n", + // Carriage return + "\r": "\\r", + // Tab + "\t": "\\t", + // Vertical tab + "\v": "\\v", + // Form feed + "\f": "\\f", + // Null character + "\0": "\\0", + // Single quotes + "'": "\\'" + }; + + var regExpString = "(" + + Object.keys(escapeCharacters) + .map(function (c) { return escapeCharacters[c]; }) + .join("|") + + ")"; + var escapeCharactersRegExp = new RegExp(regExpString, "g"); + + return function (str) { + return str.replace(escapeCharactersRegExp, function (_, c) { + return escapeCharacters[c]; + }); + }; + }()); + /** + * Add the given token to the pretty printed results. + * + * @param Object token + * The token to add. + * @param Function write + * The function to write pretty printed code to the result SourceNode. + */ + function addToken(token, write) { + if (token.type.type == "string") { + write("'" + sanitize(token.value) + "'", + token.startLoc.line, + token.startLoc.column); + } else if (token.type.type == "regexp") { + write(String(token.value.value), + token.startLoc.line, + token.startLoc.column); + } else { + write(String(token.value != null ? token.value : token.type.type), + token.startLoc.line, + token.startLoc.column); + } + } + + /** + * Returns true if the given token type belongs on the stack. + */ + function belongsOnStack(token) { + var ttt = token.type.type; + var ttk = token.type.keyword; + return ttt == "{" + || ttt == "(" + || ttt == "[" + || ttt == "?" + || ttk == "do" + || ttk == "switch" + || ttk == "case" + || ttk == "default"; + } + + /** + * Returns true if the given token should cause us to pop the stack. + */ + function shouldStackPop(token, stack) { + var ttt = token.type.type; + var ttk = token.type.keyword; + var top = stack[stack.length - 1]; + return ttt == "]" + || ttt == ")" + || ttt == "}" + || (ttt == ":" && (top == "case" || top == "default" || top == "?")) + || (ttk == "while" && top == "do"); + } + + /** + * Returns true if the given token type should cause us to decrement the + * indent level. + */ + function decrementsIndent(tokenType, stack) { + return tokenType == "}" + || (tokenType == "]" && stack[stack.length - 1] == "[\n"); + } + + /** + * Returns true if the given token should cause us to increment the indent + * level. + */ + function incrementsIndent(token) { + return token.type.type == "{" + || token.isArrayLiteral + || token.type.keyword == "switch"; + } + + /** + * Add a comment to the pretty printed code. + * + * @param Function write + * The function to write pretty printed code to the result SourceNode. + * @param Number indentLevel + * The number of indents deep we are. + * @param Object options + * The options object. + * @param Boolean block + * True if the comment is a multiline block style comment. + * @param String text + * The text of the comment. + * @param Number line + * The line number to comment appeared on. + * @param Number column + * The column number the comment appeared on. + */ + function addComment(write, indentLevel, options, block, text, line, column) { + var indentString = repeat(options.indent, indentLevel); + + write(indentString, line, column); + if (block) { + write("/*"); + write(text + .split(new RegExp("/\n" + indentString + "/", "g")) + .join("\n" + indentString)); + write("*/"); + } else { + write("//"); + write(text); + } + write("\n"); + } + + /** + * The main function. + * + * @param String input + * The ugly JS code we want to pretty print. + * @param Object options + * The options object. Provides configurability of the pretty + * printing. Properties: + * - url: The URL string of the ugly JS code. + * - indent: The string to indent code by. + * + * @returns Object + * An object with the following properties: + * - code: The pretty printed code string. + * - map: A SourceMapGenerator instance. + */ + return function prettyFast(input, options) { + // The level of indents deep we are. + var indentLevel = 0; + + // We will accumulate the pretty printed code in this SourceNode. + var result = new SourceNode(); + + /** + * Write a pretty printed string to the result SourceNode. + * + * We buffer our writes so that we only create one mapping for each line in + * the source map. This enhances performance by avoiding extraneous mapping + * serialization, and flattening the tree that + * `SourceNode#toStringWithSourceMap` will have to recursively walk. When + * timing how long it takes to pretty print jQuery, this optimization + * brought the time down from ~390 ms to ~190ms! + * + * @param String str + * The string to be added to the result. + * @param Number line + * The line number the string came from in the ugly source. + * @param Number column + * The column number the string came from in the ugly source. + */ + var write = (function () { + var buffer = []; + var bufferLine = -1; + var bufferColumn = -1; + return function write(str, line, column) { + if (line != null && bufferLine === -1) { + bufferLine = line; + } + if (column != null && bufferColumn === -1) { + bufferColumn = column; + } + buffer.push(str); + + if (str == "\n") { + var lineStr = ""; + for (var i = 0, len = buffer.length; i < len; i++) { + lineStr += buffer[i]; + } + result.add(new SourceNode(bufferLine, bufferColumn, options.url, + lineStr)); + buffer.splice(0, buffer.length); + bufferLine = -1; + bufferColumn = -1; + } + }; + }()); + + // Whether or not we added a newline on after we added the last token. + var addedNewline = false; + + // The current token we will be adding to the pretty printed code. + var token; + + // Shorthand for token.type.type, so we don't have to repeatedly access + // properties. + var ttt; + + // Shorthand for token.type.keyword, so we don't have to repeatedly access + // properties. + var ttk; + + // The last token we added to the pretty printed code. + var lastToken; + + // Stack of token types/keywords that can affect whether we want to add a + // newline or a space. We can make that decision based on what token type is + // on the top of the stack. For example, a comma in a parameter list should + // be followed by a space, while a comma in an object literal should be + // followed by a newline. + // + // Strings that go on the stack: + // + // - "{" + // - "(" + // - "[" + // - "[\n" + // - "do" + // - "?" + // - "switch" + // - "case" + // - "default" + // + // The difference between "[" and "[\n" is that "[\n" is used when we are + // treating "[" and "]" tokens as line delimiters and should increment and + // decrement the indent level when we find them. + var stack = []; + + // Acorn's tokenizer will always yield comments *before* the token they + // follow (unless the very first thing in the source is a comment), so we + // have to queue the comments in order to pretty print them in the correct + // location. For example, the source file: + // + // foo + // // a + // // b + // bar + // + // When tokenized by acorn, gives us the following token stream: + // + // [ '// a', '// b', foo, bar ] + var commentQueue = []; + + var getToken = acorn.tokenize(input, { + locations: true, + sourceFile: options.url, + onComment: function (block, text, start, end, startLoc, endLoc) { + if (lastToken) { + commentQueue.push({ + block: block, + text: text, + line: startLoc.line, + column: startLoc.column, + trailing: lastToken.endLoc.line == startLoc.line + }); + } else { + addComment(write, indentLevel, options, block, text, startLoc.line, + startLoc.column); + addedNewline = true; + } + } + }); + + for (;;) { + token = getToken(); + + ttk = token.type.keyword; + ttt = token.type.type; + + if (ttt == "eof") { + if (!addedNewline) { + write("\n"); + } + break; + } + + token.isArrayLiteral = isArrayLiteral(token, lastToken); + + if (belongsOnStack(token)) { + if (token.isArrayLiteral) { + stack.push("[\n"); + } else { + stack.push(ttt || ttk); + } + } + + if (decrementsIndent(ttt, stack)) { + indentLevel--; + if (ttt == "}" + && stack.length > 1 + && stack[stack.length - 2] == "switch") { + indentLevel--; + } + } + + prependWhiteSpace(token, lastToken, addedNewline, write, options, + indentLevel, stack); + addToken(token, write); + if (commentQueue.length === 0 || !commentQueue[0].trailing) { + addedNewline = appendNewline(token, write, stack); + } + + if (shouldStackPop(token, stack)) { + stack.pop(); + if (token == "}" && stack.length + && stack[stack.length - 1] == "switch") { + stack.pop(); + } + } + + if (incrementsIndent(token)) { + indentLevel++; + } + + // Acorn's tokenizer re-uses tokens, so we have to copy the last token on + // every iteration. We follow acorn's lead here, and reuse the lastToken + // object the same way that acorn reuses the token object. This allows us + // to avoid allocations and minimize GC pauses. + if (!lastToken) { + lastToken = { startLoc: {}, endLoc: {} }; + } + lastToken.start = token.start; + lastToken.end = token.end; + lastToken.startLoc.line = token.startLoc.line; + lastToken.startLoc.column = token.startLoc.column; + lastToken.endLoc.line = token.endLoc.line; + lastToken.endLoc.column = token.endLoc.column; + lastToken.type = token.type; + lastToken.value = token.value; + lastToken.isArrayLiteral = token.isArrayLiteral; + + // Apply all the comments that have been queued up. + if (commentQueue.length) { + if (!addedNewline && !commentQueue[0].trailing) { + write("\n"); + } + if (commentQueue[0].trailing) { + write(" "); + } + for (var i = 0, n = commentQueue.length; i < n; i++) { + var comment = commentQueue[i]; + var commentIndentLevel = commentQueue[i].trailing ? 0 : indentLevel; + addComment(write, commentIndentLevel, options, comment.block, + comment.text, comment.line, comment.column); + } + addedNewline = true; + commentQueue.splice(0, commentQueue.length); + } + } + + return result.toStringWithSourceMap({ file: options.url }); + }; + + }.bind(this))); + + +/***/ }, + +/***/ 461: +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// Acorn is a tiny, fast JavaScript parser written in JavaScript. + // + // Acorn was written by Marijn Haverbeke and various contributors and + // released under an MIT license. The Unicode regexps (for identifiers + // and whitespace) were taken from [Esprima](http://esprima.org) by + // Ariya Hidayat. + // + // Git repositories for Acorn are available at + // + // http://marijnhaverbeke.nl/git/acorn + // https://github.com/marijnh/acorn.git + // + // Please use the [github bug tracker][ghbt] to report issues. + // + // [ghbt]: https://github.com/marijnh/acorn/issues + // + // This file defines the main parser interface. The library also comes + // with a [error-tolerant parser][dammit] and an + // [abstract syntax tree walker][walk], defined in other files. + // + // [dammit]: acorn_loose.js + // [walk]: util/walk.js + + (function(root, mod) { + if (true) return mod(exports); // CommonJS + if (true) return !(__WEBPACK_AMD_DEFINE_ARRAY__ = [exports], __WEBPACK_AMD_DEFINE_FACTORY__ = (mod), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); // AMD + mod(root.acorn || (root.acorn = {})); // Plain browser env + })(this, function(exports) { + "use strict"; + + exports.version = "0.11.0"; + + // The main exported interface (under `self.acorn` when in the + // browser) is a `parse` function that takes a code string and + // returns an abstract syntax tree as specified by [Mozilla parser + // API][api], with the caveat that inline XML is not recognized. + // + // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API + + var options, input, inputLen, sourceFile; + + exports.parse = function(inpt, opts) { + input = String(inpt); inputLen = input.length; + setOptions(opts); + initTokenState(); + var startPos = options.locations ? [tokPos, curPosition()] : tokPos; + initParserState(); + return parseTopLevel(options.program || startNodeAt(startPos)); + }; + + // A second optional argument can be given to further configure + // the parser process. These options are recognized: + + var defaultOptions = exports.defaultOptions = { + // `ecmaVersion` indicates the ECMAScript version to parse. Must + // be either 3, or 5, or 6. This influences support for strict + // mode, the set of reserved words, support for getters and + // setters and other features. + ecmaVersion: 5, + // Turn on `strictSemicolons` to prevent the parser from doing + // automatic semicolon insertion. + strictSemicolons: false, + // When `allowTrailingCommas` is false, the parser will not allow + // trailing commas in array and object literals. + allowTrailingCommas: true, + // By default, reserved words are not enforced. Enable + // `forbidReserved` to enforce them. When this option has the + // value "everywhere", reserved words and keywords can also not be + // used as property names. + forbidReserved: false, + // When enabled, a return at the top level is not considered an + // error. + allowReturnOutsideFunction: false, + // When enabled, import/export statements are not constrained to + // appearing at the top of the program. + allowImportExportEverywhere: false, + // When `locations` is on, `loc` properties holding objects with + // `start` and `end` properties in `{line, column}` form (with + // line being 1-based and column 0-based) will be attached to the + // nodes. + locations: false, + // A function can be passed as `onToken` option, which will + // cause Acorn to call that function with object in the same + // format as tokenize() returns. Note that you are not + // allowed to call the parser from the callback—that will + // corrupt its internal state. + onToken: null, + // A function can be passed as `onComment` option, which will + // cause Acorn to call that function with `(block, text, start, + // end)` parameters whenever a comment is skipped. `block` is a + // boolean indicating whether this is a block (`/* */`) comment, + // `text` is the content of the comment, and `start` and `end` are + // character offsets that denote the start and end of the comment. + // When the `locations` option is on, two more parameters are + // passed, the full `{line, column}` locations of the start and + // end of the comments. Note that you are not allowed to call the + // parser from the callback—that will corrupt its internal state. + onComment: null, + // Nodes have their start and end characters offsets recorded in + // `start` and `end` properties (directly on the node, rather than + // the `loc` object, which holds line/column data. To also add a + // [semi-standardized][range] `range` property holding a `[start, + // end]` array with the same numbers, set the `ranges` option to + // `true`. + // + // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 + ranges: false, + // It is possible to parse multiple files into a single AST by + // passing the tree produced by parsing the first file as + // `program` option in subsequent parses. This will add the + // toplevel forms of the parsed file to the `Program` (top) node + // of an existing parse tree. + program: null, + // When `locations` is on, you can pass this to record the source + // file in every node's `loc` object. + sourceFile: null, + // This value, if given, is stored in every node, whether + // `locations` is on or off. + directSourceFile: null, + // When enabled, parenthesized expressions are represented by + // (non-standard) ParenthesizedExpression nodes + preserveParens: false + }; + + // This function tries to parse a single expression at a given + // offset in a string. Useful for parsing mixed-language formats + // that embed JavaScript expressions. + + exports.parseExpressionAt = function(inpt, pos, opts) { + input = String(inpt); inputLen = input.length; + setOptions(opts); + initTokenState(pos); + initParserState(); + return parseExpression(); + }; + + var isArray = function (obj) { + return Object.prototype.toString.call(obj) === "[object Array]"; + }; + + function setOptions(opts) { + options = {}; + for (var opt in defaultOptions) + options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; + sourceFile = options.sourceFile || null; + if (isArray(options.onToken)) { + var tokens = options.onToken; + options.onToken = function (token) { + tokens.push(token); + }; + } + if (isArray(options.onComment)) { + var comments = options.onComment; + options.onComment = function (block, text, start, end, startLoc, endLoc) { + var comment = { + type: block ? 'Block' : 'Line', + value: text, + start: start, + end: end + }; + if (options.locations) { + comment.loc = new SourceLocation(); + comment.loc.start = startLoc; + comment.loc.end = endLoc; + } + if (options.ranges) + comment.range = [start, end]; + comments.push(comment); + }; + } + isKeyword = options.ecmaVersion >= 6 ? isEcma6Keyword : isEcma5AndLessKeyword; + } + + // The `getLineInfo` function is mostly useful when the + // `locations` option is off (for performance reasons) and you + // want to find the line/column position for a given character + // offset. `input` should be the code string that the offset refers + // into. + + var getLineInfo = exports.getLineInfo = function(input, offset) { + for (var line = 1, cur = 0;;) { + lineBreak.lastIndex = cur; + var match = lineBreak.exec(input); + if (match && match.index < offset) { + ++line; + cur = match.index + match[0].length; + } else break; + } + return {line: line, column: offset - cur}; + }; + + function Token() { + this.type = tokType; + this.value = tokVal; + this.start = tokStart; + this.end = tokEnd; + if (options.locations) { + this.loc = new SourceLocation(); + this.loc.end = tokEndLoc; + // TODO: remove in next major release + this.startLoc = tokStartLoc; + this.endLoc = tokEndLoc; + } + if (options.ranges) + this.range = [tokStart, tokEnd]; + } + + exports.Token = Token; + + // Acorn is organized as a tokenizer and a recursive-descent parser. + // The `tokenize` export provides an interface to the tokenizer. + // Because the tokenizer is optimized for being efficiently used by + // the Acorn parser itself, this interface is somewhat crude and not + // very modular. Performing another parse or call to `tokenize` will + // reset the internal state, and invalidate existing tokenizers. + + exports.tokenize = function(inpt, opts) { + input = String(inpt); inputLen = input.length; + setOptions(opts); + initTokenState(); + skipSpace(); + + function getToken(forceRegexp) { + lastEnd = tokEnd; + readToken(forceRegexp); + return new Token(); + } + getToken.jumpTo = function(pos, reAllowed) { + tokPos = pos; + if (options.locations) { + tokCurLine = 1; + tokLineStart = lineBreak.lastIndex = 0; + var match; + while ((match = lineBreak.exec(input)) && match.index < pos) { + ++tokCurLine; + tokLineStart = match.index + match[0].length; + } + } + tokRegexpAllowed = reAllowed; + skipSpace(); + }; + getToken.noRegexp = function() { + tokRegexpAllowed = false; + }; + getToken.options = options; + return getToken; + }; + + // State is kept in (closure-)global variables. We already saw the + // `options`, `input`, and `inputLen` variables above. + + // The current position of the tokenizer in the input. + + var tokPos; + + // The start and end offsets of the current token. + + var tokStart, tokEnd; + + // When `options.locations` is true, these hold objects + // containing the tokens start and end line/column pairs. + + var tokStartLoc, tokEndLoc; + + // The type and value of the current token. Token types are objects, + // named by variables against which they can be compared, and + // holding properties that describe them (indicating, for example, + // the precedence of an infix operator, and the original name of a + // keyword token). The kind of value that's held in `tokVal` depends + // on the type of the token. For literals, it is the literal value, + // for operators, the operator name, and so on. + + var tokType, tokVal; + + // Internal state for the tokenizer. To distinguish between division + // operators and regular expressions, it remembers whether the last + // token was one that is allowed to be followed by an expression. + // (If it is, a slash is probably a regexp, if it isn't it's a + // division operator. See the `parseStatement` function for a + // caveat.) + + var tokRegexpAllowed; + + // When `options.locations` is true, these are used to keep + // track of the current line, and know when a new line has been + // entered. + + var tokCurLine, tokLineStart; + + // These store the position of the previous token, which is useful + // when finishing a node and assigning its `end` position. + + var lastStart, lastEnd, lastEndLoc; + + // This is the parser's state. `inFunction` is used to reject + // `return` statements outside of functions, `inGenerator` to + // reject `yield`s outside of generators, `labels` to verify + // that `break` and `continue` have somewhere to jump to, and + // `strict` indicates whether strict mode is on. + + var inFunction, inGenerator, labels, strict; + + // This counter is used for checking that arrow expressions did + // not contain nested parentheses in argument list. + + var metParenL; + + // This is used by the tokenizer to track the template strings it is + // inside, and count the amount of open braces seen inside them, to + // be able to switch back to a template token when the } to match ${ + // is encountered. It will hold an array of integers. + + var templates; + + function initParserState() { + lastStart = lastEnd = tokPos; + if (options.locations) lastEndLoc = curPosition(); + inFunction = inGenerator = strict = false; + labels = []; + skipSpace(); + readToken(); + } + + // This function is used to raise exceptions on parse errors. It + // takes an offset integer (into the current `input`) to indicate + // the location of the error, attaches the position to the end + // of the error message, and then raises a `SyntaxError` with that + // message. + + function raise(pos, message) { + var loc = getLineInfo(input, pos); + message += " (" + loc.line + ":" + loc.column + ")"; + var err = new SyntaxError(message); + err.pos = pos; err.loc = loc; err.raisedAt = tokPos; + throw err; + } + + // Reused empty array added for node fields that are always empty. + + var empty = []; + + // ## Token types + + // The assignment of fine-grained, information-carrying type objects + // allows the tokenizer to store the information it has about a + // token in a way that is very cheap for the parser to look up. + + // All token type variables start with an underscore, to make them + // easy to recognize. + + // These are the general types. The `type` property is only used to + // make them recognizeable when debugging. + + var _num = {type: "num"}, _regexp = {type: "regexp"}, _string = {type: "string"}; + var _name = {type: "name"}, _eof = {type: "eof"}; + + // Keyword tokens. The `keyword` property (also used in keyword-like + // operators) indicates that the token originated from an + // identifier-like word, which is used when parsing property names. + // + // The `beforeExpr` property is used to disambiguate between regular + // expressions and divisions. It is set on all token types that can + // be followed by an expression (thus, a slash after them would be a + // regular expression). + // + // `isLoop` marks a keyword as starting a loop, which is important + // to know when parsing a label, in order to allow or disallow + // continue jumps to that label. + + var _break = {keyword: "break"}, _case = {keyword: "case", beforeExpr: true}, _catch = {keyword: "catch"}; + var _continue = {keyword: "continue"}, _debugger = {keyword: "debugger"}, _default = {keyword: "default"}; + var _do = {keyword: "do", isLoop: true}, _else = {keyword: "else", beforeExpr: true}; + var _finally = {keyword: "finally"}, _for = {keyword: "for", isLoop: true}, _function = {keyword: "function"}; + var _if = {keyword: "if"}, _return = {keyword: "return", beforeExpr: true}, _switch = {keyword: "switch"}; + var _throw = {keyword: "throw", beforeExpr: true}, _try = {keyword: "try"}, _var = {keyword: "var"}; + var _let = {keyword: "let"}, _const = {keyword: "const"}; + var _while = {keyword: "while", isLoop: true}, _with = {keyword: "with"}, _new = {keyword: "new", beforeExpr: true}; + var _this = {keyword: "this"}; + var _class = {keyword: "class"}, _extends = {keyword: "extends", beforeExpr: true}; + var _export = {keyword: "export"}, _import = {keyword: "import"}; + var _yield = {keyword: "yield", beforeExpr: true}; + + // The keywords that denote values. + + var _null = {keyword: "null", atomValue: null}, _true = {keyword: "true", atomValue: true}; + var _false = {keyword: "false", atomValue: false}; + + // Some keywords are treated as regular operators. `in` sometimes + // (when parsing `for`) needs to be tested against specifically, so + // we assign a variable name to it for quick comparing. + + var _in = {keyword: "in", binop: 7, beforeExpr: true}; + + // Map keyword names to token types. + + var keywordTypes = {"break": _break, "case": _case, "catch": _catch, + "continue": _continue, "debugger": _debugger, "default": _default, + "do": _do, "else": _else, "finally": _finally, "for": _for, + "function": _function, "if": _if, "return": _return, "switch": _switch, + "throw": _throw, "try": _try, "var": _var, "let": _let, "const": _const, + "while": _while, "with": _with, + "null": _null, "true": _true, "false": _false, "new": _new, "in": _in, + "instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true}, "this": _this, + "typeof": {keyword: "typeof", prefix: true, beforeExpr: true}, + "void": {keyword: "void", prefix: true, beforeExpr: true}, + "delete": {keyword: "delete", prefix: true, beforeExpr: true}, + "class": _class, "extends": _extends, + "export": _export, "import": _import, "yield": _yield}; + + // Punctuation token types. Again, the `type` property is purely for debugging. + + var _bracketL = {type: "[", beforeExpr: true}, _bracketR = {type: "]"}, _braceL = {type: "{", beforeExpr: true}; + var _braceR = {type: "}"}, _parenL = {type: "(", beforeExpr: true}, _parenR = {type: ")"}; + var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true}; + var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _question = {type: "?", beforeExpr: true}; + var _arrow = {type: "=>", beforeExpr: true}, _template = {type: "template"}, _templateContinued = {type: "templateContinued"}; + var _ellipsis = {type: "...", prefix: true, beforeExpr: true}; + + // Operators. These carry several kinds of properties to help the + // parser use them properly (the presence of these properties is + // what categorizes them as operators). + // + // `binop`, when present, specifies that this operator is a binary + // operator, and will refer to its precedence. + // + // `prefix` and `postfix` mark the operator as a prefix or postfix + // unary operator. `isUpdate` specifies that the node produced by + // the operator should be of type UpdateExpression rather than + // simply UnaryExpression (`++` and `--`). + // + // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as + // binary operators with a very low precedence, that should result + // in AssignmentExpression nodes. + + var _slash = {binop: 10, beforeExpr: true}, _eq = {isAssign: true, beforeExpr: true}; + var _assign = {isAssign: true, beforeExpr: true}; + var _incDec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true}; + var _logicalOR = {binop: 1, beforeExpr: true}; + var _logicalAND = {binop: 2, beforeExpr: true}; + var _bitwiseOR = {binop: 3, beforeExpr: true}; + var _bitwiseXOR = {binop: 4, beforeExpr: true}; + var _bitwiseAND = {binop: 5, beforeExpr: true}; + var _equality = {binop: 6, beforeExpr: true}; + var _relational = {binop: 7, beforeExpr: true}; + var _bitShift = {binop: 8, beforeExpr: true}; + var _plusMin = {binop: 9, prefix: true, beforeExpr: true}; + var _modulo = {binop: 10, beforeExpr: true}; + + // '*' may be multiply or have special meaning in ES6 + var _star = {binop: 10, beforeExpr: true}; + + // Provide access to the token types for external users of the + // tokenizer. + + exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR, + parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon, + dot: _dot, ellipsis: _ellipsis, question: _question, slash: _slash, eq: _eq, + name: _name, eof: _eof, num: _num, regexp: _regexp, string: _string, + arrow: _arrow, template: _template, templateContinued: _templateContinued, star: _star, + assign: _assign}; + for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw]; + + // This is a trick taken from Esprima. It turns out that, on + // non-Chrome browsers, to check whether a string is in a set, a + // predicate containing a big ugly `switch` statement is faster than + // a regular expression, and on Chrome the two are about on par. + // This function uses `eval` (non-lexical) to produce such a + // predicate from a space-separated string of words. + // + // It starts by sorting the words by length. + + function makePredicate(words) { + words = words.split(" "); + var f = "", cats = []; + out: for (var i = 0; i < words.length; ++i) { + for (var j = 0; j < cats.length; ++j) + if (cats[j][0].length == words[i].length) { + cats[j].push(words[i]); + continue out; + } + cats.push([words[i]]); + } + function compareTo(arr) { + if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";"; + f += "switch(str){"; + for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":"; + f += "return true}return false;"; + } + + // When there are more than three length categories, an outer + // switch first dispatches on the lengths, to save on comparisons. + + if (cats.length > 3) { + cats.sort(function(a, b) {return b.length - a.length;}); + f += "switch(str.length){"; + for (var i = 0; i < cats.length; ++i) { + var cat = cats[i]; + f += "case " + cat[0].length + ":"; + compareTo(cat); + } + f += "}"; + + // Otherwise, simply generate a flat `switch` statement. + + } else { + compareTo(words); + } + return new Function("str", f); + } + + // The ECMAScript 3 reserved word list. + + var isReservedWord3 = makePredicate("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"); + + // ECMAScript 5 reserved words. + + var isReservedWord5 = makePredicate("class enum extends super const export import"); + + // The additional reserved words in strict mode. + + var isStrictReservedWord = makePredicate("implements interface let package private protected public static yield"); + + // The forbidden variable names in strict mode. + + var isStrictBadIdWord = makePredicate("eval arguments"); + + // And the keywords. + + var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; + + var isEcma5AndLessKeyword = makePredicate(ecma5AndLessKeywords); + + var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const class extends export import yield"); + + var isKeyword = isEcma5AndLessKeyword; + + // ## Character categories + + // Big ugly regular expressions that match characters in the + // whitespace, identifier, and identifier-start categories. These + // are only applied when a character is found to actually have a + // code point above 128. + // Generated by `tools/generate-identifier-regex.js`. + + var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; + var nonASCIIidentifierStartChars = "\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC"; + var nonASCIIidentifierChars = "\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u0669\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u06F0-\u06F9\u0711\u0730-\u074A\u07A6-\u07B0\u07C0-\u07C9\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0966-\u096F\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09E6-\u09EF\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A66-\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B66-\u0B6F\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0CE6-\u0CEF\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D66-\u0D6F\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0E50-\u0E59\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0ED0-\u0ED9\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1040-\u1049\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19B0-\u19C0\u19C8\u19C9\u19D0-\u19D9\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AB0-\u1ABD\u1B00-\u1B04\u1B34-\u1B44\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BF3\u1C24-\u1C37\u1C40-\u1C49\u1C50-\u1C59\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u200C\u200D\u203F\u2040\u2054\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA620-\uA629\uA66F\uA674-\uA67D\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F1\uA900-\uA909\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9D0-\uA9D9\uA9E5\uA9F0-\uA9F9\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA50-\uAA59\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uABF0-\uABF9\uFB1E\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFF10-\uFF19\uFF3F"; + var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); + var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); + + // Whether a single character denotes a newline. + + var newline = /[\n\r\u2028\u2029]/; + + function isNewLine(code) { + return code === 10 || code === 13 || code === 0x2028 || code == 0x2029; + } + + // Matches a whole line break (where CRLF is considered a single + // line break). Used to count lines. + + var lineBreak = /\r\n|[\n\r\u2028\u2029]/g; + + // Test whether a given character code starts an identifier. + + var isIdentifierStart = exports.isIdentifierStart = function(code) { + if (code < 65) return code === 36; + if (code < 91) return true; + if (code < 97) return code === 95; + if (code < 123)return true; + return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); + }; + + // Test whether a given character is part of an identifier. + + var isIdentifierChar = exports.isIdentifierChar = function(code) { + if (code < 48) return code === 36; + if (code < 58) return true; + if (code < 65) return false; + if (code < 91) return true; + if (code < 97) return code === 95; + if (code < 123)return true; + return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); + }; + + // ## Tokenizer + + // These are used when `options.locations` is on, for the + // `tokStartLoc` and `tokEndLoc` properties. + + function Position(line, col) { + this.line = line; + this.column = col; + } + + Position.prototype.offset = function(n) { + return new Position(this.line, this.column + n); + } + + function curPosition() { + return new Position(tokCurLine, tokPos - tokLineStart); + } + + // Reset the token state. Used at the start of a parse. + + function initTokenState(pos) { + if (pos) { + tokPos = pos; + tokLineStart = Math.max(0, input.lastIndexOf("\n", pos)); + tokCurLine = input.slice(0, tokLineStart).split(newline).length; + } else { + tokCurLine = 1; + tokPos = tokLineStart = 0; + } + tokRegexpAllowed = true; + metParenL = 0; + templates = []; + } + + // Called at the end of every token. Sets `tokEnd`, `tokVal`, and + // `tokRegexpAllowed`, and skips the space after the token, so that + // the next one's `tokStart` will point at the right position. + + function finishToken(type, val, shouldSkipSpace) { + tokEnd = tokPos; + if (options.locations) tokEndLoc = curPosition(); + tokType = type; + if (shouldSkipSpace !== false) skipSpace(); + tokVal = val; + tokRegexpAllowed = type.beforeExpr; + if (options.onToken) { + options.onToken(new Token()); + } + } + + function skipBlockComment() { + var startLoc = options.onComment && options.locations && curPosition(); + var start = tokPos, end = input.indexOf("*/", tokPos += 2); + if (end === -1) raise(tokPos - 2, "Unterminated comment"); + tokPos = end + 2; + if (options.locations) { + lineBreak.lastIndex = start; + var match; + while ((match = lineBreak.exec(input)) && match.index < tokPos) { + ++tokCurLine; + tokLineStart = match.index + match[0].length; + } + } + if (options.onComment) + options.onComment(true, input.slice(start + 2, end), start, tokPos, + startLoc, options.locations && curPosition()); + } + + function skipLineComment(startSkip) { + var start = tokPos; + var startLoc = options.onComment && options.locations && curPosition(); + var ch = input.charCodeAt(tokPos+=startSkip); + while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { + ++tokPos; + ch = input.charCodeAt(tokPos); + } + if (options.onComment) + options.onComment(false, input.slice(start + startSkip, tokPos), start, tokPos, + startLoc, options.locations && curPosition()); + } + + // Called at the start of the parse and after every token. Skips + // whitespace and comments, and. + + function skipSpace() { + while (tokPos < inputLen) { + var ch = input.charCodeAt(tokPos); + if (ch === 32) { // ' ' + ++tokPos; + } else if (ch === 13) { + ++tokPos; + var next = input.charCodeAt(tokPos); + if (next === 10) { + ++tokPos; + } + if (options.locations) { + ++tokCurLine; + tokLineStart = tokPos; + } + } else if (ch === 10 || ch === 8232 || ch === 8233) { + ++tokPos; + if (options.locations) { + ++tokCurLine; + tokLineStart = tokPos; + } + } else if (ch > 8 && ch < 14) { + ++tokPos; + } else if (ch === 47) { // '/' + var next = input.charCodeAt(tokPos + 1); + if (next === 42) { // '*' + skipBlockComment(); + } else if (next === 47) { // '/' + skipLineComment(2); + } else break; + } else if (ch === 160) { // '\xa0' + ++tokPos; + } else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { + ++tokPos; + } else { + break; + } + } + } + + // ### Token reading + + // This is the function that is called to fetch the next token. It + // is somewhat obscure, because it works in character codes rather + // than characters, and because operator parsing has been inlined + // into it. + // + // All in the name of speed. + // + // The `forceRegexp` parameter is used in the one case where the + // `tokRegexpAllowed` trick does not work. See `parseStatement`. + + function readToken_dot() { + var next = input.charCodeAt(tokPos + 1); + if (next >= 48 && next <= 57) return readNumber(true); + var next2 = input.charCodeAt(tokPos + 2); + if (options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' + tokPos += 3; + return finishToken(_ellipsis); + } else { + ++tokPos; + return finishToken(_dot); + } + } + + function readToken_slash() { // '/' + var next = input.charCodeAt(tokPos + 1); + if (tokRegexpAllowed) {++tokPos; return readRegexp();} + if (next === 61) return finishOp(_assign, 2); + return finishOp(_slash, 1); + } + + function readToken_mult_modulo(code) { // '%*' + var next = input.charCodeAt(tokPos + 1); + if (next === 61) return finishOp(_assign, 2); + return finishOp(code === 42 ? _star : _modulo, 1); + } + + function readToken_pipe_amp(code) { // '|&' + var next = input.charCodeAt(tokPos + 1); + if (next === code) return finishOp(code === 124 ? _logicalOR : _logicalAND, 2); + if (next === 61) return finishOp(_assign, 2); + return finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1); + } + + function readToken_caret() { // '^' + var next = input.charCodeAt(tokPos + 1); + if (next === 61) return finishOp(_assign, 2); + return finishOp(_bitwiseXOR, 1); + } + + function readToken_plus_min(code) { // '+-' + var next = input.charCodeAt(tokPos + 1); + if (next === code) { + if (next == 45 && input.charCodeAt(tokPos + 2) == 62 && + newline.test(input.slice(lastEnd, tokPos))) { + // A `-->` line comment + skipLineComment(3); + skipSpace(); + return readToken(); + } + return finishOp(_incDec, 2); + } + if (next === 61) return finishOp(_assign, 2); + return finishOp(_plusMin, 1); + } + + function readToken_lt_gt(code) { // '<>' + var next = input.charCodeAt(tokPos + 1); + var size = 1; + if (next === code) { + size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2; + if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1); + return finishOp(_bitShift, size); + } + if (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 && + input.charCodeAt(tokPos + 3) == 45) { + // `<!--`, an XML-style comment that should be interpreted as a line comment + skipLineComment(4); + skipSpace(); + return readToken(); + } + if (next === 61) + size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2; + return finishOp(_relational, size); + } + + function readToken_eq_excl(code) { // '=!', '=>' + var next = input.charCodeAt(tokPos + 1); + if (next === 61) return finishOp(_equality, input.charCodeAt(tokPos + 2) === 61 ? 3 : 2); + if (code === 61 && next === 62 && options.ecmaVersion >= 6) { // '=>' + tokPos += 2; + return finishToken(_arrow); + } + return finishOp(code === 61 ? _eq : _prefix, 1); + } + + function getTokenFromCode(code) { + switch (code) { + // The interpretation of a dot depends on whether it is followed + // by a digit or another two dots. + case 46: // '.' + return readToken_dot(); + + // Punctuation tokens. + case 40: ++tokPos; return finishToken(_parenL); + case 41: ++tokPos; return finishToken(_parenR); + case 59: ++tokPos; return finishToken(_semi); + case 44: ++tokPos; return finishToken(_comma); + case 91: ++tokPos; return finishToken(_bracketL); + case 93: ++tokPos; return finishToken(_bracketR); + case 123: + ++tokPos; + if (templates.length) ++templates[templates.length - 1]; + return finishToken(_braceL); + case 125: + ++tokPos; + if (templates.length && --templates[templates.length - 1] === 0) + return readTemplateString(_templateContinued); + else + return finishToken(_braceR); + case 58: ++tokPos; return finishToken(_colon); + case 63: ++tokPos; return finishToken(_question); + + case 96: // '`' + if (options.ecmaVersion >= 6) { + ++tokPos; + return readTemplateString(_template); + } + + case 48: // '0' + var next = input.charCodeAt(tokPos + 1); + if (next === 120 || next === 88) return readRadixNumber(16); // '0x', '0X' - hex number + if (options.ecmaVersion >= 6) { + if (next === 111 || next === 79) return readRadixNumber(8); // '0o', '0O' - octal number + if (next === 98 || next === 66) return readRadixNumber(2); // '0b', '0B' - binary number + } + // Anything else beginning with a digit is an integer, octal + // number, or float. + case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9 + return readNumber(false); + + // Quotes produce strings. + case 34: case 39: // '"', "'" + return readString(code); + + // Operators are parsed inline in tiny state machines. '=' (61) is + // often referred to. `finishOp` simply skips the amount of + // characters it is given as second argument, and returns a token + // of the type given by its first argument. + + case 47: // '/' + return readToken_slash(); + + case 37: case 42: // '%*' + return readToken_mult_modulo(code); + + case 124: case 38: // '|&' + return readToken_pipe_amp(code); + + case 94: // '^' + return readToken_caret(); + + case 43: case 45: // '+-' + return readToken_plus_min(code); + + case 60: case 62: // '<>' + return readToken_lt_gt(code); + + case 61: case 33: // '=!' + return readToken_eq_excl(code); + + case 126: // '~' + return finishOp(_prefix, 1); + } + + return false; + } + + function readToken(forceRegexp) { + if (!forceRegexp) tokStart = tokPos; + else tokPos = tokStart + 1; + if (options.locations) tokStartLoc = curPosition(); + if (forceRegexp) return readRegexp(); + if (tokPos >= inputLen) return finishToken(_eof); + + var code = input.charCodeAt(tokPos); + + // Identifier or keyword. '\uXXXX' sequences are allowed in + // identifiers, so '\' also dispatches to that. + if (isIdentifierStart(code) || code === 92 /* '\' */) return readWord(); + + var tok = getTokenFromCode(code); + + if (tok === false) { + // If we are here, we either found a non-ASCII identifier + // character, or something that's entirely disallowed. + var ch = String.fromCharCode(code); + if (ch === "\\" || nonASCIIidentifierStart.test(ch)) return readWord(); + raise(tokPos, "Unexpected character '" + ch + "'"); + } + return tok; + } + + function finishOp(type, size) { + var str = input.slice(tokPos, tokPos + size); + tokPos += size; + finishToken(type, str); + } + + var regexpUnicodeSupport = false; + try { new RegExp("\uffff", "u"); regexpUnicodeSupport = true; } + catch(e) {} + + // Parse a regular expression. Some context-awareness is necessary, + // since a '/' inside a '[]' set does not end the expression. + + function readRegexp() { + var content = "", escaped, inClass, start = tokPos; + for (;;) { + if (tokPos >= inputLen) raise(start, "Unterminated regular expression"); + var ch = input.charAt(tokPos); + if (newline.test(ch)) raise(start, "Unterminated regular expression"); + if (!escaped) { + if (ch === "[") inClass = true; + else if (ch === "]" && inClass) inClass = false; + else if (ch === "/" && !inClass) break; + escaped = ch === "\\"; + } else escaped = false; + ++tokPos; + } + var content = input.slice(start, tokPos); + ++tokPos; + // Need to use `readWord1` because '\uXXXX' sequences are allowed + // here (don't ask). + var mods = readWord1(); + var tmp = content; + if (mods) { + var validFlags = /^[gmsiy]*$/; + if (options.ecmaVersion >= 6) validFlags = /^[gmsiyu]*$/; + if (!validFlags.test(mods)) raise(start, "Invalid regular expression flag"); + if (mods.indexOf('u') >= 0 && !regexpUnicodeSupport) { + // Replace each astral symbol and every Unicode code point + // escape sequence that represents such a symbol with a single + // ASCII symbol to avoid throwing on regular expressions that + // are only valid in combination with the `/u` flag. + tmp = tmp + .replace(/\\u\{([0-9a-fA-F]{5,6})\}/g, "x") + .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "x"); + } + } + // Detect invalid regular expressions. + try { + new RegExp(tmp); + } catch (e) { + if (e instanceof SyntaxError) raise(start, "Error parsing regular expression: " + e.message); + raise(e); + } + // Get a regular expression object for this pattern-flag pair, or `null` in + // case the current environment doesn't support the flags it uses. + try { + var value = new RegExp(content, mods); + } catch (err) { + value = null; + } + return finishToken(_regexp, {pattern: content, flags: mods, value: value}); + } + + // Read an integer in the given radix. Return null if zero digits + // were read, the integer value otherwise. When `len` is given, this + // will return `null` unless the integer has exactly `len` digits. + + function readInt(radix, len) { + var start = tokPos, total = 0; + for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) { + var code = input.charCodeAt(tokPos), val; + if (code >= 97) val = code - 97 + 10; // a + else if (code >= 65) val = code - 65 + 10; // A + else if (code >= 48 && code <= 57) val = code - 48; // 0-9 + else val = Infinity; + if (val >= radix) break; + ++tokPos; + total = total * radix + val; + } + if (tokPos === start || len != null && tokPos - start !== len) return null; + + return total; + } + + function readRadixNumber(radix) { + tokPos += 2; // 0x + var val = readInt(radix); + if (val == null) raise(tokStart + 2, "Expected number in radix " + radix); + if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number"); + return finishToken(_num, val); + } + + // Read an integer, octal integer, or floating-point number. + + function readNumber(startsWithDot) { + var start = tokPos, isFloat = false, octal = input.charCodeAt(tokPos) === 48; + if (!startsWithDot && readInt(10) === null) raise(start, "Invalid number"); + if (input.charCodeAt(tokPos) === 46) { + ++tokPos; + readInt(10); + isFloat = true; + } + var next = input.charCodeAt(tokPos); + if (next === 69 || next === 101) { // 'eE' + next = input.charCodeAt(++tokPos); + if (next === 43 || next === 45) ++tokPos; // '+-' + if (readInt(10) === null) raise(start, "Invalid number"); + isFloat = true; + } + if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number"); + + var str = input.slice(start, tokPos), val; + if (isFloat) val = parseFloat(str); + else if (!octal || str.length === 1) val = parseInt(str, 10); + else if (/[89]/.test(str) || strict) raise(start, "Invalid number"); + else val = parseInt(str, 8); + return finishToken(_num, val); + } + + // Read a string value, interpreting backslash-escapes. + + function readCodePoint() { + var ch = input.charCodeAt(tokPos), code; + + if (ch === 123) { + if (options.ecmaVersion < 6) unexpected(); + ++tokPos; + code = readHexChar(input.indexOf('}', tokPos) - tokPos); + ++tokPos; + if (code > 0x10FFFF) unexpected(); + } else { + code = readHexChar(4); + } + + // UTF-16 Encoding + if (code <= 0xFFFF) { + return String.fromCharCode(code); + } + var cu1 = ((code - 0x10000) >> 10) + 0xD800; + var cu2 = ((code - 0x10000) & 1023) + 0xDC00; + return String.fromCharCode(cu1, cu2); + } + + function readString(quote) { + ++tokPos; + var out = ""; + for (;;) { + if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant"); + var ch = input.charCodeAt(tokPos); + if (ch === quote) { + ++tokPos; + return finishToken(_string, out); + } + if (ch === 92) { // '\' + out += readEscapedChar(); + } else { + ++tokPos; + if (newline.test(String.fromCharCode(ch))) { + raise(tokStart, "Unterminated string constant"); + } + out += String.fromCharCode(ch); // '\' + } + } + } + + function readTemplateString(type) { + if (type == _templateContinued) templates.pop(); + var out = "", start = tokPos;; + for (;;) { + if (tokPos >= inputLen) raise(tokStart, "Unterminated template"); + var ch = input.charAt(tokPos); + if (ch === "`" || ch === "$" && input.charCodeAt(tokPos + 1) === 123) { // '`', '${' + var raw = input.slice(start, tokPos); + ++tokPos; + if (ch == "$") { ++tokPos; templates.push(1); } + return finishToken(type, {cooked: out, raw: raw}); + } + + if (ch === "\\") { // '\' + out += readEscapedChar(); + } else { + ++tokPos; + if (newline.test(ch)) { + if (ch === "\r" && input.charCodeAt(tokPos) === 10) { + ++tokPos; + ch = "\n"; + } + if (options.locations) { + ++tokCurLine; + tokLineStart = tokPos; + } + } + out += ch; + } + } + } + + // Used to read escaped characters + + function readEscapedChar() { + var ch = input.charCodeAt(++tokPos); + var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3)); + if (octal) octal = octal[0]; + while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1); + if (octal === "0") octal = null; + ++tokPos; + if (octal) { + if (strict) raise(tokPos - 2, "Octal literal in strict mode"); + tokPos += octal.length - 1; + return String.fromCharCode(parseInt(octal, 8)); + } else { + switch (ch) { + case 110: return "\n"; // 'n' -> '\n' + case 114: return "\r"; // 'r' -> '\r' + case 120: return String.fromCharCode(readHexChar(2)); // 'x' + case 117: return readCodePoint(); // 'u' + case 116: return "\t"; // 't' -> '\t' + case 98: return "\b"; // 'b' -> '\b' + case 118: return "\u000b"; // 'v' -> '\u000b' + case 102: return "\f"; // 'f' -> '\f' + case 48: return "\0"; // 0 -> '\0' + case 13: if (input.charCodeAt(tokPos) === 10) ++tokPos; // '\r\n' + case 10: // ' \n' + if (options.locations) { tokLineStart = tokPos; ++tokCurLine; } + return ""; + default: return String.fromCharCode(ch); + } + } + } + + // Used to read character escape sequences ('\x', '\u', '\U'). + + function readHexChar(len) { + var n = readInt(16, len); + if (n === null) raise(tokStart, "Bad character escape sequence"); + return n; + } + + // Used to signal to callers of `readWord1` whether the word + // contained any escape sequences. This is needed because words with + // escape sequences must not be interpreted as keywords. + + var containsEsc; + + // Read an identifier, and return it as a string. Sets `containsEsc` + // to whether the word contained a '\u' escape. + // + // Only builds up the word character-by-character when it actually + // containeds an escape, as a micro-optimization. + + function readWord1() { + containsEsc = false; + var word, first = true, start = tokPos; + for (;;) { + var ch = input.charCodeAt(tokPos); + if (isIdentifierChar(ch)) { + if (containsEsc) word += input.charAt(tokPos); + ++tokPos; + } else if (ch === 92) { // "\" + if (!containsEsc) word = input.slice(start, tokPos); + containsEsc = true; + if (input.charCodeAt(++tokPos) != 117) // "u" + raise(tokPos, "Expecting Unicode escape sequence \\uXXXX"); + ++tokPos; + var esc = readHexChar(4); + var escStr = String.fromCharCode(esc); + if (!escStr) raise(tokPos - 1, "Invalid Unicode escape"); + if (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc))) + raise(tokPos - 4, "Invalid Unicode escape"); + word += escStr; + } else { + break; + } + first = false; + } + return containsEsc ? word : input.slice(start, tokPos); + } + + // Read an identifier or keyword token. Will check for reserved + // words when necessary. + + function readWord() { + var word = readWord1(); + var type = _name; + if (!containsEsc && isKeyword(word)) + type = keywordTypes[word]; + return finishToken(type, word); + } + + // ## Parser + + // A recursive descent parser operates by defining functions for all + // syntactic elements, and recursively calling those, each function + // advancing the input stream and returning an AST node. Precedence + // of constructs (for example, the fact that `!x[1]` means `!(x[1])` + // instead of `(!x)[1]` is handled by the fact that the parser + // function that parses unary prefix operators is called first, and + // in turn calls the function that parses `[]` subscripts — that + // way, it'll receive the node for `x[1]` already parsed, and wraps + // *that* in the unary operator node. + // + // Acorn uses an [operator precedence parser][opp] to handle binary + // operator precedence, because it is much more compact than using + // the technique outlined above, which uses different, nesting + // functions to specify precedence, for all of the ten binary + // precedence levels that JavaScript defines. + // + // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser + + // ### Parser utilities + + // Continue to the next token. + + function next() { + lastStart = tokStart; + lastEnd = tokEnd; + lastEndLoc = tokEndLoc; + readToken(); + } + + // Enter strict mode. Re-reads the next token to please pedantic + // tests ("use strict"; 010; -- should fail). + + function setStrict(strct) { + strict = strct; + tokPos = tokStart; + if (options.locations) { + while (tokPos < tokLineStart) { + tokLineStart = input.lastIndexOf("\n", tokLineStart - 2) + 1; + --tokCurLine; + } + } + skipSpace(); + readToken(); + } + + // Start an AST node, attaching a start offset. + + function Node() { + this.type = null; + this.start = tokStart; + this.end = null; + } + + exports.Node = Node; + + function SourceLocation() { + this.start = tokStartLoc; + this.end = null; + if (sourceFile !== null) this.source = sourceFile; + } + + function startNode() { + var node = new Node(); + if (options.locations) + node.loc = new SourceLocation(); + if (options.directSourceFile) + node.sourceFile = options.directSourceFile; + if (options.ranges) + node.range = [tokStart, 0]; + return node; + } + + // Sometimes, a node is only started *after* the token stream passed + // its start position. The functions below help storing a position + // and creating a node from a previous position. + + function storeCurrentPos() { + return options.locations ? [tokStart, tokStartLoc] : tokStart; + } + + function startNodeAt(pos) { + var node = new Node(), start = pos; + if (options.locations) { + node.loc = new SourceLocation(); + node.loc.start = start[1]; + start = pos[0]; + } + node.start = start; + if (options.directSourceFile) + node.sourceFile = options.directSourceFile; + if (options.ranges) + node.range = [start, 0]; + + return node; + } + + // Finish an AST node, adding `type` and `end` properties. + + function finishNode(node, type) { + node.type = type; + node.end = lastEnd; + if (options.locations) + node.loc.end = lastEndLoc; + if (options.ranges) + node.range[1] = lastEnd; + return node; + } + + function finishNodeAt(node, type, pos) { + if (options.locations) { node.loc.end = pos[1]; pos = pos[0]; } + node.type = type; + node.end = pos; + if (options.ranges) + node.range[1] = pos; + return node; + } + + // Test whether a statement node is the string literal `"use strict"`. + + function isUseStrict(stmt) { + return options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" && + stmt.expression.type === "Literal" && stmt.expression.value === "use strict"; + } + + // Predicate that tests whether the next token is of the given + // type, and if yes, consumes it as a side effect. + + function eat(type) { + if (tokType === type) { + next(); + return true; + } else { + return false; + } + } + + // Test whether a semicolon can be inserted at the current position. + + function canInsertSemicolon() { + return !options.strictSemicolons && + (tokType === _eof || tokType === _braceR || newline.test(input.slice(lastEnd, tokStart))); + } + + // Consume a semicolon, or, failing that, see if we are allowed to + // pretend that there is a semicolon at this position. + + function semicolon() { + if (!eat(_semi) && !canInsertSemicolon()) unexpected(); + } + + // Expect a token of a given type. If found, consume it, otherwise, + // raise an unexpected token error. + + function expect(type) { + eat(type) || unexpected(); + } + + // Raise an unexpected token error. + + function unexpected(pos) { + raise(pos != null ? pos : tokStart, "Unexpected token"); + } + + // Checks if hash object has a property. + + function has(obj, propName) { + return Object.prototype.hasOwnProperty.call(obj, propName); + } + // Convert existing expression atom to assignable pattern + // if possible. + + function toAssignable(node, allowSpread, checkType) { + if (options.ecmaVersion >= 6 && node) { + switch (node.type) { + case "Identifier": + case "MemberExpression": + break; + + case "ObjectExpression": + node.type = "ObjectPattern"; + for (var i = 0; i < node.properties.length; i++) { + var prop = node.properties[i]; + if (prop.kind !== "init") unexpected(prop.key.start); + toAssignable(prop.value, false, checkType); + } + break; + + case "ArrayExpression": + node.type = "ArrayPattern"; + for (var i = 0, lastI = node.elements.length - 1; i <= lastI; i++) { + toAssignable(node.elements[i], i === lastI, checkType); + } + break; + + case "SpreadElement": + if (allowSpread) { + toAssignable(node.argument, false, checkType); + checkSpreadAssign(node.argument); + } else { + unexpected(node.start); + } + break; + + default: + if (checkType) unexpected(node.start); + } + } + return node; + } + + // Checks if node can be assignable spread argument. + + function checkSpreadAssign(node) { + if (node.type !== "Identifier" && node.type !== "ArrayPattern") + unexpected(node.start); + } + + // Verify that argument names are not repeated, and it does not + // try to bind the words `eval` or `arguments`. + + function checkFunctionParam(param, nameHash) { + switch (param.type) { + case "Identifier": + if (isStrictReservedWord(param.name) || isStrictBadIdWord(param.name)) + raise(param.start, "Defining '" + param.name + "' in strict mode"); + if (has(nameHash, param.name)) + raise(param.start, "Argument name clash in strict mode"); + nameHash[param.name] = true; + break; + + case "ObjectPattern": + for (var i = 0; i < param.properties.length; i++) + checkFunctionParam(param.properties[i].value, nameHash); + break; + + case "ArrayPattern": + for (var i = 0; i < param.elements.length; i++) { + var elem = param.elements[i]; + if (elem) checkFunctionParam(elem, nameHash); + } + break; + } + } + + // Check if property name clashes with already added. + // Object/class getters and setters are not allowed to clash — + // either with each other or with an init property — and in + // strict mode, init properties are also not allowed to be repeated. + + function checkPropClash(prop, propHash) { + if (options.ecmaVersion >= 6) return; + var key = prop.key, name; + switch (key.type) { + case "Identifier": name = key.name; break; + case "Literal": name = String(key.value); break; + default: return; + } + var kind = prop.kind || "init", other; + if (has(propHash, name)) { + other = propHash[name]; + var isGetSet = kind !== "init"; + if ((strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) + raise(key.start, "Redefinition of property"); + } else { + other = propHash[name] = { + init: false, + get: false, + set: false + }; + } + other[kind] = true; + } + + // Verify that a node is an lval — something that can be assigned + // to. + + function checkLVal(expr, isBinding) { + switch (expr.type) { + case "Identifier": + if (strict && (isStrictBadIdWord(expr.name) || isStrictReservedWord(expr.name))) + raise(expr.start, isBinding + ? "Binding " + expr.name + " in strict mode" + : "Assigning to " + expr.name + " in strict mode" + ); + break; + + case "MemberExpression": + if (!isBinding) break; + + case "ObjectPattern": + for (var i = 0; i < expr.properties.length; i++) + checkLVal(expr.properties[i].value, isBinding); + break; + + case "ArrayPattern": + for (var i = 0; i < expr.elements.length; i++) { + var elem = expr.elements[i]; + if (elem) checkLVal(elem, isBinding); + } + break; + + case "SpreadElement": + break; + + default: + raise(expr.start, "Assigning to rvalue"); + } + } + + // ### Statement parsing + + // Parse a program. Initializes the parser, reads any number of + // statements, and wraps them in a Program node. Optionally takes a + // `program` argument. If present, the statements will be appended + // to its body instead of creating a new node. + + function parseTopLevel(node) { + var first = true; + if (!node.body) node.body = []; + while (tokType !== _eof) { + var stmt = parseStatement(true); + node.body.push(stmt); + if (first && isUseStrict(stmt)) setStrict(true); + first = false; + } + + lastStart = tokStart; + lastEnd = tokEnd; + lastEndLoc = tokEndLoc; + return finishNode(node, "Program"); + } + + var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"}; + + // Parse a single statement. + // + // If expecting a statement and finding a slash operator, parse a + // regular expression literal. This is to handle cases like + // `if (foo) /blah/.exec(foo);`, where looking at the previous token + // does not help. + + function parseStatement(topLevel) { + if (tokType === _slash || tokType === _assign && tokVal == "/=") + readToken(true); + + var starttype = tokType, node = startNode(); + + // Most types of statements are recognized by the keyword they + // start with. Many are trivial to parse, some require a bit of + // complexity. + + switch (starttype) { + case _break: case _continue: return parseBreakContinueStatement(node, starttype.keyword); + case _debugger: return parseDebuggerStatement(node); + case _do: return parseDoStatement(node); + case _for: return parseForStatement(node); + case _function: return parseFunctionStatement(node); + case _class: return parseClass(node, true); + case _if: return parseIfStatement(node); + case _return: return parseReturnStatement(node); + case _switch: return parseSwitchStatement(node); + case _throw: return parseThrowStatement(node); + case _try: return parseTryStatement(node); + case _var: case _let: case _const: return parseVarStatement(node, starttype.keyword); + case _while: return parseWhileStatement(node); + case _with: return parseWithStatement(node); + case _braceL: return parseBlock(); // no point creating a function for this + case _semi: return parseEmptyStatement(node); + case _export: + case _import: + if (!topLevel && !options.allowImportExportEverywhere) + raise(tokStart, "'import' and 'export' may only appear at the top level"); + return starttype === _import ? parseImport(node) : parseExport(node); + + // If the statement does not start with a statement keyword or a + // brace, it's an ExpressionStatement or LabeledStatement. We + // simply start parsing an expression, and afterwards, if the + // next token is a colon and the expression was a simple + // Identifier node, we switch to interpreting it as a label. + default: + var maybeName = tokVal, expr = parseExpression(); + if (starttype === _name && expr.type === "Identifier" && eat(_colon)) + return parseLabeledStatement(node, maybeName, expr); + else return parseExpressionStatement(node, expr); + } + } + + function parseBreakContinueStatement(node, keyword) { + var isBreak = keyword == "break"; + next(); + if (eat(_semi) || canInsertSemicolon()) node.label = null; + else if (tokType !== _name) unexpected(); + else { + node.label = parseIdent(); + semicolon(); + } + + // Verify that there is an actual destination to break or + // continue to. + for (var i = 0; i < labels.length; ++i) { + var lab = labels[i]; + if (node.label == null || lab.name === node.label.name) { + if (lab.kind != null && (isBreak || lab.kind === "loop")) break; + if (node.label && isBreak) break; + } + } + if (i === labels.length) raise(node.start, "Unsyntactic " + keyword); + return finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement"); + } + + function parseDebuggerStatement(node) { + next(); + semicolon(); + return finishNode(node, "DebuggerStatement"); + } + + function parseDoStatement(node) { + next(); + labels.push(loopLabel); + node.body = parseStatement(); + labels.pop(); + expect(_while); + node.test = parseParenExpression(); + if (options.ecmaVersion >= 6) + eat(_semi); + else + semicolon(); + return finishNode(node, "DoWhileStatement"); + } + + // Disambiguating between a `for` and a `for`/`in` or `for`/`of` + // loop is non-trivial. Basically, we have to parse the init `var` + // statement or expression, disallowing the `in` operator (see + // the second parameter to `parseExpression`), and then check + // whether the next token is `in` or `of`. When there is no init + // part (semicolon immediately after the opening parenthesis), it + // is a regular `for` loop. + + function parseForStatement(node) { + next(); + labels.push(loopLabel); + expect(_parenL); + if (tokType === _semi) return parseFor(node, null); + if (tokType === _var || tokType === _let) { + var init = startNode(), varKind = tokType.keyword, isLet = tokType === _let; + next(); + parseVar(init, true, varKind); + finishNode(init, "VariableDeclaration"); + if ((tokType === _in || (options.ecmaVersion >= 6 && tokType === _name && tokVal === "of")) && init.declarations.length === 1 && + !(isLet && init.declarations[0].init)) + return parseForIn(node, init); + return parseFor(node, init); + } + var init = parseExpression(false, true); + if (tokType === _in || (options.ecmaVersion >= 6 && tokType === _name && tokVal === "of")) { + checkLVal(init); + return parseForIn(node, init); + } + return parseFor(node, init); + } + + function parseFunctionStatement(node) { + next(); + return parseFunction(node, true); + } + + function parseIfStatement(node) { + next(); + node.test = parseParenExpression(); + node.consequent = parseStatement(); + node.alternate = eat(_else) ? parseStatement() : null; + return finishNode(node, "IfStatement"); + } + + function parseReturnStatement(node) { + if (!inFunction && !options.allowReturnOutsideFunction) + raise(tokStart, "'return' outside of function"); + next(); + + // In `return` (and `break`/`continue`), the keywords with + // optional arguments, we eagerly look for a semicolon or the + // possibility to insert one. + + if (eat(_semi) || canInsertSemicolon()) node.argument = null; + else { node.argument = parseExpression(); semicolon(); } + return finishNode(node, "ReturnStatement"); + } + + function parseSwitchStatement(node) { + next(); + node.discriminant = parseParenExpression(); + node.cases = []; + expect(_braceL); + labels.push(switchLabel); + + // Statements under must be grouped (by label) in SwitchCase + // nodes. `cur` is used to keep the node that we are currently + // adding statements to. + + for (var cur, sawDefault; tokType != _braceR;) { + if (tokType === _case || tokType === _default) { + var isCase = tokType === _case; + if (cur) finishNode(cur, "SwitchCase"); + node.cases.push(cur = startNode()); + cur.consequent = []; + next(); + if (isCase) cur.test = parseExpression(); + else { + if (sawDefault) raise(lastStart, "Multiple default clauses"); sawDefault = true; + cur.test = null; + } + expect(_colon); + } else { + if (!cur) unexpected(); + cur.consequent.push(parseStatement()); + } + } + if (cur) finishNode(cur, "SwitchCase"); + next(); // Closing brace + labels.pop(); + return finishNode(node, "SwitchStatement"); + } + + function parseThrowStatement(node) { + next(); + if (newline.test(input.slice(lastEnd, tokStart))) + raise(lastEnd, "Illegal newline after throw"); + node.argument = parseExpression(); + semicolon(); + return finishNode(node, "ThrowStatement"); + } + + function parseTryStatement(node) { + next(); + node.block = parseBlock(); + node.handler = null; + if (tokType === _catch) { + var clause = startNode(); + next(); + expect(_parenL); + clause.param = parseIdent(); + if (strict && isStrictBadIdWord(clause.param.name)) + raise(clause.param.start, "Binding " + clause.param.name + " in strict mode"); + expect(_parenR); + clause.guard = null; + clause.body = parseBlock(); + node.handler = finishNode(clause, "CatchClause"); + } + node.guardedHandlers = empty; + node.finalizer = eat(_finally) ? parseBlock() : null; + if (!node.handler && !node.finalizer) + raise(node.start, "Missing catch or finally clause"); + return finishNode(node, "TryStatement"); + } + + function parseVarStatement(node, kind) { + next(); + parseVar(node, false, kind); + semicolon(); + return finishNode(node, "VariableDeclaration"); + } + + function parseWhileStatement(node) { + next(); + node.test = parseParenExpression(); + labels.push(loopLabel); + node.body = parseStatement(); + labels.pop(); + return finishNode(node, "WhileStatement"); + } + + function parseWithStatement(node) { + if (strict) raise(tokStart, "'with' in strict mode"); + next(); + node.object = parseParenExpression(); + node.body = parseStatement(); + return finishNode(node, "WithStatement"); + } + + function parseEmptyStatement(node) { + next(); + return finishNode(node, "EmptyStatement"); + } + + function parseLabeledStatement(node, maybeName, expr) { + for (var i = 0; i < labels.length; ++i) + if (labels[i].name === maybeName) raise(expr.start, "Label '" + maybeName + "' is already declared"); + var kind = tokType.isLoop ? "loop" : tokType === _switch ? "switch" : null; + labels.push({name: maybeName, kind: kind}); + node.body = parseStatement(); + labels.pop(); + node.label = expr; + return finishNode(node, "LabeledStatement"); + } + + function parseExpressionStatement(node, expr) { + node.expression = expr; + semicolon(); + return finishNode(node, "ExpressionStatement"); + } + + // Used for constructs like `switch` and `if` that insist on + // parentheses around their expression. + + function parseParenExpression() { + expect(_parenL); + var val = parseExpression(); + expect(_parenR); + return val; + } + + // Parse a semicolon-enclosed block of statements, handling `"use + // strict"` declarations when `allowStrict` is true (used for + // function bodies). + + function parseBlock(allowStrict) { + var node = startNode(), first = true, oldStrict; + node.body = []; + expect(_braceL); + while (!eat(_braceR)) { + var stmt = parseStatement(); + node.body.push(stmt); + if (first && allowStrict && isUseStrict(stmt)) { + oldStrict = strict; + setStrict(strict = true); + } + first = false; + } + if (oldStrict === false) setStrict(false); + return finishNode(node, "BlockStatement"); + } + + // Parse a regular `for` loop. The disambiguation code in + // `parseStatement` will already have parsed the init statement or + // expression. + + function parseFor(node, init) { + node.init = init; + expect(_semi); + node.test = tokType === _semi ? null : parseExpression(); + expect(_semi); + node.update = tokType === _parenR ? null : parseExpression(); + expect(_parenR); + node.body = parseStatement(); + labels.pop(); + return finishNode(node, "ForStatement"); + } + + // Parse a `for`/`in` and `for`/`of` loop, which are almost + // same from parser's perspective. + + function parseForIn(node, init) { + var type = tokType === _in ? "ForInStatement" : "ForOfStatement"; + next(); + node.left = init; + node.right = parseExpression(); + expect(_parenR); + node.body = parseStatement(); + labels.pop(); + return finishNode(node, type); + } + + // Parse a list of variable declarations. + + function parseVar(node, noIn, kind) { + node.declarations = []; + node.kind = kind; + for (;;) { + var decl = startNode(); + decl.id = options.ecmaVersion >= 6 ? toAssignable(parseExprAtom()) : parseIdent(); + checkLVal(decl.id, true); + decl.init = eat(_eq) ? parseExpression(true, noIn) : (kind === _const.keyword ? unexpected() : null); + node.declarations.push(finishNode(decl, "VariableDeclarator")); + if (!eat(_comma)) break; + } + return node; + } + + // ### Expression parsing + + // These nest, from the most general expression type at the top to + // 'atomic', nondivisible expression types at the bottom. Most of + // the functions will simply let the function(s) below them parse, + // and, *if* the syntactic construct they handle is present, wrap + // the AST node that the inner parser gave them in another node. + + // Parse a full expression. The arguments are used to forbid comma + // sequences (in argument lists, array literals, or object literals) + // or the `in` operator (in for loops initalization expressions). + + function parseExpression(noComma, noIn) { + var start = storeCurrentPos(); + var expr = parseMaybeAssign(noIn); + if (!noComma && tokType === _comma) { + var node = startNodeAt(start); + node.expressions = [expr]; + while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn)); + return finishNode(node, "SequenceExpression"); + } + return expr; + } + + // Parse an assignment expression. This includes applications of + // operators like `+=`. + + function parseMaybeAssign(noIn) { + var start = storeCurrentPos(); + var left = parseMaybeConditional(noIn); + if (tokType.isAssign) { + var node = startNodeAt(start); + node.operator = tokVal; + node.left = tokType === _eq ? toAssignable(left) : left; + checkLVal(left); + next(); + node.right = parseMaybeAssign(noIn); + return finishNode(node, "AssignmentExpression"); + } + return left; + } + + // Parse a ternary conditional (`?:`) operator. + + function parseMaybeConditional(noIn) { + var start = storeCurrentPos(); + var expr = parseExprOps(noIn); + if (eat(_question)) { + var node = startNodeAt(start); + node.test = expr; + node.consequent = parseExpression(true); + expect(_colon); + node.alternate = parseExpression(true, noIn); + return finishNode(node, "ConditionalExpression"); + } + return expr; + } + + // Start the precedence parser. + + function parseExprOps(noIn) { + var start = storeCurrentPos(); + return parseExprOp(parseMaybeUnary(), start, -1, noIn); + } + + // Parse binary operators with the operator precedence parsing + // algorithm. `left` is the left-hand side of the operator. + // `minPrec` provides context that allows the function to stop and + // defer further parser to one of its callers when it encounters an + // operator that has a lower precedence than the set it is parsing. + + function parseExprOp(left, leftStart, minPrec, noIn) { + var prec = tokType.binop; + if (prec != null && (!noIn || tokType !== _in)) { + if (prec > minPrec) { + var node = startNodeAt(leftStart); + node.left = left; + node.operator = tokVal; + var op = tokType; + next(); + var start = storeCurrentPos(); + node.right = parseExprOp(parseMaybeUnary(), start, prec, noIn); + finishNode(node, (op === _logicalOR || op === _logicalAND) ? "LogicalExpression" : "BinaryExpression"); + return parseExprOp(node, leftStart, minPrec, noIn); + } + } + return left; + } + + // Parse unary operators, both prefix and postfix. + + function parseMaybeUnary() { + if (tokType.prefix) { + var node = startNode(), update = tokType.isUpdate, nodeType; + if (tokType === _ellipsis) { + nodeType = "SpreadElement"; + } else { + nodeType = update ? "UpdateExpression" : "UnaryExpression"; + node.operator = tokVal; + node.prefix = true; + } + tokRegexpAllowed = true; + next(); + node.argument = parseMaybeUnary(); + if (update) checkLVal(node.argument); + else if (strict && node.operator === "delete" && + node.argument.type === "Identifier") + raise(node.start, "Deleting local variable in strict mode"); + return finishNode(node, nodeType); + } + var start = storeCurrentPos(); + var expr = parseExprSubscripts(); + while (tokType.postfix && !canInsertSemicolon()) { + var node = startNodeAt(start); + node.operator = tokVal; + node.prefix = false; + node.argument = expr; + checkLVal(expr); + next(); + expr = finishNode(node, "UpdateExpression"); + } + return expr; + } + + // Parse call, dot, and `[]`-subscript expressions. + + function parseExprSubscripts() { + var start = storeCurrentPos(); + return parseSubscripts(parseExprAtom(), start); + } + + function parseSubscripts(base, start, noCalls) { + if (eat(_dot)) { + var node = startNodeAt(start); + node.object = base; + node.property = parseIdent(true); + node.computed = false; + return parseSubscripts(finishNode(node, "MemberExpression"), start, noCalls); + } else if (eat(_bracketL)) { + var node = startNodeAt(start); + node.object = base; + node.property = parseExpression(); + node.computed = true; + expect(_bracketR); + return parseSubscripts(finishNode(node, "MemberExpression"), start, noCalls); + } else if (!noCalls && eat(_parenL)) { + var node = startNodeAt(start); + node.callee = base; + node.arguments = parseExprList(_parenR, false); + return parseSubscripts(finishNode(node, "CallExpression"), start, noCalls); + } else if (tokType === _template) { + var node = startNodeAt(start); + node.tag = base; + node.quasi = parseTemplate(); + return parseSubscripts(finishNode(node, "TaggedTemplateExpression"), start, noCalls); + } return base; + } + + // Parse an atomic expression — either a single token that is an + // expression, an expression started by a keyword like `function` or + // `new`, or an expression wrapped in punctuation like `()`, `[]`, + // or `{}`. + + function parseExprAtom() { + switch (tokType) { + case _this: + var node = startNode(); + next(); + return finishNode(node, "ThisExpression"); + + case _yield: + if (inGenerator) return parseYield(); + + case _name: + var start = storeCurrentPos(); + var id = parseIdent(tokType !== _name); + if (eat(_arrow)) { + return parseArrowExpression(startNodeAt(start), [id]); + } + return id; + + case _regexp: + var node = startNode(); + node.regex = {pattern: tokVal.pattern, flags: tokVal.flags}; + node.value = tokVal.value; + node.raw = input.slice(tokStart, tokEnd); + next(); + return finishNode(node, "Literal"); + + case _num: case _string: + var node = startNode(); + node.value = tokVal; + node.raw = input.slice(tokStart, tokEnd); + next(); + return finishNode(node, "Literal"); + + case _null: case _true: case _false: + var node = startNode(); + node.value = tokType.atomValue; + node.raw = tokType.keyword; + next(); + return finishNode(node, "Literal"); + + case _parenL: + var start = storeCurrentPos(); + var val, exprList; + next(); + // check whether this is generator comprehension or regular expression + if (options.ecmaVersion >= 7 && tokType === _for) { + val = parseComprehension(startNodeAt(start), true); + } else { + var oldParenL = ++metParenL; + if (tokType !== _parenR) { + val = parseExpression(); + exprList = val.type === "SequenceExpression" ? val.expressions : [val]; + } else { + exprList = []; + } + expect(_parenR); + // if '=>' follows '(...)', convert contents to arguments + if (metParenL === oldParenL && eat(_arrow)) { + val = parseArrowExpression(startNodeAt(start), exprList); + } else { + // forbid '()' before everything but '=>' + if (!val) unexpected(lastStart); + // forbid '...' in sequence expressions + if (options.ecmaVersion >= 6) { + for (var i = 0; i < exprList.length; i++) { + if (exprList[i].type === "SpreadElement") unexpected(); + } + } + + if (options.preserveParens) { + var par = startNodeAt(start); + par.expression = val; + val = finishNode(par, "ParenthesizedExpression"); + } + } + } + return val; + + case _bracketL: + var node = startNode(); + next(); + // check whether this is array comprehension or regular array + if (options.ecmaVersion >= 7 && tokType === _for) { + return parseComprehension(node, false); + } + node.elements = parseExprList(_bracketR, true, true); + return finishNode(node, "ArrayExpression"); + + case _braceL: + return parseObj(); + + case _function: + var node = startNode(); + next(); + return parseFunction(node, false); + + case _class: + return parseClass(startNode(), false); + + case _new: + return parseNew(); + + case _template: + return parseTemplate(); + + default: + unexpected(); + } + } + + // New's precedence is slightly tricky. It must allow its argument + // to be a `[]` or dot subscript expression, but not a call — at + // least, not without wrapping it in parentheses. Thus, it uses the + + function parseNew() { + var node = startNode(); + next(); + var start = storeCurrentPos(); + node.callee = parseSubscripts(parseExprAtom(), start, true); + if (eat(_parenL)) node.arguments = parseExprList(_parenR, false); + else node.arguments = empty; + return finishNode(node, "NewExpression"); + } + + // Parse template expression. + + function parseTemplateElement() { + var elem = startNodeAt(options.locations ? [tokStart + 1, tokStartLoc.offset(1)] : tokStart + 1); + elem.value = tokVal; + elem.tail = input.charCodeAt(tokEnd - 1) !== 123; // '{' + next(); + var endOff = elem.tail ? 1 : 2; + return finishNodeAt(elem, "TemplateElement", options.locations ? [lastEnd - endOff, lastEndLoc.offset(-endOff)] : lastEnd - endOff); + } + + function parseTemplate() { + var node = startNode(); + node.expressions = []; + var curElt = parseTemplateElement(); + node.quasis = [curElt]; + while (!curElt.tail) { + node.expressions.push(parseExpression()); + if (tokType !== _templateContinued) unexpected(); + node.quasis.push(curElt = parseTemplateElement()); + } + return finishNode(node, "TemplateLiteral"); + } + + // Parse an object literal. + + function parseObj() { + var node = startNode(), first = true, propHash = {}; + node.properties = []; + next(); + while (!eat(_braceR)) { + if (!first) { + expect(_comma); + if (options.allowTrailingCommas && eat(_braceR)) break; + } else first = false; + + var prop = startNode(), isGenerator; + if (options.ecmaVersion >= 6) { + prop.method = false; + prop.shorthand = false; + isGenerator = eat(_star); + } + parsePropertyName(prop); + if (eat(_colon)) { + prop.value = parseExpression(true); + prop.kind = "init"; + } else if (options.ecmaVersion >= 6 && tokType === _parenL) { + prop.kind = "init"; + prop.method = true; + prop.value = parseMethod(isGenerator); + } else if (options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && + (prop.key.name === "get" || prop.key.name === "set")) { + if (isGenerator) unexpected(); + prop.kind = prop.key.name; + parsePropertyName(prop); + prop.value = parseMethod(false); + } else if (options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { + prop.kind = "init"; + prop.value = prop.key; + prop.shorthand = true; + } else unexpected(); + + checkPropClash(prop, propHash); + node.properties.push(finishNode(prop, "Property")); + } + return finishNode(node, "ObjectExpression"); + } + + function parsePropertyName(prop) { + if (options.ecmaVersion >= 6) { + if (eat(_bracketL)) { + prop.computed = true; + prop.key = parseExpression(); + expect(_bracketR); + return; + } else { + prop.computed = false; + } + } + prop.key = (tokType === _num || tokType === _string) ? parseExprAtom() : parseIdent(true); + } + + // Initialize empty function node. + + function initFunction(node) { + node.id = null; + node.params = []; + if (options.ecmaVersion >= 6) { + node.defaults = []; + node.rest = null; + node.generator = false; + } + } + + // Parse a function declaration or literal (depending on the + // `isStatement` parameter). + + function parseFunction(node, isStatement, allowExpressionBody) { + initFunction(node); + if (options.ecmaVersion >= 6) { + node.generator = eat(_star); + } + if (isStatement || tokType === _name) { + node.id = parseIdent(); + } + parseFunctionParams(node); + parseFunctionBody(node, allowExpressionBody); + return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression"); + } + + // Parse object or class method. + + function parseMethod(isGenerator) { + var node = startNode(); + initFunction(node); + parseFunctionParams(node); + var allowExpressionBody; + if (options.ecmaVersion >= 6) { + node.generator = isGenerator; + allowExpressionBody = true; + } else { + allowExpressionBody = false; + } + parseFunctionBody(node, allowExpressionBody); + return finishNode(node, "FunctionExpression"); + } + + // Parse arrow function expression with given parameters. + + function parseArrowExpression(node, params) { + initFunction(node); + + var defaults = node.defaults, hasDefaults = false; + + for (var i = 0, lastI = params.length - 1; i <= lastI; i++) { + var param = params[i]; + + if (param.type === "AssignmentExpression" && param.operator === "=") { + hasDefaults = true; + params[i] = param.left; + defaults.push(param.right); + } else { + toAssignable(param, i === lastI, true); + defaults.push(null); + if (param.type === "SpreadElement") { + params.length--; + node.rest = param.argument; + break; + } + } + } + + node.params = params; + if (!hasDefaults) node.defaults = []; + + parseFunctionBody(node, true); + return finishNode(node, "ArrowFunctionExpression"); + } + + // Parse function parameters. + + function parseFunctionParams(node) { + var defaults = [], hasDefaults = false; + + expect(_parenL); + for (;;) { + if (eat(_parenR)) { + break; + } else if (options.ecmaVersion >= 6 && eat(_ellipsis)) { + node.rest = toAssignable(parseExprAtom(), false, true); + checkSpreadAssign(node.rest); + expect(_parenR); + defaults.push(null); + break; + } else { + node.params.push(options.ecmaVersion >= 6 ? toAssignable(parseExprAtom(), false, true) : parseIdent()); + if (options.ecmaVersion >= 6) { + if (eat(_eq)) { + hasDefaults = true; + defaults.push(parseExpression(true)); + } else { + defaults.push(null); + } + } + if (!eat(_comma)) { + expect(_parenR); + break; + } + } + } + + if (hasDefaults) node.defaults = defaults; + } + + // Parse function body and check parameters. + + function parseFunctionBody(node, allowExpression) { + var isExpression = allowExpression && tokType !== _braceL; + + if (isExpression) { + node.body = parseExpression(true); + node.expression = true; + } else { + // Start a new scope with regard to labels and the `inFunction` + // flag (restore them to their old value afterwards). + var oldInFunc = inFunction, oldInGen = inGenerator, oldLabels = labels; + inFunction = true; inGenerator = node.generator; labels = []; + node.body = parseBlock(true); + node.expression = false; + inFunction = oldInFunc; inGenerator = oldInGen; labels = oldLabels; + } + + // If this is a strict mode function, verify that argument names + // are not repeated, and it does not try to bind the words `eval` + // or `arguments`. + if (strict || !isExpression && node.body.body.length && isUseStrict(node.body.body[0])) { + var nameHash = {}; + if (node.id) + checkFunctionParam(node.id, {}); + for (var i = 0; i < node.params.length; i++) + checkFunctionParam(node.params[i], nameHash); + if (node.rest) + checkFunctionParam(node.rest, nameHash); + } + } + + // Parse a class declaration or literal (depending on the + // `isStatement` parameter). + + function parseClass(node, isStatement) { + next(); + node.id = tokType === _name ? parseIdent() : isStatement ? unexpected() : null; + node.superClass = eat(_extends) ? parseExpression() : null; + var classBody = startNode(); + classBody.body = []; + expect(_braceL); + while (!eat(_braceR)) { + var method = startNode(); + if (tokType === _name && tokVal === "static") { + next(); + method['static'] = true; + } else { + method['static'] = false; + } + var isGenerator = eat(_star); + parsePropertyName(method); + if (tokType !== _parenL && !method.computed && method.key.type === "Identifier" && + (method.key.name === "get" || method.key.name === "set")) { + if (isGenerator) unexpected(); + method.kind = method.key.name; + parsePropertyName(method); + } else { + method.kind = ""; + } + method.value = parseMethod(isGenerator); + classBody.body.push(finishNode(method, "MethodDefinition")); + eat(_semi); + } + node.body = finishNode(classBody, "ClassBody"); + return finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression"); + } + + // Parses a comma-separated list of expressions, and returns them as + // an array. `close` is the token type that ends the list, and + // `allowEmpty` can be turned on to allow subsequent commas with + // nothing in between them to be parsed as `null` (which is needed + // for array literals). + + function parseExprList(close, allowTrailingComma, allowEmpty) { + var elts = [], first = true; + while (!eat(close)) { + if (!first) { + expect(_comma); + if (allowTrailingComma && options.allowTrailingCommas && eat(close)) break; + } else first = false; + + if (allowEmpty && tokType === _comma) elts.push(null); + else elts.push(parseExpression(true)); + } + return elts; + } + + // Parse the next token as an identifier. If `liberal` is true (used + // when parsing properties), it will also convert keywords into + // identifiers. + + function parseIdent(liberal) { + var node = startNode(); + if (liberal && options.forbidReserved == "everywhere") liberal = false; + if (tokType === _name) { + if (!liberal && + (options.forbidReserved && + (options.ecmaVersion === 3 ? isReservedWord3 : isReservedWord5)(tokVal) || + strict && isStrictReservedWord(tokVal)) && + input.slice(tokStart, tokEnd).indexOf("\\") == -1) + raise(tokStart, "The keyword '" + tokVal + "' is reserved"); + node.name = tokVal; + } else if (liberal && tokType.keyword) { + node.name = tokType.keyword; + } else { + unexpected(); + } + tokRegexpAllowed = false; + next(); + return finishNode(node, "Identifier"); + } + + // Parses module export declaration. + + function parseExport(node) { + next(); + // export var|const|let|function|class ...; + if (tokType === _var || tokType === _const || tokType === _let || tokType === _function || tokType === _class) { + node.declaration = parseStatement(); + node['default'] = false; + node.specifiers = null; + node.source = null; + } else + // export default ...; + if (eat(_default)) { + node.declaration = parseExpression(true); + node['default'] = true; + node.specifiers = null; + node.source = null; + semicolon(); + } else { + // export * from '...'; + // export { x, y as z } [from '...']; + var isBatch = tokType === _star; + node.declaration = null; + node['default'] = false; + node.specifiers = parseExportSpecifiers(); + if (tokType === _name && tokVal === "from") { + next(); + node.source = tokType === _string ? parseExprAtom() : unexpected(); + } else { + if (isBatch) unexpected(); + node.source = null; + } + semicolon(); + } + return finishNode(node, "ExportDeclaration"); + } + + // Parses a comma-separated list of module exports. + + function parseExportSpecifiers() { + var nodes = [], first = true; + if (tokType === _star) { + // export * from '...' + var node = startNode(); + next(); + nodes.push(finishNode(node, "ExportBatchSpecifier")); + } else { + // export { x, y as z } [from '...'] + expect(_braceL); + while (!eat(_braceR)) { + if (!first) { + expect(_comma); + if (options.allowTrailingCommas && eat(_braceR)) break; + } else first = false; + + var node = startNode(); + node.id = parseIdent(tokType === _default); + if (tokType === _name && tokVal === "as") { + next(); + node.name = parseIdent(true); + } else { + node.name = null; + } + nodes.push(finishNode(node, "ExportSpecifier")); + } + } + return nodes; + } + + // Parses import declaration. + + function parseImport(node) { + next(); + // import '...'; + if (tokType === _string) { + node.specifiers = []; + node.source = parseExprAtom(); + node.kind = ""; + } else { + node.specifiers = parseImportSpecifiers(); + if (tokType !== _name || tokVal !== "from") unexpected(); + next(); + node.source = tokType === _string ? parseExprAtom() : unexpected(); + } + semicolon(); + return finishNode(node, "ImportDeclaration"); + } + + // Parses a comma-separated list of module imports. + + function parseImportSpecifiers() { + var nodes = [], first = true; + if (tokType === _name) { + // import defaultObj, { x, y as z } from '...' + var node = startNode(); + node.id = parseIdent(); + checkLVal(node.id, true); + node.name = null; + node['default'] = true; + nodes.push(finishNode(node, "ImportSpecifier")); + if (!eat(_comma)) return nodes; + } + if (tokType === _star) { + var node = startNode(); + next(); + if (tokType !== _name || tokVal !== "as") unexpected(); + next(); + node.name = parseIdent(); + checkLVal(node.name, true); + nodes.push(finishNode(node, "ImportBatchSpecifier")); + return nodes; + } + expect(_braceL); + while (!eat(_braceR)) { + if (!first) { + expect(_comma); + if (options.allowTrailingCommas && eat(_braceR)) break; + } else first = false; + + var node = startNode(); + node.id = parseIdent(true); + if (tokType === _name && tokVal === "as") { + next(); + node.name = parseIdent(); + } else { + node.name = null; + } + checkLVal(node.name || node.id, true); + node['default'] = false; + nodes.push(finishNode(node, "ImportSpecifier")); + } + return nodes; + } + + // Parses yield expression inside generator. + + function parseYield() { + var node = startNode(); + next(); + if (eat(_semi) || canInsertSemicolon()) { + node.delegate = false; + node.argument = null; + } else { + node.delegate = eat(_star); + node.argument = parseExpression(true); + } + return finishNode(node, "YieldExpression"); + } + + // Parses array and generator comprehensions. + + function parseComprehension(node, isGenerator) { + node.blocks = []; + while (tokType === _for) { + var block = startNode(); + next(); + expect(_parenL); + block.left = toAssignable(parseExprAtom()); + checkLVal(block.left, true); + if (tokType !== _name || tokVal !== "of") unexpected(); + next(); + // `of` property is here for compatibility with Esprima's AST + // which also supports deprecated [for (... in ...) expr] + block.of = true; + block.right = parseExpression(); + expect(_parenR); + node.blocks.push(finishNode(block, "ComprehensionBlock")); + } + node.filter = eat(_if) ? parseParenExpression() : null; + node.body = parseExpression(); + expect(isGenerator ? _parenR : _bracketR); + node.generator = isGenerator; + return finishNode(node, "ComprehensionExpression"); + } + + }); + + +/***/ }, + +/***/ 462: +/***/ function(module, exports, __webpack_require__) { + + /* + * 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 = __webpack_require__(463).SourceMapGenerator; + exports.SourceMapConsumer = __webpack_require__(469).SourceMapConsumer; + exports.SourceNode = __webpack_require__(471).SourceNode; + + +/***/ }, + +/***/ 463: +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- 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 (false) { + var define = require('amdefine')(module, require); + } + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + + var base64VLQ = __webpack_require__(464); + var util = __webpack_require__(466); + var ArraySet = __webpack_require__(467).ArraySet; + var MappingList = __webpack_require__(468).MappingList; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. You may pass an object with the following + * properties: + * + * - file: The filename of the generated source. + * - sourceRoot: A root for all relative URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + if (!aArgs) { + aArgs = {}; + } + this._file = util.getArg(aArgs, 'file', null); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._skipValidation = util.getArg(aArgs, 'skipValidation', false); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = new MappingList(); + 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 != null) { + newMapping.source = mapping.source; + if (sourceRoot != null) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name != null) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + 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); + + if (!this._skipValidation) { + this._validateMapping(generated, original, source, name); + } + + if (source != null && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name != null && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.add({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + 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 != null) { + 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 if (this._sourcesContents) { + // 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. + * @param aSourceMapPath Optional. The dirname of the path to the source map + * to be applied. If relative, it is relative to the SourceMapConsumer. + * This parameter is needed when the two source maps aren't in the same + * directory, and the source map to be applied contains relative source + * paths. If so, those relative source paths need to be rewritten + * relative to the SourceMapGenerator. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { + var sourceFile = aSourceFile; + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (aSourceFile == null) { + if (aSourceMapConsumer.file == null) { + throw new Error( + 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + + 'or the source map\'s "file" property. Both were omitted.' + ); + } + sourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "sourceFile" relative if an absolute Url is passed. + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + // 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 "sourceFile" + this._mappings.unsortedForEach(function (mapping) { + if (mapping.source === sourceFile && mapping.originalLine != null) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source != null) { + // Copy mapping + mapping.source = original.source; + if (aSourceMapPath != null) { + mapping.source = util.join(aSourceMapPath, mapping.source) + } + if (sourceRoot != null) { + mapping.source = util.relative(sourceRoot, mapping.source); + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name != null) { + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source != null && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name != null && !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 != null) { + if (aSourceMapPath != null) { + sourceFile = util.join(aSourceMapPath, sourceFile); + } + if (sourceRoot != null) { + 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: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + original: aOriginal, + name: aName + })); + } + }; + + /** + * 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; + + var mappings = this._mappings.toArray(); + + for (var i = 0, len = mappings.length; i < len; i++) { + mapping = mappings[i]; + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!util.compareByGeneratedPositions(mapping, mappings[i - 1])) { + continue; + } + result += ','; + } + } + + result += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; + + if (mapping.source != null) { + 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.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; + + result += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; + + if (mapping.name != null) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot != null) { + source = util.relative(aSourceRoot, source); + } + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, + key) + ? this._sourcesContents[key] + : null; + }, this); + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._file != null) { + map.file = this._file; + } + if (this._sourceRoot != null) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } + + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + + +/***/ }, + +/***/ 464: +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- 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 + * + * 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 + * + * 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: + * + * * 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. + */ + if (false) { + var define = require('amdefine')(module, require); + } + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + + var base64 = __webpack_require__(465); + + // 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 VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit 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; + } + + /** + * Converts to a two-complement value from a value where the sign bit 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; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + 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; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string via the out parameter. + */ + exports.decode = function base64VLQ_decode(aStr, aOutParam) { + var i = 0; + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (i >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + 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); + + aOutParam.value = fromVLQSigned(result); + aOutParam.rest = aStr.slice(i); + }; + + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + + +/***/ }, + +/***/ 465: +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- 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 (false) { + var define = require('amdefine')(module, require); + } + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + + var charToIntMap = {}; + var intToCharMap = {}; + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + .split('') + .forEach(function (ch, index) { + charToIntMap[ch] = index; + intToCharMap[index] = ch; + }); + + /** + * 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); + }; + + /** + * Decode a single base 64 digit to an integer. + */ + exports.decode = function base64_decode(aChar) { + if (aChar in charToIntMap) { + return charToIntMap[aChar]; + } + throw new TypeError("Not a valid base 64 digit: " + aChar); + }; + + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + + +/***/ }, + +/***/ 466: +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- 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 (false) { + var define = require('amdefine')(module, require); + } + !(__WEBPACK_AMD_DEFINE_RESULT__ = 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; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; + var dataUrlRegexp = /^data:.+\,.+$/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[2], + host: match[3], + port: match[4], + path: match[5] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = ''; + if (aParsedUrl.scheme) { + url += aParsedUrl.scheme + ':'; + } + url += '//'; + 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; + + /** + * Normalizes a path, or the path portion of a URL: + * + * - Replaces consequtive slashes with one slash. + * - Removes unnecessary '.' parts. + * - Removes unnecessary '<dir>/..' parts. + * + * Based on code in the Node.js 'path' core module. + * + * @param aPath The path or url to normalize. + */ + function normalize(aPath) { + var path = aPath; + var url = urlParse(aPath); + if (url) { + if (!url.path) { + return aPath; + } + path = url.path; + } + var isAbsolute = (path.charAt(0) === '/'); + + var parts = path.split(/\/+/); + for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { + part = parts[i]; + if (part === '.') { + parts.splice(i, 1); + } else if (part === '..') { + up++; + } else if (up > 0) { + if (part === '') { + // The first part is blank if the path is absolute. Trying to go + // above the root is a no-op. Therefore we can remove all '..' parts + // directly after the root. + parts.splice(i + 1, up); + up = 0; + } else { + parts.splice(i, 2); + up--; + } + } + } + path = parts.join('/'); + + if (path === '') { + path = isAbsolute ? '/' : '.'; + } + + if (url) { + url.path = path; + return urlGenerate(url); + } + return path; + } + exports.normalize = normalize; + + /** + * Joins two paths/URLs. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be joined with the root. + * + * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a + * scheme-relative URL: Then the scheme of aRoot, if any, is prepended + * first. + * - Otherwise aPath is a path. If aRoot is a URL, then its path portion + * is updated with the result and aRoot is returned. Otherwise the result + * is returned. + * - If aPath is absolute, the result is aPath. + * - Otherwise the two paths are joined with a slash. + * - Joining for example 'http://' and 'www.example.com' is also supported. + */ + function join(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + if (aPath === "") { + aPath = "."; + } + var aPathUrl = urlParse(aPath); + var aRootUrl = urlParse(aRoot); + if (aRootUrl) { + aRoot = aRootUrl.path || '/'; + } + + // `join(foo, '//www.example.org')` + if (aPathUrl && !aPathUrl.scheme) { + if (aRootUrl) { + aPathUrl.scheme = aRootUrl.scheme; + } + return urlGenerate(aPathUrl); + } + + if (aPathUrl || aPath.match(dataUrlRegexp)) { + return aPath; + } + + // `join('http://', 'www.example.com')` + if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { + aRootUrl.host = aPath; + return urlGenerate(aRootUrl); + } + + var joined = aPath.charAt(0) === '/' + ? aPath + : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); + + if (aRootUrl) { + aRootUrl.path = joined; + return urlGenerate(aRootUrl); + } + return joined; + } + exports.join = join; + + /** + * Make a path relative to a URL or another path. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be made relative to aRoot. + */ + function relative(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + + aRoot = aRoot.replace(/\/$/, ''); + + // XXX: It is possible to remove this block, and the tests still pass! + 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; + + /** + * 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; + + function fromSetString(aStr) { + return aStr.substr(1); + } + exports.fromSetString = fromSetString; + + function strcmp(aStr1, aStr2) { + var s1 = aStr1 || ""; + var s2 = aStr2 || ""; + return (s1 > s2) - (s1 < s2); + } + + /** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ + function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp; + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp || onlyCompareOriginal) { + return cmp; + } + + cmp = strcmp(mappingA.name, mappingB.name); + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + return mappingA.generatedColumn - mappingB.generatedColumn; + }; + exports.compareByOriginalPositions = compareByOriginalPositions; + + /** + * Comparator between two mappings where the generated positions are + * compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ + function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) { + var cmp; + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp || onlyCompareGenerated) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + }; + exports.compareByGeneratedPositions = compareByGeneratedPositions; + + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + + +/***/ }, + +/***/ 467: +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- 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 (false) { + var define = require('amdefine')(module, require); + } + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + + var util = __webpack_require__(466); + + /** + * 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 = {}; + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); + } + return set; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var isDuplicate = this.has(aStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + this._set[util.toSetString(aStr)] = idx; + } + }; + + /** + * 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)); + }; + + /** + * 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.'); + }; + + /** + * 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]; + } + 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(); + }; + + exports.ArraySet = ArraySet; + + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + + +/***/ }, + +/***/ 468: +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2014 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + if (false) { + var define = require('amdefine')(module, require); + } + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + + var util = __webpack_require__(466); + + /** + * Determine whether mappingB is after mappingA with respect to generated + * position. + */ + function generatedPositionAfter(mappingA, mappingB) { + // Optimized for most common case + var lineA = mappingA.generatedLine; + var lineB = mappingB.generatedLine; + var columnA = mappingA.generatedColumn; + var columnB = mappingB.generatedColumn; + return lineB > lineA || lineB == lineA && columnB >= columnA || + util.compareByGeneratedPositions(mappingA, mappingB) <= 0; + } + + /** + * A data structure to provide a sorted view of accumulated mappings in a + * performance conscious manner. It trades a neglibable overhead in general + * case for a large speedup in case of mappings being added in order. + */ + function MappingList() { + this._array = []; + this._sorted = true; + // Serves as infimum + this._last = {generatedLine: -1, generatedColumn: 0}; + } + + /** + * Iterate through internal items. This method takes the same arguments that + * `Array.prototype.forEach` takes. + * + * NOTE: The order of the mappings is NOT guaranteed. + */ + MappingList.prototype.unsortedForEach = + function MappingList_forEach(aCallback, aThisArg) { + this._array.forEach(aCallback, aThisArg); + }; + + /** + * Add the given source mapping. + * + * @param Object aMapping + */ + MappingList.prototype.add = function MappingList_add(aMapping) { + var mapping; + if (generatedPositionAfter(this._last, aMapping)) { + this._last = aMapping; + this._array.push(aMapping); + } else { + this._sorted = false; + this._array.push(aMapping); + } + }; + + /** + * Returns the flat, sorted array of mappings. The mappings are sorted by + * generated position. + * + * WARNING: This method returns internal data without copying, for + * performance. The return value must NOT be mutated, and should be treated as + * an immutable borrow. If you want to take ownership, you must make your own + * copy. + */ + MappingList.prototype.toArray = function MappingList_toArray() { + if (!this._sorted) { + this._array.sort(util.compareByGeneratedPositions); + this._sorted = true; + } + return this._array; + }; + + exports.MappingList = MappingList; + + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + + +/***/ }, + +/***/ 469: +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- 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 (false) { + var define = require('amdefine')(module, require); + } + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + + var util = __webpack_require__(466); + var binarySearch = __webpack_require__(470); + var ArraySet = __webpack_require__(467).ArraySet; + var base64VLQ = __webpack_require__(464); + + /** + * A SourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: Optional. The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util.getArg(sourceMap, 'names', []); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + // Some source maps produce relative source paths like "./foo.js" instead of + // "foo.js". Normalize these first so that future comparisons will succeed. + // See bugzil.la/1090768. + sources = sources.map(util.normalize); + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names, true); + this._sources = ArraySet.fromArray(sources, true); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this.file = file; + } + + /** + * Create a SourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns SourceMapConsumer + */ + SourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(SourceMapConsumer.prototype); + + smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + smc.__generatedMappings = aSourceMap._mappings.toArray().slice(); + smc.__originalMappings = aSourceMap._mappings.toArray().slice() + .sort(util.compareByOriginalPositions); + + return smc; + }; + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(SourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + // `__generatedMappings` and `__originalMappings` are arrays that hold the + // parsed mapping coordinates from the source map's "mappings" attribute. They + // are lazily instantiated, accessed via the `_generatedMappings` and + // `_originalMappings` getters respectively, and we only parse the mappings + // and create these arrays once queried for a source location. We jump through + // these hoops because there can be many thousands of mappings, and parsing + // them is expensive, so we only want to do it if we must. + // + // Each object in the arrays is of the form: + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `_generatedMappings` is ordered by the generated positions. + // + // `_originalMappings` is ordered by the original positions. + + SourceMapConsumer.prototype.__generatedMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } + }); + + SourceMapConsumer.prototype.__originalMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } + }); + + SourceMapConsumer.prototype._nextCharIsMappingSeparator = + function SourceMapConsumer_nextCharIsMappingSeparator(aStr) { + var c = aStr.charAt(0); + return c === ";" || c === ","; + }; + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var str = aStr; + var temp = {}; + var mapping; + + while (str.length > 0) { + if (str.charAt(0) === ';') { + generatedLine++; + str = str.slice(1); + previousGeneratedColumn = 0; + } + else if (str.charAt(0) === ',') { + str = str.slice(1); + } + else { + mapping = {}; + mapping.generatedLine = generatedLine; + + // Generated column. + base64VLQ.decode(str, temp); + mapping.generatedColumn = previousGeneratedColumn + temp.value; + previousGeneratedColumn = mapping.generatedColumn; + str = temp.rest; + + if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) { + // Original source. + base64VLQ.decode(str, temp); + mapping.source = this._sources.at(previousSource + temp.value); + previousSource += temp.value; + str = temp.rest; + if (str.length === 0 || this._nextCharIsMappingSeparator(str)) { + throw new Error('Found a source, but no line and column'); + } + + // Original line. + base64VLQ.decode(str, temp); + mapping.originalLine = previousOriginalLine + temp.value; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + str = temp.rest; + if (str.length === 0 || this._nextCharIsMappingSeparator(str)) { + throw new Error('Found a source and line, but no column'); + } + + // Original column. + base64VLQ.decode(str, temp); + mapping.originalColumn = previousOriginalColumn + temp.value; + previousOriginalColumn = mapping.originalColumn; + str = temp.rest; + + if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) { + // Original name. + base64VLQ.decode(str, temp); + mapping.name = this._names.at(previousName + temp.value); + previousName += temp.value; + str = temp.rest; + } + } + + this.__generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + this.__originalMappings.push(mapping); + } + } + } + + this.__generatedMappings.sort(util.compareByGeneratedPositions); + this.__originalMappings.sort(util.compareByOriginalPositions); + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + SourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator); + }; + + /** + * Compute the last column for each generated mapping. The last column is + * inclusive. + */ + SourceMapConsumer.prototype.computeColumnSpans = + function SourceMapConsumer_computeColumnSpans() { + for (var index = 0; index < this._generatedMappings.length; ++index) { + var mapping = this._generatedMappings[index]; + + // Mappings do not contain a field for the last generated columnt. We + // can come up with an optimistic estimate, however, by assuming that + // mappings are contiguous (i.e. given two consecutive mappings, the + // first mapping ends where the second one starts). + if (index + 1 < this._generatedMappings.length) { + var nextMapping = this._generatedMappings[index + 1]; + + if (mapping.generatedLine === nextMapping.generatedLine) { + mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; + continue; + } + } + + // The last mapping for each line spans the entire line. + mapping.lastGeneratedColumn = Infinity; + } + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + SourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var index = this._findMapping(needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositions); + + if (index >= 0) { + var mapping = this._generatedMappings[index]; + + if (mapping.generatedLine === needle.generatedLine) { + var source = util.getArg(mapping, 'source', null); + if (source != null && this.sourceRoot != null) { + source = util.join(this.sourceRoot, source); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: util.getArg(mapping, 'name', null) + }; + } + } + + return { + source: null, + line: null, + column: null, + 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. + */ + SourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot != null) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot != null + && (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.'); + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + if (this.sourceRoot != null) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions); + + if (index >= 0) { + var mapping = this._originalMappings[index]; + + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }; + } + + return { + line: null, + column: null, + lastColumn: null + }; + }; + + /** + * Returns all generated line and column information for the original source + * and line provided. The only argument is an object with the following + * properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * + * and an array of objects is returned, each with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.allGeneratedPositionsFor = + function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { + // When there is no exact match, SourceMapConsumer.prototype._findMapping + // returns the index of the closest mapping less than the needle. By + // setting needle.originalColumn to Infinity, we thus find the last + // mapping for the given line, provided such a mapping exists. + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: Infinity + }; + + if (this.sourceRoot != null) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var mappings = []; + + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions); + if (index >= 0) { + var mapping = this._originalMappings[index]; + + while (mapping && mapping.originalLine === needle.originalLine) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[--index]; + } + } + + return mappings.reverse(); + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source; + if (source != null && sourceRoot != null) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name + }; + }).forEach(aCallback, context); + }; + + exports.SourceMapConsumer = SourceMapConsumer; + + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + + +/***/ }, + +/***/ 470: +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- 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 (false) { + var define = require('amdefine')(module, require); + } + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + + /** + * 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 index of + // 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 -1. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return 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); + } + // We did not find an exact match, return the next closest one + // (termination case 2). + return 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); + } + // 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 ? -1 : aLow; + } + } + + /** + * This is an implementation of binary search which will always try and return + * the index of 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) { + if (aHaystack.length === 0) { + return -1; + } + return recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) + }; + + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + + +/***/ }, + +/***/ 471: +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* -*- 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 (false) { + var define = require('amdefine')(module, require); + } + !(__WEBPACK_AMD_DEFINE_RESULT__ = function (require, exports, module) { + + var SourceMapGenerator = __webpack_require__(463).SourceMapGenerator; + var util = __webpack_require__(466); + + // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other + // operating systems these days (capturing the result). + var REGEX_NEWLINE = /(\r?\n)/; + + // Newline character code for charCodeAt() comparisons + var NEWLINE_CODE = 10; + + // Private symbol for identifying `SourceNode`s when multiple versions of + // the source-map library are loaded. This MUST NOT CHANGE across + // versions! + var isSourceNode = "$$$isSourceNode$$$"; + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine == null ? null : aLine; + this.column = aColumn == null ? null : aColumn; + this.source = aSource == null ? null : aSource; + this.name = aName == null ? null : aName; + this[isSourceNode] = true; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + * @param aRelativePath Optional. The path that relative sources in the + * SourceMapConsumer should be relative to. + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // All even indices of this array are one line of the generated code, + // while all odd indices are the newlines between two adjacent lines + // (since `REGEX_NEWLINE` captures its match). + // Processed fragments are removed from this array, by calling `shiftNextLine`. + var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); + var shiftNextLine = function() { + var lineContents = remainingLines.shift(); + // The last line of a file might not have a newline. + var newLine = remainingLines.shift() || ""; + return lineContents + newLine; + }; + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping !== null) { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + var code = ""; + // Associate first line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + lastGeneratedLine++; + lastGeneratedColumn = 0; + // The remaining code is added without mapping + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[0]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + // No more remaining code, continue + lastMapping = mapping; + return; + } + } + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(shiftNextLine()); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + if (remainingLines.length > 0) { + if (lastMapping) { + // Associate the remaining code in the current line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + } + // and add the remaining lines without any mapping + node.add(remainingLines.join("")); + } + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aRelativePath != null) { + sourceFile = util.join(aRelativePath, sourceFile); + } + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + var source = aRelativePath + ? util.join(aRelativePath, mapping.source) + : mapping.source; + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk[isSourceNode]) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + } + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild[isSourceNode]) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i][isSourceNode]) { + this.children[i].walkSourceContents(aFn); + } + } + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + for (var idx = 0, length = chunk.length; idx < length; idx++) { + if (chunk.charCodeAt(idx) === NEWLINE_CODE) { + generated.line++; + generated.column = 0; + // Mappings end at eol + if (idx + 1 === length) { + lastOriginalSource = null; + sourceMappingActive = false; + } else if (sourceMappingActive) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + } else { + generated.column++; + } + } + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + + +/***/ } + +/******/ }); +//# sourceMappingURL=pretty-print-worker.js.map
\ No newline at end of file diff --git a/devtools/client/debugger/new/source-map-worker.js b/devtools/client/debugger/new/source-map-worker.js new file mode 100644 index 000000000..6b1a55521 --- /dev/null +++ b/devtools/client/debugger/new/source-map-worker.js @@ -0,0 +1,5831 @@ +var Debugger = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; +/******/ +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = "/public/build"; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ function(module, exports, __webpack_require__) { + + var _resolveAndFetch = (() => { + var _ref = _asyncToGenerator(function* (generatedSource) { + // Fetch the sourcemap over the network and create it. + var sourceMapURL = _resolveSourceMapURL(generatedSource); + var fetched = yield networkRequest(sourceMapURL, { loadFromCache: false }); + + // Create the source map and fix it up. + var map = new SourceMapConsumer(fetched.content); + _setSourceMapRoot(map, sourceMapURL, generatedSource); + return map; + }); + + return function _resolveAndFetch(_x) { + return _ref.apply(this, arguments); + }; + })(); + + var getOriginalURLs = (() => { + var _ref2 = _asyncToGenerator(function* (generatedSource) { + var map = yield _fetchSourceMap(generatedSource); + return map && map.sources; + }); + + return function getOriginalURLs(_x2) { + return _ref2.apply(this, arguments); + }; + })(); + + var getGeneratedLocation = (() => { + var _ref3 = _asyncToGenerator(function* (location, originalSource) { + if (!isOriginalId(location.sourceId)) { + return location; + } + + var generatedSourceId = originalToGeneratedId(location.sourceId); + var map = yield _getSourceMap(generatedSourceId); + if (!map) { + return location; + } + + var _map$generatedPositio = map.generatedPositionFor({ + source: originalSource.url, + line: location.line, + column: location.column == null ? 0 : location.column, + bias: SourceMapConsumer.LEAST_UPPER_BOUND + }); + + var line = _map$generatedPositio.line; + var column = _map$generatedPositio.column; + + + return { + sourceId: generatedSourceId, + line: line, + // Treat 0 as no column so that line breakpoints work correctly. + column: column === 0 ? undefined : column + }; + }); + + return function getGeneratedLocation(_x3, _x4) { + return _ref3.apply(this, arguments); + }; + })(); + + var getOriginalLocation = (() => { + var _ref4 = _asyncToGenerator(function* (location) { + if (!isGeneratedId(location.sourceId)) { + return location; + } + + var map = yield _getSourceMap(location.sourceId); + if (!map) { + return location; + } + + var _map$originalPosition = map.originalPositionFor({ + line: location.line, + column: location.column == null ? Infinity : location.column + }); + + var url = _map$originalPosition.source; + var line = _map$originalPosition.line; + var column = _map$originalPosition.column; + + + if (url == null) { + // No url means the location didn't map. + return location; + } + + return { + sourceId: generatedToOriginalId(location.sourceId, url), + line, + column + }; + }); + + return function getOriginalLocation(_x5) { + return _ref4.apply(this, arguments); + }; + })(); + + var getOriginalSourceText = (() => { + var _ref5 = _asyncToGenerator(function* (originalSource) { + assert(isOriginalId(originalSource.id), "Source is not an original source"); + + var generatedSourceId = originalToGeneratedId(originalSource.id); + var map = yield _getSourceMap(generatedSourceId); + if (!map) { + return null; + } + + var text = map.sourceContentFor(originalSource.url); + if (!text) { + text = (yield networkRequest(originalSource.url, { loadFromCache: false })).content; + } + + return { + text, + contentType: isJavaScript(originalSource.url || "") ? "text/javascript" : "text/plain" + }; + }); + + return function getOriginalSourceText(_x6) { + return _ref5.apply(this, arguments); + }; + })(); + + function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + + /** + * Source Map Worker + * @module utils/source-map-worker + */ + + var networkRequest = __webpack_require__(207); + + var _require = __webpack_require__(293); + + var parse = _require.parse; + + var path = __webpack_require__(278); + + var _require2 = __webpack_require__(472); + + var SourceMapConsumer = _require2.SourceMapConsumer; + var SourceMapGenerator = _require2.SourceMapGenerator; + + var _require3 = __webpack_require__(277); + + var isJavaScript = _require3.isJavaScript; + + var assert = __webpack_require__(247); + + var _require4 = __webpack_require__(265); + + var originalToGeneratedId = _require4.originalToGeneratedId; + var generatedToOriginalId = _require4.generatedToOriginalId; + var isGeneratedId = _require4.isGeneratedId; + var isOriginalId = _require4.isOriginalId; + + + var sourceMapRequests = new Map(); + var sourceMapsEnabled = false; + + function clearSourceMaps() { + sourceMapRequests.clear(); + } + + function enableSourceMaps() { + sourceMapsEnabled = true; + } + + function _resolveSourceMapURL(source) { + var _source$url = source.url; + var url = _source$url === undefined ? "" : _source$url; + var _source$sourceMapURL = source.sourceMapURL; + var sourceMapURL = _source$sourceMapURL === undefined ? "" : _source$sourceMapURL; + + if (path.isURL(sourceMapURL) || url == "") { + // If it's already a full URL or the source doesn't have a URL, + // don't resolve anything. + return sourceMapURL; + } else if (path.isAbsolute(sourceMapURL)) { + // If it's an absolute path, it should be resolved relative to the + // host of the source. + var _parse = parse(url); + + var _parse$protocol = _parse.protocol; + var protocol = _parse$protocol === undefined ? "" : _parse$protocol; + var _parse$host = _parse.host; + var host = _parse$host === undefined ? "" : _parse$host; + + return `${ protocol }//${ host }${ sourceMapURL }`; + } + // Otherwise, it's a relative path and should be resolved relative + // to the source. + return path.dirname(url) + "/" + sourceMapURL; + } + + /** + * Sets the source map's sourceRoot to be relative to the source map url. + * @memberof utils/source-map-worker + * @static + */ + function _setSourceMapRoot(sourceMap, absSourceMapURL, source) { + // No need to do this fiddling if we won't be fetching any sources over the + // wire. + if (sourceMap.hasContentsOfAllSources()) { + return; + } + + var base = path.dirname(absSourceMapURL.indexOf("data:") === 0 && source.url ? source.url : absSourceMapURL); + + if (sourceMap.sourceRoot) { + sourceMap.sourceRoot = path.join(base, sourceMap.sourceRoot); + } else { + sourceMap.sourceRoot = base; + } + + return sourceMap; + } + + function _getSourceMap(generatedSourceId) { + return sourceMapRequests.get(generatedSourceId); + } + + function _fetchSourceMap(generatedSource) { + var existingRequest = sourceMapRequests.get(generatedSource.id); + if (existingRequest) { + // If it has already been requested, return the request. Make sure + // to do this even if sourcemapping is turned off, because + // pretty-printing uses sourcemaps. + // + // An important behavior here is that if it's in the middle of + // requesting it, all subsequent calls will block on the initial + // request. + return existingRequest; + } else if (!generatedSource.sourceMapURL || !sourceMapsEnabled) { + return Promise.resolve(null); + } + + // Fire off the request, set it in the cache, and return it. + // Suppress any errors and just return null (ignores bogus + // sourcemaps). + var req = _resolveAndFetch(generatedSource).catch(() => null); + sourceMapRequests.set(generatedSource.id, req); + return req; + } + + function applySourceMap(generatedId, url, code, mappings) { + var generator = new SourceMapGenerator({ file: url }); + mappings.forEach(mapping => generator.addMapping(mapping)); + generator.setSourceContent(url, code); + + var map = SourceMapConsumer(generator.toJSON()); + sourceMapRequests.set(generatedId, Promise.resolve(map)); + } + + var publicInterface = { + getOriginalURLs, + getGeneratedLocation, + getOriginalLocation, + getOriginalSourceText, + enableSourceMaps, + applySourceMap, + clearSourceMaps + }; + + self.onmessage = function (msg) { + var _msg$data = msg.data; + var id = _msg$data.id; + var method = _msg$data.method; + var args = _msg$data.args; + + var response = publicInterface[method].apply(undefined, args); + if (response instanceof Promise) { + response.then(val => self.postMessage({ id, response: val }), err => self.postMessage({ id, error: err })); + } else { + self.postMessage({ id, response }); + } + }; + +/***/ }, + +/***/ 77: +/***/ function(module, exports) { + + module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + module.children = []; + module.webpackPolyfill = 1; + } + return module; + } + + +/***/ }, + +/***/ 207: +/***/ function(module, exports) { + + function networkRequest(url, opts) { + return new Promise((resolve, reject) => { + var req = new XMLHttpRequest(); + + req.addEventListener("readystatechange", () => { + if (req.readyState === XMLHttpRequest.DONE) { + if (req.status === 200) { + resolve({ content: req.responseText }); + } else { + resolve(req.statusText); + } + } + }); + + // Not working yet. + // if (!opts.loadFromCache) { + // req.channel.loadFlags = ( + // Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE | + // Components.interfaces.nsIRequest.INHIBIT_CACHING | + // Components.interfaces.nsIRequest.LOAD_ANONYMOUS + // ); + // } + + req.open("GET", url); + req.send(); + }); + } + + module.exports = networkRequest; + +/***/ }, + +/***/ 244: +/***/ function(module, exports, __webpack_require__) { + + var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + + function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + + /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + /** + * Utils for utils, by utils + * @module utils/utils + */ + + var co = __webpack_require__(245); + + /** + * @memberof utils/utils + * @static + */ + function asPaused(client, func) { + if (client.state != "paused") { + return co(function* () { + yield client.interrupt(); + var result = void 0; + + try { + result = yield func(); + } catch (e) { + // Try to put the debugger back in a working state by resuming + // it + yield client.resume(); + throw e; + } + + yield client.resume(); + return result; + }); + } + return func(); + } + + /** + * @memberof utils/utils + * @static + */ + function handleError(err) { + console.log("ERROR: ", err); + } + + /** + * @memberof utils/utils + * @static + */ + function promisify(context, method) { + for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { + args[_key - 2] = arguments[_key]; + } + + return new Promise((resolve, reject) => { + args.push(response => { + if (response.error) { + reject(response); + } else { + resolve(response); + } + }); + method.apply(context, args); + }); + } + + /** + * @memberof utils/utils + * @static + */ + function truncateStr(str, size) { + if (str.length > size) { + return str.slice(0, size) + "..."; + } + return str; + } + + /** + * @memberof utils/utils + * @static + */ + function endTruncateStr(str, size) { + if (str.length > size) { + return "..." + str.slice(str.length - size); + } + return str; + } + + var msgId = 1; + /** + * @memberof utils/utils + * @static + */ + function workerTask(worker, method) { + return function () { + for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + return new Promise((resolve, reject) => { + var id = msgId++; + worker.postMessage({ id, method, args }); + + var listener = (_ref) => { + var result = _ref.data; + + if (result.id !== id) { + return; + } + + worker.removeEventListener("message", listener); + if (result.error) { + reject(result.error); + } else { + resolve(result.response); + } + }; + + worker.addEventListener("message", listener); + }); + }; + } + + /** + * Interleaves two arrays element by element, returning the combined array, like + * a zip. In the case of arrays with different sizes, undefined values will be + * interleaved at the end along with the extra values of the larger array. + * + * @param Array a + * @param Array b + * @returns Array + * The combined array, in the form [a1, b1, a2, b2, ...] + * @memberof utils/utils + * @static + */ + function zip(a, b) { + if (!b) { + return a; + } + if (!a) { + return b; + } + var pairs = []; + for (var i = 0, aLength = a.length, bLength = b.length; i < aLength || i < bLength; i++) { + pairs.push([a[i], b[i]]); + } + return pairs; + } + + /** + * Converts an object into an array with 2-element arrays as key/value + * pairs of the object. `{ foo: 1, bar: 2}` would become + * `[[foo, 1], [bar 2]]` (order not guaranteed); + * + * @returns array + * @memberof utils/utils + * @static + */ + function entries(obj) { + return Object.keys(obj).map(k => [k, obj[k]]); + } + + /** + * @memberof utils/utils + * @static + */ + function mapObject(obj, iteratee) { + return toObject(entries(obj).map((_ref2) => { + var _ref3 = _slicedToArray(_ref2, 2); + + var key = _ref3[0]; + var value = _ref3[1]; + + return [key, iteratee(key, value)]; + })); + } + + /** + * Takes an array of 2-element arrays as key/values pairs and + * constructs an object using them. + * @memberof utils/utils + * @static + */ + function toObject(arr) { + var obj = {}; + for (var pair of arr) { + obj[pair[0]] = pair[1]; + } + return obj; + } + + /** + * Composes the given functions into a single function, which will + * apply the results of each function right-to-left, starting with + * applying the given arguments to the right-most function. + * `compose(foo, bar, baz)` === `args => foo(bar(baz(args)` + * + * @param ...function funcs + * @returns function + * @memberof utils/utils + * @static + */ + function compose() { + for (var _len3 = arguments.length, funcs = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + funcs[_key3] = arguments[_key3]; + } + + return function () { + for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { + args[_key4] = arguments[_key4]; + } + + var initialValue = funcs[funcs.length - 1].apply(null, args); + var leftFuncs = funcs.slice(0, -1); + return leftFuncs.reduceRight((composed, f) => f(composed), initialValue); + }; + } + + /** + * @memberof utils/utils + * @static + */ + function updateObj(obj, fields) { + return Object.assign({}, obj, fields); + } + + /** + * @memberof utils/utils + * @static + */ + function throttle(func, ms) { + var timeout = void 0, + _this = void 0; + return function () { + for (var _len5 = arguments.length, args = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { + args[_key5] = arguments[_key5]; + } + + _this = this; + if (!timeout) { + timeout = setTimeout(() => { + func.apply.apply(func, [_this].concat(_toConsumableArray(args))); + timeout = null; + }, ms); + } + }; + } + + module.exports = { + asPaused, + handleError, + promisify, + truncateStr, + endTruncateStr, + workerTask, + zip, + entries, + toObject, + mapObject, + compose, + updateObj, + throttle + }; + +/***/ }, + +/***/ 245: +/***/ function(module, exports) { + + + /** + * slice() reference. + */ + + var slice = Array.prototype.slice; + + /** + * Expose `co`. + */ + + module.exports = co['default'] = co.co = co; + + /** + * Wrap the given generator `fn` into a + * function that returns a promise. + * This is a separate function so that + * every `co()` call doesn't create a new, + * unnecessary closure. + * + * @param {GeneratorFunction} fn + * @return {Function} + * @api public + */ + + co.wrap = function (fn) { + createPromise.__generatorFunction__ = fn; + return createPromise; + function createPromise() { + return co.call(this, fn.apply(this, arguments)); + } + }; + + /** + * Execute the generator function or a generator + * and return a promise. + * + * @param {Function} fn + * @return {Promise} + * @api public + */ + + function co(gen) { + var ctx = this; + var args = slice.call(arguments, 1) + + // we wrap everything in a promise to avoid promise chaining, + // which leads to memory leak errors. + // see https://github.com/tj/co/issues/180 + return new Promise(function(resolve, reject) { + if (typeof gen === 'function') gen = gen.apply(ctx, args); + if (!gen || typeof gen.next !== 'function') return resolve(gen); + + onFulfilled(); + + /** + * @param {Mixed} res + * @return {Promise} + * @api private + */ + + function onFulfilled(res) { + var ret; + try { + ret = gen.next(res); + } catch (e) { + return reject(e); + } + next(ret); + } + + /** + * @param {Error} err + * @return {Promise} + * @api private + */ + + function onRejected(err) { + var ret; + try { + ret = gen.throw(err); + } catch (e) { + return reject(e); + } + next(ret); + } + + /** + * Get the next value in the generator, + * return a promise. + * + * @param {Object} ret + * @return {Promise} + * @api private + */ + + function next(ret) { + if (ret.done) return resolve(ret.value); + var value = toPromise.call(ctx, ret.value); + if (value && isPromise(value)) return value.then(onFulfilled, onRejected); + return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, ' + + 'but the following object was passed: "' + String(ret.value) + '"')); + } + }); + } + + /** + * Convert a `yield`ed value into a promise. + * + * @param {Mixed} obj + * @return {Promise} + * @api private + */ + + function toPromise(obj) { + if (!obj) return obj; + if (isPromise(obj)) return obj; + if (isGeneratorFunction(obj) || isGenerator(obj)) return co.call(this, obj); + if ('function' == typeof obj) return thunkToPromise.call(this, obj); + if (Array.isArray(obj)) return arrayToPromise.call(this, obj); + if (isObject(obj)) return objectToPromise.call(this, obj); + return obj; + } + + /** + * Convert a thunk to a promise. + * + * @param {Function} + * @return {Promise} + * @api private + */ + + function thunkToPromise(fn) { + var ctx = this; + return new Promise(function (resolve, reject) { + fn.call(ctx, function (err, res) { + if (err) return reject(err); + if (arguments.length > 2) res = slice.call(arguments, 1); + resolve(res); + }); + }); + } + + /** + * Convert an array of "yieldables" to a promise. + * Uses `Promise.all()` internally. + * + * @param {Array} obj + * @return {Promise} + * @api private + */ + + function arrayToPromise(obj) { + return Promise.all(obj.map(toPromise, this)); + } + + /** + * Convert an object of "yieldables" to a promise. + * Uses `Promise.all()` internally. + * + * @param {Object} obj + * @return {Promise} + * @api private + */ + + function objectToPromise(obj){ + var results = new obj.constructor(); + var keys = Object.keys(obj); + var promises = []; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var promise = toPromise.call(this, obj[key]); + if (promise && isPromise(promise)) defer(promise, key); + else results[key] = obj[key]; + } + return Promise.all(promises).then(function () { + return results; + }); + + function defer(promise, key) { + // predefine the key in the result + results[key] = undefined; + promises.push(promise.then(function (res) { + results[key] = res; + })); + } + } + + /** + * Check if `obj` is a promise. + * + * @param {Object} obj + * @return {Boolean} + * @api private + */ + + function isPromise(obj) { + return 'function' == typeof obj.then; + } + + /** + * Check if `obj` is a generator. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private + */ + + function isGenerator(obj) { + return 'function' == typeof obj.next && 'function' == typeof obj.throw; + } + + /** + * Check if `obj` is a generator function. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private + */ + function isGeneratorFunction(obj) { + var constructor = obj.constructor; + if (!constructor) return false; + if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true; + return isGenerator(constructor.prototype); + } + + /** + * Check for plain object. + * + * @param {Mixed} val + * @return {Boolean} + * @api private + */ + + function isObject(val) { + return Object == val.constructor; + } + + +/***/ }, + +/***/ 247: +/***/ function(module, exports) { + + function assert(condition, message) { + if (!condition) { + throw new Error("Assertion failure: " + message); + } + } + + module.exports = assert; + +/***/ }, + +/***/ 265: +/***/ function(module, exports, __webpack_require__) { + + var md5 = __webpack_require__(266); + + function originalToGeneratedId(originalId) { + var match = originalId.match(/(.*)\/originalSource/); + return match ? match[1] : ""; + } + + function generatedToOriginalId(generatedId, url) { + return generatedId + "/originalSource-" + md5(url); + } + + function isOriginalId(id) { + return !!id.match(/\/originalSource/); + } + + function isGeneratedId(id) { + return !isOriginalId(id); + } + + module.exports = { + originalToGeneratedId, generatedToOriginalId, isOriginalId, isGeneratedId + }; + +/***/ }, + +/***/ 266: +/***/ function(module, exports, __webpack_require__) { + + (function(){
+ var crypt = __webpack_require__(267),
+ utf8 = __webpack_require__(268).utf8,
+ isBuffer = __webpack_require__(269),
+ bin = __webpack_require__(268).bin,
+
+ // The core
+ md5 = function (message, options) {
+ // Convert to byte array
+ if (message.constructor == String)
+ if (options && options.encoding === 'binary')
+ message = bin.stringToBytes(message);
+ else
+ message = utf8.stringToBytes(message);
+ else if (isBuffer(message))
+ message = Array.prototype.slice.call(message, 0);
+ else if (!Array.isArray(message))
+ message = message.toString();
+ // else, assume byte array already
+
+ var m = crypt.bytesToWords(message),
+ l = message.length * 8,
+ a = 1732584193,
+ b = -271733879,
+ c = -1732584194,
+ d = 271733878;
+
+ // Swap endian
+ for (var i = 0; i < m.length; i++) {
+ m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF |
+ ((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00;
+ }
+
+ // Padding
+ m[l >>> 5] |= 0x80 << (l % 32);
+ m[(((l + 64) >>> 9) << 4) + 14] = l;
+
+ // Method shortcuts
+ var FF = md5._ff,
+ GG = md5._gg,
+ HH = md5._hh,
+ II = md5._ii;
+
+ for (var i = 0; i < m.length; i += 16) {
+
+ var aa = a,
+ bb = b,
+ cc = c,
+ dd = d;
+
+ a = FF(a, b, c, d, m[i+ 0], 7, -680876936);
+ d = FF(d, a, b, c, m[i+ 1], 12, -389564586);
+ c = FF(c, d, a, b, m[i+ 2], 17, 606105819);
+ b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);
+ a = FF(a, b, c, d, m[i+ 4], 7, -176418897);
+ d = FF(d, a, b, c, m[i+ 5], 12, 1200080426);
+ c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);
+ b = FF(b, c, d, a, m[i+ 7], 22, -45705983);
+ a = FF(a, b, c, d, m[i+ 8], 7, 1770035416);
+ d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);
+ c = FF(c, d, a, b, m[i+10], 17, -42063);
+ b = FF(b, c, d, a, m[i+11], 22, -1990404162);
+ a = FF(a, b, c, d, m[i+12], 7, 1804603682);
+ d = FF(d, a, b, c, m[i+13], 12, -40341101);
+ c = FF(c, d, a, b, m[i+14], 17, -1502002290);
+ b = FF(b, c, d, a, m[i+15], 22, 1236535329);
+
+ a = GG(a, b, c, d, m[i+ 1], 5, -165796510);
+ d = GG(d, a, b, c, m[i+ 6], 9, -1069501632);
+ c = GG(c, d, a, b, m[i+11], 14, 643717713);
+ b = GG(b, c, d, a, m[i+ 0], 20, -373897302);
+ a = GG(a, b, c, d, m[i+ 5], 5, -701558691);
+ d = GG(d, a, b, c, m[i+10], 9, 38016083);
+ c = GG(c, d, a, b, m[i+15], 14, -660478335);
+ b = GG(b, c, d, a, m[i+ 4], 20, -405537848);
+ a = GG(a, b, c, d, m[i+ 9], 5, 568446438);
+ d = GG(d, a, b, c, m[i+14], 9, -1019803690);
+ c = GG(c, d, a, b, m[i+ 3], 14, -187363961);
+ b = GG(b, c, d, a, m[i+ 8], 20, 1163531501);
+ a = GG(a, b, c, d, m[i+13], 5, -1444681467);
+ d = GG(d, a, b, c, m[i+ 2], 9, -51403784);
+ c = GG(c, d, a, b, m[i+ 7], 14, 1735328473);
+ b = GG(b, c, d, a, m[i+12], 20, -1926607734);
+
+ a = HH(a, b, c, d, m[i+ 5], 4, -378558);
+ d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);
+ c = HH(c, d, a, b, m[i+11], 16, 1839030562);
+ b = HH(b, c, d, a, m[i+14], 23, -35309556);
+ a = HH(a, b, c, d, m[i+ 1], 4, -1530992060);
+ d = HH(d, a, b, c, m[i+ 4], 11, 1272893353);
+ c = HH(c, d, a, b, m[i+ 7], 16, -155497632);
+ b = HH(b, c, d, a, m[i+10], 23, -1094730640);
+ a = HH(a, b, c, d, m[i+13], 4, 681279174);
+ d = HH(d, a, b, c, m[i+ 0], 11, -358537222);
+ c = HH(c, d, a, b, m[i+ 3], 16, -722521979);
+ b = HH(b, c, d, a, m[i+ 6], 23, 76029189);
+ a = HH(a, b, c, d, m[i+ 9], 4, -640364487);
+ d = HH(d, a, b, c, m[i+12], 11, -421815835);
+ c = HH(c, d, a, b, m[i+15], 16, 530742520);
+ b = HH(b, c, d, a, m[i+ 2], 23, -995338651);
+
+ a = II(a, b, c, d, m[i+ 0], 6, -198630844);
+ d = II(d, a, b, c, m[i+ 7], 10, 1126891415);
+ c = II(c, d, a, b, m[i+14], 15, -1416354905);
+ b = II(b, c, d, a, m[i+ 5], 21, -57434055);
+ a = II(a, b, c, d, m[i+12], 6, 1700485571);
+ d = II(d, a, b, c, m[i+ 3], 10, -1894986606);
+ c = II(c, d, a, b, m[i+10], 15, -1051523);
+ b = II(b, c, d, a, m[i+ 1], 21, -2054922799);
+ a = II(a, b, c, d, m[i+ 8], 6, 1873313359);
+ d = II(d, a, b, c, m[i+15], 10, -30611744);
+ c = II(c, d, a, b, m[i+ 6], 15, -1560198380);
+ b = II(b, c, d, a, m[i+13], 21, 1309151649);
+ a = II(a, b, c, d, m[i+ 4], 6, -145523070);
+ d = II(d, a, b, c, m[i+11], 10, -1120210379);
+ c = II(c, d, a, b, m[i+ 2], 15, 718787259);
+ b = II(b, c, d, a, m[i+ 9], 21, -343485551);
+
+ a = (a + aa) >>> 0;
+ b = (b + bb) >>> 0;
+ c = (c + cc) >>> 0;
+ d = (d + dd) >>> 0;
+ }
+
+ return crypt.endian([a, b, c, d]);
+ };
+
+ // Auxiliary functions
+ md5._ff = function (a, b, c, d, x, s, t) {
+ var n = a + (b & c | ~b & d) + (x >>> 0) + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ };
+ md5._gg = function (a, b, c, d, x, s, t) {
+ var n = a + (b & d | c & ~d) + (x >>> 0) + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ };
+ md5._hh = function (a, b, c, d, x, s, t) {
+ var n = a + (b ^ c ^ d) + (x >>> 0) + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ };
+ md5._ii = function (a, b, c, d, x, s, t) {
+ var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ };
+
+ // Package private blocksize
+ md5._blocksize = 16;
+ md5._digestsize = 16;
+
+ module.exports = function (message, options) {
+ if (message === undefined || message === null)
+ throw new Error('Illegal argument ' + message);
+
+ var digestbytes = crypt.wordsToBytes(md5(message, options));
+ return options && options.asBytes ? digestbytes :
+ options && options.asString ? bin.bytesToString(digestbytes) :
+ crypt.bytesToHex(digestbytes);
+ };
+
+ })();
+ + +/***/ }, + +/***/ 267: +/***/ function(module, exports) { + + (function() { + var base64map + = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', + + crypt = { + // Bit-wise rotation left + rotl: function(n, b) { + return (n << b) | (n >>> (32 - b)); + }, + + // Bit-wise rotation right + rotr: function(n, b) { + return (n << (32 - b)) | (n >>> b); + }, + + // Swap big-endian to little-endian and vice versa + endian: function(n) { + // If number given, swap endian + if (n.constructor == Number) { + return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00; + } + + // Else, assume array and swap all items + for (var i = 0; i < n.length; i++) + n[i] = crypt.endian(n[i]); + return n; + }, + + // Generate an array of any length of random bytes + randomBytes: function(n) { + for (var bytes = []; n > 0; n--) + bytes.push(Math.floor(Math.random() * 256)); + return bytes; + }, + + // Convert a byte array to big-endian 32-bit words + bytesToWords: function(bytes) { + for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8) + words[b >>> 5] |= bytes[i] << (24 - b % 32); + return words; + }, + + // Convert big-endian 32-bit words to a byte array + wordsToBytes: function(words) { + for (var bytes = [], b = 0; b < words.length * 32; b += 8) + bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); + return bytes; + }, + + // Convert a byte array to a hex string + bytesToHex: function(bytes) { + for (var hex = [], i = 0; i < bytes.length; i++) { + hex.push((bytes[i] >>> 4).toString(16)); + hex.push((bytes[i] & 0xF).toString(16)); + } + return hex.join(''); + }, + + // Convert a hex string to a byte array + hexToBytes: function(hex) { + for (var bytes = [], c = 0; c < hex.length; c += 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; + }, + + // Convert a byte array to a base-64 string + bytesToBase64: function(bytes) { + for (var base64 = [], i = 0; i < bytes.length; i += 3) { + var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; + for (var j = 0; j < 4; j++) + if (i * 8 + j * 6 <= bytes.length * 8) + base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F)); + else + base64.push('='); + } + return base64.join(''); + }, + + // Convert a base-64 string to a byte array + base64ToBytes: function(base64) { + // Remove non-base-64 characters + base64 = base64.replace(/[^A-Z0-9+\/]/ig, ''); + + for (var bytes = [], i = 0, imod4 = 0; i < base64.length; + imod4 = ++i % 4) { + if (imod4 == 0) continue; + bytes.push(((base64map.indexOf(base64.charAt(i - 1)) + & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) + | (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2))); + } + return bytes; + } + }; + + module.exports = crypt; + })(); + + +/***/ }, + +/***/ 268: +/***/ function(module, exports) { + + var charenc = { + // UTF-8 encoding + utf8: { + // Convert a string to a byte array + stringToBytes: function(str) { + return charenc.bin.stringToBytes(unescape(encodeURIComponent(str))); + }, + + // Convert a byte array to a string + bytesToString: function(bytes) { + return decodeURIComponent(escape(charenc.bin.bytesToString(bytes))); + } + }, + + // Binary encoding + bin: { + // Convert a string to a byte array + stringToBytes: function(str) { + for (var bytes = [], i = 0; i < str.length; i++) + bytes.push(str.charCodeAt(i) & 0xFF); + return bytes; + }, + + // Convert a byte array to a string + bytesToString: function(bytes) { + for (var str = [], i = 0; i < bytes.length; i++) + str.push(String.fromCharCode(bytes[i])); + return str.join(''); + } + } + }; + + module.exports = charenc; + + +/***/ }, + +/***/ 269: +/***/ function(module, exports) { + + /*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> + * @license MIT + */ + + // The _isBuffer check is for Safari 5-7 support, because it's missing + // Object.prototype.constructor. Remove this eventually + module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) + } + + function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) + } + + // For Node v0.10 support. Remove this eventually. + function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) + } + + +/***/ }, + +/***/ 277: +/***/ function(module, exports, __webpack_require__) { + + + + /** + * Utils for working with Source URLs + * @module utils/source + */ + + var _require = __webpack_require__(244); + + var endTruncateStr = _require.endTruncateStr; + + var _require2 = __webpack_require__(278); + + var basename = _require2.basename; + + + /** + * Trims the query part or reference identifier of a url string, if necessary. + * + * @memberof utils/source + * @static + */ + function trimUrlQuery(url) { + var length = url.length; + var q1 = url.indexOf("?"); + var q2 = url.indexOf("&"); + var q3 = url.indexOf("#"); + var q = Math.min(q1 != -1 ? q1 : length, q2 != -1 ? q2 : length, q3 != -1 ? q3 : length); + + return url.slice(0, q); + } + + /** + * Returns true if the specified url and/or content type are specific to + * javascript files. + * + * @return boolean + * True if the source is likely javascript. + * + * @memberof utils/source + * @static + */ + function isJavaScript(url) { + var contentType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + return url && /\.(jsm|js)?$/.test(trimUrlQuery(url)) || contentType.includes("javascript"); + } + + /** + * @memberof utils/source + * @static + */ + function isPretty(source) { + return source.url ? /formatted$/.test(source.url) : false; + } + + /** + * Show a source url's filename. + * If the source does not have a url, use the source id. + * + * @memberof utils/source + * @static + */ + function getFilename(source) { + var url = source.url; + var id = source.id; + + if (!url) { + var sourceId = id.split("/")[1]; + return `SOURCE${ sourceId }`; + } + + var name = basename(source.url || "") || "(index)"; + return endTruncateStr(name, 50); + } + + module.exports = { + isJavaScript, + isPretty, + getFilename + }; + +/***/ }, + +/***/ 278: +/***/ function(module, exports) { + + function basename(path) { + return path.split("/").pop(); + } + + function dirname(path) { + var idx = path.lastIndexOf("/"); + return path.slice(0, idx); + } + + function isURL(str) { + return str.indexOf("://") !== -1; + } + + function isAbsolute(str) { + return str[0] === "/"; + } + + function join(base, dir) { + return base + "/" + dir; + } + + module.exports = { + basename, dirname, isURL, isAbsolute, join + }; + +/***/ }, + +/***/ 293: +/***/ function(module, exports, __webpack_require__) { + + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + var punycode = __webpack_require__(294); + + exports.parse = urlParse; + exports.resolve = urlResolve; + exports.resolveObject = urlResolveObject; + exports.format = urlFormat; + + exports.Url = Url; + + function Url() { + this.protocol = null; + this.slashes = null; + this.auth = null; + this.host = null; + this.port = null; + this.hostname = null; + this.hash = null; + this.search = null; + this.query = null; + this.pathname = null; + this.path = null; + this.href = null; + } + + // Reference: RFC 3986, RFC 1808, RFC 2396 + + // define these here so at least they only have to be + // compiled once on the first module load. + var protocolPattern = /^([a-z0-9.+-]+:)/i, + portPattern = /:[0-9]*$/, + + // RFC 2396: characters reserved for delimiting URLs. + // We actually just auto-escape these. + delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], + + // RFC 2396: characters not allowed for various reasons. + unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), + + // Allowed by RFCs, but cause of XSS attacks. Always escape these. + autoEscape = ['\''].concat(unwise), + // Characters that are never ever allowed in a hostname. + // Note that any invalid chars are also handled, but these + // are the ones that are *expected* to be seen, so we fast-path + // them. + nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), + hostEndingChars = ['/', '?', '#'], + hostnameMaxLen = 255, + hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, + hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, + // protocols that can allow "unsafe" and "unwise" chars. + unsafeProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that never have a hostname. + hostlessProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that always contain a // bit. + slashedProtocol = { + 'http': true, + 'https': true, + 'ftp': true, + 'gopher': true, + 'file': true, + 'http:': true, + 'https:': true, + 'ftp:': true, + 'gopher:': true, + 'file:': true + }, + querystring = __webpack_require__(295); + + function urlParse(url, parseQueryString, slashesDenoteHost) { + if (url && isObject(url) && url instanceof Url) return url; + + var u = new Url; + u.parse(url, parseQueryString, slashesDenoteHost); + return u; + } + + Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { + if (!isString(url)) { + throw new TypeError("Parameter 'url' must be a string, not " + typeof url); + } + + var rest = url; + + // trim before proceeding. + // This is to support parse stuff like " http://foo.com \n" + rest = rest.trim(); + + var proto = protocolPattern.exec(rest); + if (proto) { + proto = proto[0]; + var lowerProto = proto.toLowerCase(); + this.protocol = lowerProto; + rest = rest.substr(proto.length); + } + + // figure out if it's got a host + // user@server is *always* interpreted as a hostname, and url + // resolution will treat //foo/bar as host=foo,path=bar because that's + // how the browser resolves relative URLs. + if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { + var slashes = rest.substr(0, 2) === '//'; + if (slashes && !(proto && hostlessProtocol[proto])) { + rest = rest.substr(2); + this.slashes = true; + } + } + + if (!hostlessProtocol[proto] && + (slashes || (proto && !slashedProtocol[proto]))) { + + // there's a hostname. + // the first instance of /, ?, ;, or # ends the host. + // + // If there is an @ in the hostname, then non-host chars *are* allowed + // to the left of the last @ sign, unless some host-ending character + // comes *before* the @-sign. + // URLs are obnoxious. + // + // ex: + // http://a@b@c/ => user:a@b host:c + // http://a@b?@c => user:a host:c path:/?@c + + // v0.12 TODO(isaacs): This is not quite how Chrome does things. + // Review our test case against browsers more comprehensively. + + // find the first instance of any hostEndingChars + var hostEnd = -1; + for (var i = 0; i < hostEndingChars.length; i++) { + var hec = rest.indexOf(hostEndingChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + + // at this point, either we have an explicit point where the + // auth portion cannot go past, or the last @ char is the decider. + var auth, atSign; + if (hostEnd === -1) { + // atSign can be anywhere. + atSign = rest.lastIndexOf('@'); + } else { + // atSign must be in auth portion. + // http://a@b/c@d => host:b auth:a path:/c@d + atSign = rest.lastIndexOf('@', hostEnd); + } + + // Now we have a portion which is definitely the auth. + // Pull that off. + if (atSign !== -1) { + auth = rest.slice(0, atSign); + rest = rest.slice(atSign + 1); + this.auth = decodeURIComponent(auth); + } + + // the host is the remaining to the left of the first non-host char + hostEnd = -1; + for (var i = 0; i < nonHostChars.length; i++) { + var hec = rest.indexOf(nonHostChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + // if we still have not hit it, then the entire thing is a host. + if (hostEnd === -1) + hostEnd = rest.length; + + this.host = rest.slice(0, hostEnd); + rest = rest.slice(hostEnd); + + // pull out port. + this.parseHost(); + + // we've indicated that there is a hostname, + // so even if it's empty, it has to be present. + this.hostname = this.hostname || ''; + + // if hostname begins with [ and ends with ] + // assume that it's an IPv6 address. + var ipv6Hostname = this.hostname[0] === '[' && + this.hostname[this.hostname.length - 1] === ']'; + + // validate a little. + if (!ipv6Hostname) { + var hostparts = this.hostname.split(/\./); + for (var i = 0, l = hostparts.length; i < l; i++) { + var part = hostparts[i]; + if (!part) continue; + if (!part.match(hostnamePartPattern)) { + var newpart = ''; + for (var j = 0, k = part.length; j < k; j++) { + if (part.charCodeAt(j) > 127) { + // we replace non-ASCII char with a temporary placeholder + // we need this to make sure size of hostname is not + // broken by replacing non-ASCII by nothing + newpart += 'x'; + } else { + newpart += part[j]; + } + } + // we test again with ASCII char only + if (!newpart.match(hostnamePartPattern)) { + var validParts = hostparts.slice(0, i); + var notHost = hostparts.slice(i + 1); + var bit = part.match(hostnamePartStart); + if (bit) { + validParts.push(bit[1]); + notHost.unshift(bit[2]); + } + if (notHost.length) { + rest = '/' + notHost.join('.') + rest; + } + this.hostname = validParts.join('.'); + break; + } + } + } + } + + if (this.hostname.length > hostnameMaxLen) { + this.hostname = ''; + } else { + // hostnames are always lower case. + this.hostname = this.hostname.toLowerCase(); + } + + if (!ipv6Hostname) { + // IDNA Support: Returns a puny coded representation of "domain". + // It only converts the part of the domain name that + // has non ASCII characters. I.e. it dosent matter if + // you call it with a domain that already is in ASCII. + var domainArray = this.hostname.split('.'); + var newOut = []; + for (var i = 0; i < domainArray.length; ++i) { + var s = domainArray[i]; + newOut.push(s.match(/[^A-Za-z0-9_-]/) ? + 'xn--' + punycode.encode(s) : s); + } + this.hostname = newOut.join('.'); + } + + var p = this.port ? ':' + this.port : ''; + var h = this.hostname || ''; + this.host = h + p; + this.href += this.host; + + // strip [ and ] from the hostname + // the host field still retains them, though + if (ipv6Hostname) { + this.hostname = this.hostname.substr(1, this.hostname.length - 2); + if (rest[0] !== '/') { + rest = '/' + rest; + } + } + } + + // now rest is set to the post-host stuff. + // chop off any delim chars. + if (!unsafeProtocol[lowerProto]) { + + // First, make 100% sure that any "autoEscape" chars get + // escaped, even if encodeURIComponent doesn't think they + // need to be. + for (var i = 0, l = autoEscape.length; i < l; i++) { + var ae = autoEscape[i]; + var esc = encodeURIComponent(ae); + if (esc === ae) { + esc = escape(ae); + } + rest = rest.split(ae).join(esc); + } + } + + + // chop off from the tail first. + var hash = rest.indexOf('#'); + if (hash !== -1) { + // got a fragment string. + this.hash = rest.substr(hash); + rest = rest.slice(0, hash); + } + var qm = rest.indexOf('?'); + if (qm !== -1) { + this.search = rest.substr(qm); + this.query = rest.substr(qm + 1); + if (parseQueryString) { + this.query = querystring.parse(this.query); + } + rest = rest.slice(0, qm); + } else if (parseQueryString) { + // no query string, but parseQueryString still requested + this.search = ''; + this.query = {}; + } + if (rest) this.pathname = rest; + if (slashedProtocol[lowerProto] && + this.hostname && !this.pathname) { + this.pathname = '/'; + } + + //to support http.request + if (this.pathname || this.search) { + var p = this.pathname || ''; + var s = this.search || ''; + this.path = p + s; + } + + // finally, reconstruct the href based on what has been validated. + this.href = this.format(); + return this; + }; + + // format a parsed object into a url string + function urlFormat(obj) { + // ensure it's an object, and not a string url. + // If it's an obj, this is a no-op. + // this way, you can call url_format() on strings + // to clean up potentially wonky urls. + if (isString(obj)) obj = urlParse(obj); + if (!(obj instanceof Url)) return Url.prototype.format.call(obj); + return obj.format(); + } + + Url.prototype.format = function() { + var auth = this.auth || ''; + if (auth) { + auth = encodeURIComponent(auth); + auth = auth.replace(/%3A/i, ':'); + auth += '@'; + } + + var protocol = this.protocol || '', + pathname = this.pathname || '', + hash = this.hash || '', + host = false, + query = ''; + + if (this.host) { + host = auth + this.host; + } else if (this.hostname) { + host = auth + (this.hostname.indexOf(':') === -1 ? + this.hostname : + '[' + this.hostname + ']'); + if (this.port) { + host += ':' + this.port; + } + } + + if (this.query && + isObject(this.query) && + Object.keys(this.query).length) { + query = querystring.stringify(this.query); + } + + var search = this.search || (query && ('?' + query)) || ''; + + if (protocol && protocol.substr(-1) !== ':') protocol += ':'; + + // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. + // unless they had them to begin with. + if (this.slashes || + (!protocol || slashedProtocol[protocol]) && host !== false) { + host = '//' + (host || ''); + if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; + } else if (!host) { + host = ''; + } + + if (hash && hash.charAt(0) !== '#') hash = '#' + hash; + if (search && search.charAt(0) !== '?') search = '?' + search; + + pathname = pathname.replace(/[?#]/g, function(match) { + return encodeURIComponent(match); + }); + search = search.replace('#', '%23'); + + return protocol + host + pathname + search + hash; + }; + + function urlResolve(source, relative) { + return urlParse(source, false, true).resolve(relative); + } + + Url.prototype.resolve = function(relative) { + return this.resolveObject(urlParse(relative, false, true)).format(); + }; + + function urlResolveObject(source, relative) { + if (!source) return relative; + return urlParse(source, false, true).resolveObject(relative); + } + + Url.prototype.resolveObject = function(relative) { + if (isString(relative)) { + var rel = new Url(); + rel.parse(relative, false, true); + relative = rel; + } + + var result = new Url(); + Object.keys(this).forEach(function(k) { + result[k] = this[k]; + }, this); + + // hash is always overridden, no matter what. + // even href="" will remove it. + result.hash = relative.hash; + + // if the relative url is empty, then there's nothing left to do here. + if (relative.href === '') { + result.href = result.format(); + return result; + } + + // hrefs like //foo/bar always cut to the protocol. + if (relative.slashes && !relative.protocol) { + // take everything except the protocol from relative + Object.keys(relative).forEach(function(k) { + if (k !== 'protocol') + result[k] = relative[k]; + }); + + //urlParse appends trailing / to urls like http://www.example.com + if (slashedProtocol[result.protocol] && + result.hostname && !result.pathname) { + result.path = result.pathname = '/'; + } + + result.href = result.format(); + return result; + } + + if (relative.protocol && relative.protocol !== result.protocol) { + // if it's a known url protocol, then changing + // the protocol does weird things + // first, if it's not file:, then we MUST have a host, + // and if there was a path + // to begin with, then we MUST have a path. + // if it is file:, then the host is dropped, + // because that's known to be hostless. + // anything else is assumed to be absolute. + if (!slashedProtocol[relative.protocol]) { + Object.keys(relative).forEach(function(k) { + result[k] = relative[k]; + }); + result.href = result.format(); + return result; + } + + result.protocol = relative.protocol; + if (!relative.host && !hostlessProtocol[relative.protocol]) { + var relPath = (relative.pathname || '').split('/'); + while (relPath.length && !(relative.host = relPath.shift())); + if (!relative.host) relative.host = ''; + if (!relative.hostname) relative.hostname = ''; + if (relPath[0] !== '') relPath.unshift(''); + if (relPath.length < 2) relPath.unshift(''); + result.pathname = relPath.join('/'); + } else { + result.pathname = relative.pathname; + } + result.search = relative.search; + result.query = relative.query; + result.host = relative.host || ''; + result.auth = relative.auth; + result.hostname = relative.hostname || relative.host; + result.port = relative.port; + // to support http.request + if (result.pathname || result.search) { + var p = result.pathname || ''; + var s = result.search || ''; + result.path = p + s; + } + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + } + + var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), + isRelAbs = ( + relative.host || + relative.pathname && relative.pathname.charAt(0) === '/' + ), + mustEndAbs = (isRelAbs || isSourceAbs || + (result.host && relative.pathname)), + removeAllDots = mustEndAbs, + srcPath = result.pathname && result.pathname.split('/') || [], + relPath = relative.pathname && relative.pathname.split('/') || [], + psychotic = result.protocol && !slashedProtocol[result.protocol]; + + // if the url is a non-slashed url, then relative + // links like ../.. should be able + // to crawl up to the hostname, as well. This is strange. + // result.protocol has already been set by now. + // Later on, put the first path part into the host field. + if (psychotic) { + result.hostname = ''; + result.port = null; + if (result.host) { + if (srcPath[0] === '') srcPath[0] = result.host; + else srcPath.unshift(result.host); + } + result.host = ''; + if (relative.protocol) { + relative.hostname = null; + relative.port = null; + if (relative.host) { + if (relPath[0] === '') relPath[0] = relative.host; + else relPath.unshift(relative.host); + } + relative.host = null; + } + mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); + } + + if (isRelAbs) { + // it's absolute. + result.host = (relative.host || relative.host === '') ? + relative.host : result.host; + result.hostname = (relative.hostname || relative.hostname === '') ? + relative.hostname : result.hostname; + result.search = relative.search; + result.query = relative.query; + srcPath = relPath; + // fall through to the dot-handling below. + } else if (relPath.length) { + // it's relative + // throw away the existing file, and take the new path instead. + if (!srcPath) srcPath = []; + srcPath.pop(); + srcPath = srcPath.concat(relPath); + result.search = relative.search; + result.query = relative.query; + } else if (!isNullOrUndefined(relative.search)) { + // just pull out the search. + // like href='?foo'. + // Put this after the other two cases because it simplifies the booleans + if (psychotic) { + result.hostname = result.host = srcPath.shift(); + //occationaly the auth can get stuck only in host + //this especialy happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + result.search = relative.search; + result.query = relative.query; + //to support http.request + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.href = result.format(); + return result; + } + + if (!srcPath.length) { + // no path at all. easy. + // we've already handled the other stuff above. + result.pathname = null; + //to support http.request + if (result.search) { + result.path = '/' + result.search; + } else { + result.path = null; + } + result.href = result.format(); + return result; + } + + // if a url ENDs in . or .., then it must get a trailing slash. + // however, if it ends in anything else non-slashy, + // then it must NOT get a trailing slash. + var last = srcPath.slice(-1)[0]; + var hasTrailingSlash = ( + (result.host || relative.host) && (last === '.' || last === '..') || + last === ''); + + // strip single dots, resolve double dots to parent dir + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = srcPath.length; i >= 0; i--) { + last = srcPath[i]; + if (last == '.') { + srcPath.splice(i, 1); + } else if (last === '..') { + srcPath.splice(i, 1); + up++; + } else if (up) { + srcPath.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (!mustEndAbs && !removeAllDots) { + for (; up--; up) { + srcPath.unshift('..'); + } + } + + if (mustEndAbs && srcPath[0] !== '' && + (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { + srcPath.unshift(''); + } + + if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { + srcPath.push(''); + } + + var isAbsolute = srcPath[0] === '' || + (srcPath[0] && srcPath[0].charAt(0) === '/'); + + // put the host back + if (psychotic) { + result.hostname = result.host = isAbsolute ? '' : + srcPath.length ? srcPath.shift() : ''; + //occationaly the auth can get stuck only in host + //this especialy happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + + mustEndAbs = mustEndAbs || (result.host && srcPath.length); + + if (mustEndAbs && !isAbsolute) { + srcPath.unshift(''); + } + + if (!srcPath.length) { + result.pathname = null; + result.path = null; + } else { + result.pathname = srcPath.join('/'); + } + + //to support request.http + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.auth = relative.auth || result.auth; + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + }; + + Url.prototype.parseHost = function() { + var host = this.host; + var port = portPattern.exec(host); + if (port) { + port = port[0]; + if (port !== ':') { + this.port = port.substr(1); + } + host = host.substr(0, host.length - port.length); + } + if (host) this.hostname = host; + }; + + function isString(arg) { + return typeof arg === "string"; + } + + function isObject(arg) { + return typeof arg === 'object' && arg !== null; + } + + function isNull(arg) { + return arg === null; + } + function isNullOrUndefined(arg) { + return arg == null; + } + + +/***/ }, + +/***/ 294: +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */ + ;(function(root) { + + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see <https://mathiasbynens.be/notes/javascript-encoding> + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * http://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>, + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.3.2', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see <https://mathiasbynens.be/notes/javascript-encoding> + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + true + ) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { + return punycode; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { // in Rhino or a web browser + root.punycode = punycode; + } + + }(this)); + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(77)(module), (function() { return this; }()))) + +/***/ }, + +/***/ 295: +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.decode = exports.parse = __webpack_require__(296); + exports.encode = exports.stringify = __webpack_require__(297); + + +/***/ }, + +/***/ 296: +/***/ function(module, exports) { + + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + 'use strict'; + + // If obj.hasOwnProperty has been overridden, then calling + // obj.hasOwnProperty(prop) will break. + // See: https://github.com/joyent/node/issues/1707 + function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); + } + + module.exports = function(qs, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + var obj = {}; + + if (typeof qs !== 'string' || qs.length === 0) { + return obj; + } + + var regexp = /\+/g; + qs = qs.split(sep); + + var maxKeys = 1000; + if (options && typeof options.maxKeys === 'number') { + maxKeys = options.maxKeys; + } + + var len = qs.length; + // maxKeys <= 0 means that we should not limit keys count + if (maxKeys > 0 && len > maxKeys) { + len = maxKeys; + } + + for (var i = 0; i < len; ++i) { + var x = qs[i].replace(regexp, '%20'), + idx = x.indexOf(eq), + kstr, vstr, k, v; + + if (idx >= 0) { + kstr = x.substr(0, idx); + vstr = x.substr(idx + 1); + } else { + kstr = x; + vstr = ''; + } + + k = decodeURIComponent(kstr); + v = decodeURIComponent(vstr); + + if (!hasOwnProperty(obj, k)) { + obj[k] = v; + } else if (Array.isArray(obj[k])) { + obj[k].push(v); + } else { + obj[k] = [obj[k], v]; + } + } + + return obj; + }; + + +/***/ }, + +/***/ 297: +/***/ function(module, exports) { + + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + 'use strict'; + + var stringifyPrimitive = function(v) { + switch (typeof v) { + case 'string': + return v; + + case 'boolean': + return v ? 'true' : 'false'; + + case 'number': + return isFinite(v) ? v : ''; + + default: + return ''; + } + }; + + module.exports = function(obj, sep, eq, name) { + sep = sep || '&'; + eq = eq || '='; + if (obj === null) { + obj = undefined; + } + + if (typeof obj === 'object') { + return Object.keys(obj).map(function(k) { + var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; + if (Array.isArray(obj[k])) { + return obj[k].map(function(v) { + return ks + encodeURIComponent(stringifyPrimitive(v)); + }).join(sep); + } else { + return ks + encodeURIComponent(stringifyPrimitive(obj[k])); + } + }).join(sep); + + } + + if (!name) return ''; + return encodeURIComponent(stringifyPrimitive(name)) + eq + + encodeURIComponent(stringifyPrimitive(obj)); + }; + + +/***/ }, + +/***/ 472: +/***/ function(module, exports, __webpack_require__) { + + /* + * 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 = __webpack_require__(473).SourceMapGenerator; + exports.SourceMapConsumer = __webpack_require__(479).SourceMapConsumer; + exports.SourceNode = __webpack_require__(482).SourceNode; + + +/***/ }, + +/***/ 473: +/***/ function(module, exports, __webpack_require__) { + + /* -*- 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 base64VLQ = __webpack_require__(474); + var util = __webpack_require__(476); + var ArraySet = __webpack_require__(477).ArraySet; + var MappingList = __webpack_require__(478).MappingList; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. You may pass an object with the following + * properties: + * + * - file: The filename of the generated source. + * - sourceRoot: A root for all relative URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + if (!aArgs) { + aArgs = {}; + } + this._file = util.getArg(aArgs, 'file', null); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._skipValidation = util.getArg(aArgs, 'skipValidation', false); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = new MappingList(); + 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 != null) { + newMapping.source = mapping.source; + if (sourceRoot != null) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name != null) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + 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); + + if (!this._skipValidation) { + this._validateMapping(generated, original, source, name); + } + + if (source != null) { + source = String(source); + if (!this._sources.has(source)) { + this._sources.add(source); + } + } + + if (name != null) { + name = String(name); + if (!this._names.has(name)) { + this._names.add(name); + } + } + + this._mappings.add({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + 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 != null) { + 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 = Object.create(null); + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else if (this._sourcesContents) { + // 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. + * @param aSourceMapPath Optional. The dirname of the path to the source map + * to be applied. If relative, it is relative to the SourceMapConsumer. + * This parameter is needed when the two source maps aren't in the same + * directory, and the source map to be applied contains relative source + * paths. If so, those relative source paths need to be rewritten + * relative to the SourceMapGenerator. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { + var sourceFile = aSourceFile; + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (aSourceFile == null) { + if (aSourceMapConsumer.file == null) { + throw new Error( + 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + + 'or the source map\'s "file" property. Both were omitted.' + ); + } + sourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "sourceFile" relative if an absolute Url is passed. + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + // 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 "sourceFile" + this._mappings.unsortedForEach(function (mapping) { + if (mapping.source === sourceFile && mapping.originalLine != null) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source != null) { + // Copy mapping + mapping.source = original.source; + if (aSourceMapPath != null) { + mapping.source = util.join(aSourceMapPath, mapping.source) + } + if (sourceRoot != null) { + mapping.source = util.relative(sourceRoot, mapping.source); + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name != null) { + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source != null && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name != null && !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 != null) { + if (aSourceMapPath != null) { + sourceFile = util.join(aSourceMapPath, sourceFile); + } + if (sourceRoot != null) { + 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: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + original: aOriginal, + name: aName + })); + } + }; + + /** + * 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 next; + var mapping; + var nameIdx; + var sourceIdx; + + var mappings = this._mappings.toArray(); + for (var i = 0, len = mappings.length; i < len; i++) { + mapping = mappings[i]; + next = '' + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + next += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { + continue; + } + next += ','; + } + } + + next += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; + + if (mapping.source != null) { + sourceIdx = this._sources.indexOf(mapping.source); + next += base64VLQ.encode(sourceIdx - previousSource); + previousSource = sourceIdx; + + // lines are stored 0-based in SourceMap spec version 3 + next += base64VLQ.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; + + next += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; + + if (mapping.name != null) { + nameIdx = this._names.indexOf(mapping.name); + next += base64VLQ.encode(nameIdx - previousName); + previousName = nameIdx; + } + } + + result += next; + } + + return result; + }; + + SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot != null) { + source = util.relative(aSourceRoot, source); + } + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) + ? this._sourcesContents[key] + : null; + }, this); + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._file != null) { + map.file = this._file; + } + if (this._sourceRoot != null) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } + + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this.toJSON()); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + + +/***/ }, + +/***/ 474: +/***/ function(module, exports, __webpack_require__) { + + /* -*- 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 + * + * 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 + * + * 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: + * + * * 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. + */ + + var base64 = __webpack_require__(475); + + // 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 VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit 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; + } + + /** + * Converts to a two-complement value from a value where the sign bit 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; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + 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; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string via the out parameter. + */ + exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (aIndex >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + + digit = base64.decode(aStr.charCodeAt(aIndex++)); + if (digit === -1) { + throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1)); + } + + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + aOutParam.value = fromVLQSigned(result); + aOutParam.rest = aIndex; + }; + + +/***/ }, + +/***/ 475: +/***/ function(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 intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function (number) { + if (0 <= number && number < intToCharMap.length) { + return intToCharMap[number]; + } + throw new TypeError("Must be between 0 and 63: " + number); + }; + + /** + * Decode a single base 64 character code digit to an integer. Returns -1 on + * failure. + */ + exports.decode = function (charCode) { + var bigA = 65; // 'A' + var bigZ = 90; // 'Z' + + var littleA = 97; // 'a' + var littleZ = 122; // 'z' + + var zero = 48; // '0' + var nine = 57; // '9' + + var plus = 43; // '+' + var slash = 47; // '/' + + var littleOffset = 26; + var numberOffset = 52; + + // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ + if (bigA <= charCode && charCode <= bigZ) { + return (charCode - bigA); + } + + // 26 - 51: abcdefghijklmnopqrstuvwxyz + if (littleA <= charCode && charCode <= littleZ) { + return (charCode - littleA + littleOffset); + } + + // 52 - 61: 0123456789 + if (zero <= charCode && charCode <= nine) { + return (charCode - zero + numberOffset); + } + + // 62: + + if (charCode == plus) { + return 62; + } + + // 63: / + if (charCode == slash) { + return 63; + } + + // Invalid base64 digit. + return -1; + }; + + +/***/ }, + +/***/ 476: +/***/ function(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 + */ + + /** + * 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; + + var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; + var dataUrlRegexp = /^data:.+\,.+$/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[2], + host: match[3], + port: match[4], + path: match[5] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = ''; + if (aParsedUrl.scheme) { + url += aParsedUrl.scheme + ':'; + } + url += '//'; + 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; + + /** + * Normalizes a path, or the path portion of a URL: + * + * - Replaces consecutive slashes with one slash. + * - Removes unnecessary '.' parts. + * - Removes unnecessary '<dir>/..' parts. + * + * Based on code in the Node.js 'path' core module. + * + * @param aPath The path or url to normalize. + */ + function normalize(aPath) { + var path = aPath; + var url = urlParse(aPath); + if (url) { + if (!url.path) { + return aPath; + } + path = url.path; + } + var isAbsolute = exports.isAbsolute(path); + + var parts = path.split(/\/+/); + for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { + part = parts[i]; + if (part === '.') { + parts.splice(i, 1); + } else if (part === '..') { + up++; + } else if (up > 0) { + if (part === '') { + // The first part is blank if the path is absolute. Trying to go + // above the root is a no-op. Therefore we can remove all '..' parts + // directly after the root. + parts.splice(i + 1, up); + up = 0; + } else { + parts.splice(i, 2); + up--; + } + } + } + path = parts.join('/'); + + if (path === '') { + path = isAbsolute ? '/' : '.'; + } + + if (url) { + url.path = path; + return urlGenerate(url); + } + return path; + } + exports.normalize = normalize; + + /** + * Joins two paths/URLs. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be joined with the root. + * + * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a + * scheme-relative URL: Then the scheme of aRoot, if any, is prepended + * first. + * - Otherwise aPath is a path. If aRoot is a URL, then its path portion + * is updated with the result and aRoot is returned. Otherwise the result + * is returned. + * - If aPath is absolute, the result is aPath. + * - Otherwise the two paths are joined with a slash. + * - Joining for example 'http://' and 'www.example.com' is also supported. + */ + function join(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + if (aPath === "") { + aPath = "."; + } + var aPathUrl = urlParse(aPath); + var aRootUrl = urlParse(aRoot); + if (aRootUrl) { + aRoot = aRootUrl.path || '/'; + } + + // `join(foo, '//www.example.org')` + if (aPathUrl && !aPathUrl.scheme) { + if (aRootUrl) { + aPathUrl.scheme = aRootUrl.scheme; + } + return urlGenerate(aPathUrl); + } + + if (aPathUrl || aPath.match(dataUrlRegexp)) { + return aPath; + } + + // `join('http://', 'www.example.com')` + if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { + aRootUrl.host = aPath; + return urlGenerate(aRootUrl); + } + + var joined = aPath.charAt(0) === '/' + ? aPath + : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); + + if (aRootUrl) { + aRootUrl.path = joined; + return urlGenerate(aRootUrl); + } + return joined; + } + exports.join = join; + + exports.isAbsolute = function (aPath) { + return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp); + }; + + /** + * Make a path relative to a URL or another path. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be made relative to aRoot. + */ + function relative(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + + aRoot = aRoot.replace(/\/$/, ''); + + // It is possible for the path to be above the root. In this case, simply + // checking whether the root is a prefix of the path won't work. Instead, we + // need to remove components from the root one by one, until either we find + // a prefix that fits, or we run out of components to remove. + var level = 0; + while (aPath.indexOf(aRoot + '/') !== 0) { + var index = aRoot.lastIndexOf("/"); + if (index < 0) { + return aPath; + } + + // If the only part of the root that is left is the scheme (i.e. http://, + // file:///, etc.), one or more slashes (/), or simply nothing at all, we + // have exhausted all components, so the path is not relative to the root. + aRoot = aRoot.slice(0, index); + if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { + return aPath; + } + + ++level; + } + + // Make sure we add a "../" for each component we removed from the root. + return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); + } + exports.relative = relative; + + var supportsNullProto = (function () { + var obj = Object.create(null); + return !('__proto__' in obj); + }()); + + function identity (s) { + return s; + } + + /** + * 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) { + if (isProtoString(aStr)) { + return '$' + aStr; + } + + return aStr; + } + exports.toSetString = supportsNullProto ? identity : toSetString; + + function fromSetString(aStr) { + if (isProtoString(aStr)) { + return aStr.slice(1); + } + + return aStr; + } + exports.fromSetString = supportsNullProto ? identity : fromSetString; + + function isProtoString(s) { + if (!s) { + return false; + } + + var length = s.length; + + if (length < 9 /* "__proto__".length */) { + return false; + } + + if (s.charCodeAt(length - 1) !== 95 /* '_' */ || + s.charCodeAt(length - 2) !== 95 /* '_' */ || + s.charCodeAt(length - 3) !== 111 /* 'o' */ || + s.charCodeAt(length - 4) !== 116 /* 't' */ || + s.charCodeAt(length - 5) !== 111 /* 'o' */ || + s.charCodeAt(length - 6) !== 114 /* 'r' */ || + s.charCodeAt(length - 7) !== 112 /* 'p' */ || + s.charCodeAt(length - 8) !== 95 /* '_' */ || + s.charCodeAt(length - 9) !== 95 /* '_' */) { + return false; + } + + for (var i = length - 10; i >= 0; i--) { + if (s.charCodeAt(i) !== 36 /* '$' */) { + return false; + } + } + + return true; + } + + /** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ + function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0 || onlyCompareOriginal) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + return mappingA.name - mappingB.name; + } + exports.compareByOriginalPositions = compareByOriginalPositions; + + /** + * Comparator between two mappings with deflated source and name indices where + * the generated positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ + function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0 || onlyCompareGenerated) { + return cmp; + } + + cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return mappingA.name - mappingB.name; + } + exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; + + function strcmp(aStr1, aStr2) { + if (aStr1 === aStr2) { + return 0; + } + + if (aStr1 > aStr2) { + return 1; + } + + return -1; + } + + /** + * Comparator between two mappings with inflated source and name strings where + * the generated positions are compared. + */ + function compareByGeneratedPositionsInflated(mappingA, mappingB) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + } + exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; + + +/***/ }, + +/***/ 477: +/***/ function(module, exports, __webpack_require__) { + + /* -*- 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 util = __webpack_require__(476); + var has = Object.prototype.hasOwnProperty; + + /** + * 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 = Object.create(null); + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); + } + return set; + }; + + /** + * Return how many unique items are in this ArraySet. If duplicates have been + * added, than those do not count towards the size. + * + * @returns Number + */ + ArraySet.prototype.size = function ArraySet_size() { + return Object.getOwnPropertyNames(this._set).length; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var sStr = util.toSetString(aStr); + var isDuplicate = has.call(this._set, sStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + this._set[sStr] = idx; + } + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + var sStr = util.toSetString(aStr); + return has.call(this._set, sStr); + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + var sStr = util.toSetString(aStr); + if (has.call(this._set, sStr)) { + return this._set[sStr]; + } + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * 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]; + } + 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(); + }; + + exports.ArraySet = ArraySet; + + +/***/ }, + +/***/ 478: +/***/ function(module, exports, __webpack_require__) { + + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2014 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var util = __webpack_require__(476); + + /** + * Determine whether mappingB is after mappingA with respect to generated + * position. + */ + function generatedPositionAfter(mappingA, mappingB) { + // Optimized for most common case + var lineA = mappingA.generatedLine; + var lineB = mappingB.generatedLine; + var columnA = mappingA.generatedColumn; + var columnB = mappingB.generatedColumn; + return lineB > lineA || lineB == lineA && columnB >= columnA || + util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; + } + + /** + * A data structure to provide a sorted view of accumulated mappings in a + * performance conscious manner. It trades a neglibable overhead in general + * case for a large speedup in case of mappings being added in order. + */ + function MappingList() { + this._array = []; + this._sorted = true; + // Serves as infimum + this._last = {generatedLine: -1, generatedColumn: 0}; + } + + /** + * Iterate through internal items. This method takes the same arguments that + * `Array.prototype.forEach` takes. + * + * NOTE: The order of the mappings is NOT guaranteed. + */ + MappingList.prototype.unsortedForEach = + function MappingList_forEach(aCallback, aThisArg) { + this._array.forEach(aCallback, aThisArg); + }; + + /** + * Add the given source mapping. + * + * @param Object aMapping + */ + MappingList.prototype.add = function MappingList_add(aMapping) { + if (generatedPositionAfter(this._last, aMapping)) { + this._last = aMapping; + this._array.push(aMapping); + } else { + this._sorted = false; + this._array.push(aMapping); + } + }; + + /** + * Returns the flat, sorted array of mappings. The mappings are sorted by + * generated position. + * + * WARNING: This method returns internal data without copying, for + * performance. The return value must NOT be mutated, and should be treated as + * an immutable borrow. If you want to take ownership, you must make your own + * copy. + */ + MappingList.prototype.toArray = function MappingList_toArray() { + if (!this._sorted) { + this._array.sort(util.compareByGeneratedPositionsInflated); + this._sorted = true; + } + return this._array; + }; + + exports.MappingList = MappingList; + + +/***/ }, + +/***/ 479: +/***/ function(module, exports, __webpack_require__) { + + /* -*- 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 util = __webpack_require__(476); + var binarySearch = __webpack_require__(480); + var ArraySet = __webpack_require__(477).ArraySet; + var base64VLQ = __webpack_require__(474); + var quickSort = __webpack_require__(481).quickSort; + + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + return sourceMap.sections != null + ? new IndexedSourceMapConsumer(sourceMap) + : new BasicSourceMapConsumer(sourceMap); + } + + SourceMapConsumer.fromSourceMap = function(aSourceMap) { + return BasicSourceMapConsumer.fromSourceMap(aSourceMap); + } + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + // `__generatedMappings` and `__originalMappings` are arrays that hold the + // parsed mapping coordinates from the source map's "mappings" attribute. They + // are lazily instantiated, accessed via the `_generatedMappings` and + // `_originalMappings` getters respectively, and we only parse the mappings + // and create these arrays once queried for a source location. We jump through + // these hoops because there can be many thousands of mappings, and parsing + // them is expensive, so we only want to do it if we must. + // + // Each object in the arrays is of the form: + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `_generatedMappings` is ordered by the generated positions. + // + // `_originalMappings` is ordered by the original positions. + + SourceMapConsumer.prototype.__generatedMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } + }); + + SourceMapConsumer.prototype.__originalMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } + }); + + SourceMapConsumer.prototype._charIsMappingSeparator = + function SourceMapConsumer_charIsMappingSeparator(aStr, index) { + var c = aStr.charAt(index); + return c === ";" || c === ","; + }; + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + throw new Error("Subclasses must implement _parseMappings"); + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + SourceMapConsumer.GREATEST_LOWER_BOUND = 1; + SourceMapConsumer.LEAST_UPPER_BOUND = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source === null ? null : this._sources.at(mapping.source); + if (source != null && sourceRoot != null) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name === null ? null : this._names.at(mapping.name) + }; + }, this).forEach(aCallback, context); + }; + + /** + * Returns all generated line and column information for the original source, + * line, and column provided. If no column is provided, returns all mappings + * corresponding to a either the line we are searching for or the next + * closest line that has any mappings. Otherwise, returns all mappings + * corresponding to the given line and either the column we are searching for + * or the next closest column that has any offsets. + * + * The only argument is an object with the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: Optional. the column number in the original source. + * + * and an array of objects is returned, each with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.allGeneratedPositionsFor = + function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { + var line = util.getArg(aArgs, 'line'); + + // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping + // returns the index of the closest mapping less than the needle. By + // setting needle.originalColumn to 0, we thus find the last mapping for + // the given line, provided such a mapping exists. + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: line, + originalColumn: util.getArg(aArgs, 'column', 0) + }; + + if (this.sourceRoot != null) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + if (!this._sources.has(needle.source)) { + return []; + } + needle.source = this._sources.indexOf(needle.source); + + var mappings = []; + + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + binarySearch.LEAST_UPPER_BOUND); + if (index >= 0) { + var mapping = this._originalMappings[index]; + + if (aArgs.column === undefined) { + var originalLine = mapping.originalLine; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we found. Since + // mappings are sorted, this is guaranteed to find all mappings for + // the line we found. + while (mapping && mapping.originalLine === originalLine) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } + } else { + var originalColumn = mapping.originalColumn; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we were searching for. + // Since mappings are sorted, this is guaranteed to find all mappings for + // the line we are searching for. + while (mapping && + mapping.originalLine === line && + mapping.originalColumn == originalColumn) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } + } + } + + return mappings; + }; + + exports.SourceMapConsumer = SourceMapConsumer; + + /** + * A BasicSourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: Optional. The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function BasicSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util.getArg(sourceMap, 'names', []); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + sources = sources + .map(String) + // Some source maps produce relative source paths like "./foo.js" instead of + // "foo.js". Normalize these first so that future comparisons will succeed. + // See bugzil.la/1090768. + .map(util.normalize) + // Always ensure that absolute sources are internally stored relative to + // the source root, if the source root is absolute. Not doing this would + // be particularly problematic when the source root is a prefix of the + // source (valid, but why??). See github issue #199 and bugzil.la/1188982. + .map(function (source) { + return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) + ? util.relative(sourceRoot, source) + : source; + }); + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names.map(String), true); + this._sources = ArraySet.fromArray(sources, true); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this.file = file; + } + + BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); + BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer; + + /** + * Create a BasicSourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns BasicSourceMapConsumer + */ + BasicSourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(BasicSourceMapConsumer.prototype); + + var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + // Because we are modifying the entries (by converting string sources and + // names to indices into the sources and names ArraySets), we have to make + // a copy of the entry or else bad things happen. Shared mutable state + // strikes again! See github issue #191. + + var generatedMappings = aSourceMap._mappings.toArray().slice(); + var destGeneratedMappings = smc.__generatedMappings = []; + var destOriginalMappings = smc.__originalMappings = []; + + for (var i = 0, length = generatedMappings.length; i < length; i++) { + var srcMapping = generatedMappings[i]; + var destMapping = new Mapping; + destMapping.generatedLine = srcMapping.generatedLine; + destMapping.generatedColumn = srcMapping.generatedColumn; + + if (srcMapping.source) { + destMapping.source = sources.indexOf(srcMapping.source); + destMapping.originalLine = srcMapping.originalLine; + destMapping.originalColumn = srcMapping.originalColumn; + + if (srcMapping.name) { + destMapping.name = names.indexOf(srcMapping.name); + } + + destOriginalMappings.push(destMapping); + } + + destGeneratedMappings.push(destMapping); + } + + quickSort(smc.__originalMappings, util.compareByOriginalPositions); + + return smc; + }; + + /** + * The version of the source mapping spec that we are consuming. + */ + BasicSourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + /** + * Provide the JIT with a nice shape / hidden class. + */ + function Mapping() { + this.generatedLine = 0; + this.generatedColumn = 0; + this.source = null; + this.originalLine = null; + this.originalColumn = null; + this.name = null; + } + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + BasicSourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var length = aStr.length; + var index = 0; + var cachedSegments = {}; + var temp = {}; + var originalMappings = []; + var generatedMappings = []; + var mapping, str, segment, end, value; + + while (index < length) { + if (aStr.charAt(index) === ';') { + generatedLine++; + index++; + previousGeneratedColumn = 0; + } + else if (aStr.charAt(index) === ',') { + index++; + } + else { + mapping = new Mapping(); + mapping.generatedLine = generatedLine; + + // Because each offset is encoded relative to the previous one, + // many segments often have the same encoding. We can exploit this + // fact by caching the parsed variable length fields of each segment, + // allowing us to avoid a second parse if we encounter the same + // segment again. + for (end = index; end < length; end++) { + if (this._charIsMappingSeparator(aStr, end)) { + break; + } + } + str = aStr.slice(index, end); + + segment = cachedSegments[str]; + if (segment) { + index += str.length; + } else { + segment = []; + while (index < end) { + base64VLQ.decode(aStr, index, temp); + value = temp.value; + index = temp.rest; + segment.push(value); + } + + if (segment.length === 2) { + throw new Error('Found a source, but no line and column'); + } + + if (segment.length === 3) { + throw new Error('Found a source and line, but no column'); + } + + cachedSegments[str] = segment; + } + + // Generated column. + mapping.generatedColumn = previousGeneratedColumn + segment[0]; + previousGeneratedColumn = mapping.generatedColumn; + + if (segment.length > 1) { + // Original source. + mapping.source = previousSource + segment[1]; + previousSource += segment[1]; + + // Original line. + mapping.originalLine = previousOriginalLine + segment[2]; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + + // Original column. + mapping.originalColumn = previousOriginalColumn + segment[3]; + previousOriginalColumn = mapping.originalColumn; + + if (segment.length > 4) { + // Original name. + mapping.name = previousName + segment[4]; + previousName += segment[4]; + } + } + + generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + originalMappings.push(mapping); + } + } + } + + quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated); + this.__generatedMappings = generatedMappings; + + quickSort(originalMappings, util.compareByOriginalPositions); + this.__originalMappings = originalMappings; + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + BasicSourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator, aBias) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator, aBias); + }; + + /** + * Compute the last column for each generated mapping. The last column is + * inclusive. + */ + BasicSourceMapConsumer.prototype.computeColumnSpans = + function SourceMapConsumer_computeColumnSpans() { + for (var index = 0; index < this._generatedMappings.length; ++index) { + var mapping = this._generatedMappings[index]; + + // Mappings do not contain a field for the last generated columnt. We + // can come up with an optimistic estimate, however, by assuming that + // mappings are contiguous (i.e. given two consecutive mappings, the + // first mapping ends where the second one starts). + if (index + 1 < this._generatedMappings.length) { + var nextMapping = this._generatedMappings[index + 1]; + + if (mapping.generatedLine === nextMapping.generatedLine) { + mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; + continue; + } + } + + // The last mapping for each line spans the entire line. + mapping.lastGeneratedColumn = Infinity; + } + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + BasicSourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var index = this._findMapping( + needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositionsDeflated, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); + + if (index >= 0) { + var mapping = this._generatedMappings[index]; + + if (mapping.generatedLine === needle.generatedLine) { + var source = util.getArg(mapping, 'source', null); + if (source !== null) { + source = this._sources.at(source); + if (this.sourceRoot != null) { + source = util.join(this.sourceRoot, source); + } + } + var name = util.getArg(mapping, 'name', null); + if (name !== null) { + name = this._names.at(name); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: name + }; + } + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ + BasicSourceMapConsumer.prototype.hasContentsOfAllSources = + function BasicSourceMapConsumer_hasContentsOfAllSources() { + if (!this.sourcesContent) { + return false; + } + return this.sourcesContent.length >= this._sources.size() && + !this.sourcesContent.some(function (sc) { return sc == 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 + * available. + */ + BasicSourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot != null) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot != null + && (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)]; + } + } + + // This function is used recursively from + // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we + // don't want to throw if we can't find the source - we just want to + // return null, so we provide a flag to exit gracefully. + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + BasicSourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var source = util.getArg(aArgs, 'source'); + if (this.sourceRoot != null) { + source = util.relative(this.sourceRoot, source); + } + if (!this._sources.has(source)) { + return { + line: null, + column: null, + lastColumn: null + }; + } + source = this._sources.indexOf(source); + + var needle = { + source: source, + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + var index = this._findMapping( + needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); + + if (index >= 0) { + var mapping = this._originalMappings[index]; + + if (mapping.source === needle.source) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }; + } + } + + return { + line: null, + column: null, + lastColumn: null + }; + }; + + exports.BasicSourceMapConsumer = BasicSourceMapConsumer; + + /** + * An IndexedSourceMapConsumer instance represents a parsed source map which + * we can query for information. It differs from BasicSourceMapConsumer in + * that it takes "indexed" source maps (i.e. ones with a "sections" field) as + * input. + * + * The only parameter is a raw source map (either as a JSON string, or already + * parsed to an object). According to the spec for indexed source maps, they + * have the following attributes: + * + * - version: Which version of the source map spec this map is following. + * - file: Optional. The generated file this source map is associated with. + * - sections: A list of section definitions. + * + * Each value under the "sections" field has two fields: + * - offset: The offset into the original specified at which this section + * begins to apply, defined as an object with a "line" and "column" + * field. + * - map: A source map definition. This source map could also be indexed, + * but doesn't have to be. + * + * Instead of the "map" field, it's also possible to have a "url" field + * specifying a URL to retrieve a source map from, but that's currently + * unsupported. + * + * Here's an example source map, taken from the source map spec[0], but + * modified to omit a section which uses the "url" field. + * + * { + * version : 3, + * file: "app.js", + * sections: [{ + * offset: {line:100, column:10}, + * map: { + * version : 3, + * file: "section.js", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AAAA,E;;ABCDE;" + * } + * }], + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt + */ + function IndexedSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sections = util.getArg(sourceMap, 'sections'); + + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + this._sources = new ArraySet(); + this._names = new ArraySet(); + + var lastOffset = { + line: -1, + column: 0 + }; + this._sections = sections.map(function (s) { + if (s.url) { + // The url field will require support for asynchronicity. + // See https://github.com/mozilla/source-map/issues/16 + throw new Error('Support for url field in sections not implemented.'); + } + var offset = util.getArg(s, 'offset'); + var offsetLine = util.getArg(offset, 'line'); + var offsetColumn = util.getArg(offset, 'column'); + + if (offsetLine < lastOffset.line || + (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { + throw new Error('Section offsets must be ordered and non-overlapping.'); + } + lastOffset = offset; + + return { + generatedOffset: { + // The offset fields are 0-based, but we use 1-based indices when + // encoding/decoding from VLQ. + generatedLine: offsetLine + 1, + generatedColumn: offsetColumn + 1 + }, + consumer: new SourceMapConsumer(util.getArg(s, 'map')) + } + }); + } + + IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); + IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer; + + /** + * The version of the source mapping spec that we are consuming. + */ + IndexedSourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', { + get: function () { + var sources = []; + for (var i = 0; i < this._sections.length; i++) { + for (var j = 0; j < this._sections[i].consumer.sources.length; j++) { + sources.push(this._sections[i].consumer.sources[j]); + } + } + return sources; + } + }); + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + IndexedSourceMapConsumer.prototype.originalPositionFor = + function IndexedSourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + // Find the section containing the generated position we're trying to map + // to an original position. + var sectionIndex = binarySearch.search(needle, this._sections, + function(needle, section) { + var cmp = needle.generatedLine - section.generatedOffset.generatedLine; + if (cmp) { + return cmp; + } + + return (needle.generatedColumn - + section.generatedOffset.generatedColumn); + }); + var section = this._sections[sectionIndex]; + + if (!section) { + return { + source: null, + line: null, + column: null, + name: null + }; + } + + return section.consumer.originalPositionFor({ + line: needle.generatedLine - + (section.generatedOffset.generatedLine - 1), + column: needle.generatedColumn - + (section.generatedOffset.generatedLine === needle.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + bias: aArgs.bias + }); + }; + + /** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ + IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = + function IndexedSourceMapConsumer_hasContentsOfAllSources() { + return this._sections.every(function (s) { + return s.consumer.hasContentsOfAllSources(); + }); + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * available. + */ + IndexedSourceMapConsumer.prototype.sourceContentFor = + function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + var content = section.consumer.sourceContentFor(aSource, true); + if (content) { + return content; + } + } + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + IndexedSourceMapConsumer.prototype.generatedPositionFor = + function IndexedSourceMapConsumer_generatedPositionFor(aArgs) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + // Only consider this section if the requested source is in the list of + // sources of the consumer. + if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) { + continue; + } + var generatedPosition = section.consumer.generatedPositionFor(aArgs); + if (generatedPosition) { + var ret = { + line: generatedPosition.line + + (section.generatedOffset.generatedLine - 1), + column: generatedPosition.column + + (section.generatedOffset.generatedLine === generatedPosition.line + ? section.generatedOffset.generatedColumn - 1 + : 0) + }; + return ret; + } + } + + return { + line: null, + column: null + }; + }; + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + IndexedSourceMapConsumer.prototype._parseMappings = + function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) { + this.__generatedMappings = []; + this.__originalMappings = []; + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + var sectionMappings = section.consumer._generatedMappings; + for (var j = 0; j < sectionMappings.length; j++) { + var mapping = sectionMappings[j]; + + var source = section.consumer._sources.at(mapping.source); + if (section.consumer.sourceRoot !== null) { + source = util.join(section.consumer.sourceRoot, source); + } + this._sources.add(source); + source = this._sources.indexOf(source); + + var name = section.consumer._names.at(mapping.name); + this._names.add(name); + name = this._names.indexOf(name); + + // The mappings coming from the consumer for the section have + // generated positions relative to the start of the section, so we + // need to offset them to be relative to the start of the concatenated + // generated file. + var adjustedMapping = { + source: source, + generatedLine: mapping.generatedLine + + (section.generatedOffset.generatedLine - 1), + generatedColumn: mapping.generatedColumn + + (section.generatedOffset.generatedLine === mapping.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: name + }; + + this.__generatedMappings.push(adjustedMapping); + if (typeof adjustedMapping.originalLine === 'number') { + this.__originalMappings.push(adjustedMapping); + } + } + } + + quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated); + quickSort(this.__originalMappings, util.compareByOriginalPositions); + }; + + exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; + + +/***/ }, + +/***/ 480: +/***/ function(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 + */ + + exports.GREATEST_LOWER_BOUND = 1; + exports.LEAST_UPPER_BOUND = 2; + + /** + * 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. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { + // 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 index of + // the next-closest element. + // + // 3. We did not find the exact element, and there is no next-closest + // element than the one we are searching for, so we return -1. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return mid; + } + else if (cmp > 0) { + // Our needle is greater than aHaystack[mid]. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); + } + + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return aHigh < aHaystack.length ? aHigh : -1; + } else { + return mid; + } + } + else { + // Our needle is less than aHaystack[mid]. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); + } + + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return mid; + } else { + return aLow < 0 ? -1 : aLow; + } + } + } + + /** + * This is an implementation of binary search which will always try and return + * the index of the closest element 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. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. + */ + exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { + if (aHaystack.length === 0) { + return -1; + } + + var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, + aCompare, aBias || exports.GREATEST_LOWER_BOUND); + if (index < 0) { + return -1; + } + + // We have found either the exact element, or the next-closest element than + // the one we are searching for. However, there may be more than one such + // element. Make sure we always return the smallest of these. + while (index - 1 >= 0) { + if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { + break; + } + --index; + } + + return index; + }; + + +/***/ }, + +/***/ 481: +/***/ function(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 + */ + + // It turns out that some (most?) JavaScript engines don't self-host + // `Array.prototype.sort`. This makes sense because C++ will likely remain + // faster than JS when doing raw CPU-intensive sorting. However, when using a + // custom comparator function, calling back and forth between the VM's C++ and + // JIT'd JS is rather slow *and* loses JIT type information, resulting in + // worse generated code for the comparator function than would be optimal. In + // fact, when sorting with a comparator, these costs outweigh the benefits of + // sorting in C++. By using our own JS-implemented Quick Sort (below), we get + // a ~3500ms mean speed-up in `bench/bench.html`. + + /** + * Swap the elements indexed by `x` and `y` in the array `ary`. + * + * @param {Array} ary + * The array. + * @param {Number} x + * The index of the first item. + * @param {Number} y + * The index of the second item. + */ + function swap(ary, x, y) { + var temp = ary[x]; + ary[x] = ary[y]; + ary[y] = temp; + } + + /** + * Returns a random integer within the range `low .. high` inclusive. + * + * @param {Number} low + * The lower bound on the range. + * @param {Number} high + * The upper bound on the range. + */ + function randomIntInRange(low, high) { + return Math.round(low + (Math.random() * (high - low))); + } + + /** + * The Quick Sort algorithm. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + * @param {Number} p + * Start index of the array + * @param {Number} r + * End index of the array + */ + function doQuickSort(ary, comparator, p, r) { + // If our lower bound is less than our upper bound, we (1) partition the + // array into two pieces and (2) recurse on each half. If it is not, this is + // the empty array and our base case. + + if (p < r) { + // (1) Partitioning. + // + // The partitioning chooses a pivot between `p` and `r` and moves all + // elements that are less than or equal to the pivot to the before it, and + // all the elements that are greater than it after it. The effect is that + // once partition is done, the pivot is in the exact place it will be when + // the array is put in sorted order, and it will not need to be moved + // again. This runs in O(n) time. + + // Always choose a random pivot so that an input array which is reverse + // sorted does not cause O(n^2) running time. + var pivotIndex = randomIntInRange(p, r); + var i = p - 1; + + swap(ary, pivotIndex, r); + var pivot = ary[r]; + + // Immediately after `j` is incremented in this loop, the following hold + // true: + // + // * Every element in `ary[p .. i]` is less than or equal to the pivot. + // + // * Every element in `ary[i+1 .. j-1]` is greater than the pivot. + for (var j = p; j < r; j++) { + if (comparator(ary[j], pivot) <= 0) { + i += 1; + swap(ary, i, j); + } + } + + swap(ary, i + 1, j); + var q = i + 1; + + // (2) Recurse on each half. + + doQuickSort(ary, comparator, p, q - 1); + doQuickSort(ary, comparator, q + 1, r); + } + } + + /** + * Sort the given array in-place with the given comparator function. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + */ + exports.quickSort = function (ary, comparator) { + doQuickSort(ary, comparator, 0, ary.length - 1); + }; + + +/***/ }, + +/***/ 482: +/***/ function(module, exports, __webpack_require__) { + + /* -*- 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 SourceMapGenerator = __webpack_require__(473).SourceMapGenerator; + var util = __webpack_require__(476); + + // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other + // operating systems these days (capturing the result). + var REGEX_NEWLINE = /(\r?\n)/; + + // Newline character code for charCodeAt() comparisons + var NEWLINE_CODE = 10; + + // Private symbol for identifying `SourceNode`s when multiple versions of + // the source-map library are loaded. This MUST NOT CHANGE across + // versions! + var isSourceNode = "$$$isSourceNode$$$"; + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine == null ? null : aLine; + this.column = aColumn == null ? null : aColumn; + this.source = aSource == null ? null : aSource; + this.name = aName == null ? null : aName; + this[isSourceNode] = true; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + * @param aRelativePath Optional. The path that relative sources in the + * SourceMapConsumer should be relative to. + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // All even indices of this array are one line of the generated code, + // while all odd indices are the newlines between two adjacent lines + // (since `REGEX_NEWLINE` captures its match). + // Processed fragments are removed from this array, by calling `shiftNextLine`. + var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); + var shiftNextLine = function() { + var lineContents = remainingLines.shift(); + // The last line of a file might not have a newline. + var newLine = remainingLines.shift() || ""; + return lineContents + newLine; + }; + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping !== null) { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + // Associate first line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + lastGeneratedLine++; + lastGeneratedColumn = 0; + // The remaining code is added without mapping + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[0]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + // No more remaining code, continue + lastMapping = mapping; + return; + } + } + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(shiftNextLine()); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + if (remainingLines.length > 0) { + if (lastMapping) { + // Associate the remaining code in the current line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + } + // and add the remaining lines without any mapping + node.add(remainingLines.join("")); + } + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aRelativePath != null) { + sourceFile = util.join(aRelativePath, sourceFile); + } + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + var source = aRelativePath + ? util.join(aRelativePath, mapping.source) + : mapping.source; + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk[isSourceNode]) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + } + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild[isSourceNode]) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i][isSourceNode]) { + this.children[i].walkSourceContents(aFn); + } + } + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + for (var idx = 0, length = chunk.length; idx < length; idx++) { + if (chunk.charCodeAt(idx) === NEWLINE_CODE) { + generated.line++; + generated.column = 0; + // Mappings end at eol + if (idx + 1 === length) { + lastOriginalSource = null; + sourceMappingActive = false; + } else if (sourceMappingActive) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + } else { + generated.column++; + } + } + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + + +/***/ } + +/******/ }); +//# sourceMappingURL=source-map-worker.js.map diff --git a/devtools/client/debugger/new/styles.css b/devtools/client/debugger/new/styles.css new file mode 100644 index 000000000..479bee363 --- /dev/null +++ b/devtools/client/debugger/new/styles.css @@ -0,0 +1,1724 @@ +:root.theme-light, +:root .theme-light { + --theme-search-overlays-semitransparent: rgba(221, 225, 228, 0.66); +} + +* { + box-sizing: border-box; +} + +html, +body { + height: 100%; + margin: 0; + padding: 0; + width: 100%; +} + +#mount { + display: flex; + height: 100%; +} + + +::-webkit-scrollbar { + width: 8px; + height: 8px; + background: transparent; +} + +::-webkit-scrollbar-track { + border-radius: 8px; + background: transparent; +} + +::-webkit-scrollbar-thumb { + border-radius: 8px; + background: rgba(113,113,113,0.5); +} + +:root.theme-dark .CodeMirror-scrollbar-filler { + background: transparent; +} +.landing-page { + flex: 1; + display: flex; + width: 100%; + height: 100%; + flex-direction: row; +} + +.landing-page .sidebar { + display: flex; + background-color: var(--theme-tab-toolbar-background); + width: 200px; + height: 100%; + flex-direction: column; +} + +.landing-page .sidebar h1 { + color: var(--theme-body-color); + font-size: 24px; + margin: 0; + line-height: 30px; + font-weight: normal; + padding: 40px 20px; +} + +.landing-page .sidebar ul { + list-style: none; + padding: 0; + line-height: 30px; + font-size: 18px; +} + +.landing-page .sidebar li { + padding: 5px 20px; +} + +.landing-page .sidebar li.selected { + background: var(--theme-search-overlays-semitransparent); + transition: all 0.25s ease; +} + +.landing-page .sidebar li:hover { + background: var(--theme-selection-background); + cursor: pointer; +} + +.landing-page .sidebar li a { + color: var(--theme-body-color); +} + +.landing-page .sidebar li:hover a { + color: var(--theme-selection-color); +} + +.landing-page .panel { + display: flex; + flex: 1; + height: 100%; + overflow: auto; + flex-direction: column; +} + +.landing-page .panel .title { + margin: 20px 40px; + width: calc(100% - 80px); + font-size: 16px; + border-bottom: 1px solid var(--theme-splitter-color); + height: 54px; +} + +.landing-page .panel h2 { + color: var(--theme-body-color); + font-weight: normal; +} + +.landing-page .panel .center { + flex: 1; + display: flex; + flex-direction: column; +} + +.landing-page .panel .center .center-message { + margin: 40px; + font-size: 16px; + line-height: 25px; + padding: 10px; +} + +.landing-page .center a { + color: var(--theme-highlight-bluegrey); + text-decoration: none; +} + +.landing-page .tab-group { + margin: 40px; +} + +.landing-page .tab-list { + list-style: none; + padding: 0px; + margin: 0px; +} + +.landing-page .tab { + border-bottom: 1px solid var(--theme-splitter-color); + padding: 10px; + font-family: sans-serif; +} + +.landing-page .tab:hover { + background-color: var(--theme-toolbar-background); + cursor: pointer; +} + +.landing-page .tab-title { + line-height: 25px; + font-size: 16px; + color: var(--theme-highlight-bluegrey); +} + +.landing-page .tab-url { + color: var(--theme-comment); +} + +.landing-page .panel .center .footer-note { + flex: 1; + padding: 50px; + font-size: 14px; + color: var(--theme-comment); + bottom: 0; + position: absolute; +} +/* vim:set ts=2 sw=2 sts=2 et: */ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +:root.theme-light, +:root .theme-light { + --theme-search-overlays-semitransparent: rgba(221, 225, 228, 0.66); + --theme-faded-tab-color: #7e7e7e; +} + +:root.theme-dark, +:root .theme-dark { + --theme-faded-tab-color: #6e7d8c; +} + +* { + box-sizing: border-box; +} + +html, +body { + height: 100%; + margin: 0; + padding: 0; + width: 100%; +} + +#mount { + display: flex; + height: 100%; +} + +.debugger { + display: flex; + flex: 1; + height: 100%; +} + +.center-pane { + display: flex; + position: relative; + flex: 1; + background-color: var(--theme-tab-toolbar-background); + overflow: hidden; +} + +.editor-container { + display: flex; + flex: 1; +} + +.subsettings:hover { + cursor: pointer; +} + +.search-container { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + z-index: 200; + background-color: var(--theme-search-overlays-semitransparent); +} + +.search-container .autocomplete { + flex: 1; +} + +.search-container .close-button { + width: 16px; + margin-top: 25px; + margin-right: 20px; +} + +.welcomebox { + width: calc(100% - 1px); + + /* Offsetting it by 30px for the sources-header area */ + height: calc(100% - 30px); + position: absolute; + top: 30px; + left: 0; + padding: 50px 0; + text-align: center; + font-size: 1.25em; + color: var(--theme-comment-alt); + background-color: var(--theme-tab-toolbar-background); + font-weight: lighter; + z-index: 100; +} +menupopup { + position: fixed; + z-index: 10000; + background: white; + border: 1px solid #cccccc; + padding: 5px 0; + background: #f2f2f2; + border-radius: 5px; + color: #585858; + box-shadow: 0 0 4px 0 rgba(190, 190, 190, 0.8); + min-width: 130px; +} + +menuitem { + display: block; + padding: 0 20px; + line-height: 20px; + font-weight: 500; + font-size: 13px; +} + +menuitem:hover { + background: #3780fb; + color: white; + cursor: pointer; +} + +menuseparator { + border-bottom: 1px solid #cacdd3; + width: 100%; + height: 5px; + display: block; + margin-bottom: 5px; +} + +#contextmenu-mask.show { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 999; +} +/* vim:set ts=2 sw=2 sts=2 et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +.split-box { + display: flex; + flex: 1; + min-width: 0; + height: 100%; + width: 100%; +} + +.split-box.vert { + flex-direction: row; +} + +.split-box.horz { + flex-direction: column; +} + +.split-box > .uncontrolled { + display: flex; + flex: 1; + min-width: 0; + overflow: auto; +} + +.split-box > .controlled { + display: flex; + overflow: auto; +} + +.split-box > .splitter { + background-image: none; + border: 0; + border-style: solid; + border-color: transparent; + background-color: var(--theme-splitter-color); + background-clip: content-box; + position: relative; + + box-sizing: border-box; + + /* Positive z-index positions the splitter on top of its siblings and makes + it clickable on both sides. */ + z-index: 1; +} + +.split-box.vert > .splitter { + min-width: calc(var(--devtools-splitter-inline-start-width) + + var(--devtools-splitter-inline-end-width) + 1px); + + border-left-width: var(--devtools-splitter-inline-start-width); + border-right-width: var(--devtools-splitter-inline-end-width); + + margin-left: calc(-1 * var(--devtools-splitter-inline-start-width) - 1px); + margin-right: calc(-1 * var(--devtools-splitter-inline-end-width)); + + cursor: ew-resize; +} + +.split-box.horz > .splitter { + min-height: calc(var(--devtools-splitter-top-width) + + var(--devtools-splitter-bottom-width) + 1px); + + border-top-width: var(--devtools-splitter-top-width); + border-bottom-width: var(--devtools-splitter-bottom-width); + + margin-top: calc(-1 * var(--devtools-splitter-top-width) - 1px); + margin-bottom: calc(-1 * var(--devtools-splitter-bottom-width)); + + cursor: ns-resize; +} + +.split-box.disabled { + pointer-events: none; +} + +/** + * Make sure splitter panels are not processing any mouse + * events. This is good for performance during splitter + * bar dragging. + */ +.split-box.dragging > .controlled, +.split-box.dragging > .uncontrolled { + pointer-events: none; +} +/* vim:set ts=2 sw=2 sts=2 et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +.theme-dark, +.theme-light { + --number-color: var(--theme-highlight-green); + --string-color: var(--theme-highlight-orange); + --null-color: var(--theme-comment); + --object-color: var(--theme-body-color); + --caption-color: var(--theme-highlight-blue); + --location-color: var(--theme-content-color1); + --source-link-color: var(--theme-highlight-blue); + --node-color: var(--theme-highlight-bluegrey); + --reference-color: var(--theme-highlight-purple); +} + +.theme-firebug { + --number-color: #000088; + --string-color: #FF0000; + --null-color: #787878; + --object-color: DarkGreen; + --caption-color: #444444; + --location-color: #555555; + --source-link-color: blue; + --node-color: rgb(0, 0, 136); + --reference-color: rgb(102, 102, 255); +} + +/******************************************************************************/ + +.objectLink:hover { + cursor: pointer; + text-decoration: underline; +} + +.inline { + display: inline; + white-space: normal; +} + +.objectBox-object { + font-weight: bold; + color: var(--object-color); + white-space: pre-wrap; +} + +.objectBox-string, +.objectBox-text, +.objectLink-textNode, +.objectBox-table { + white-space: pre-wrap; +} + +.objectBox-number, +.objectLink-styleRule, +.objectLink-element, +.objectLink-textNode, +.objectBox-array > .length { + color: var(--number-color); +} + +.objectBox-string { + color: var(--string-color); +} + +.objectLink-function, +.objectBox-stackTrace, +.objectLink-profile { + color: var(--object-color); +} + +.objectLink-Location { + font-style: italic; + color: var(--location-color); +} + +.objectBox-null, +.objectBox-undefined, +.objectBox-hint, +.logRowHint { + font-style: italic; + color: var(--null-color); +} + +.objectLink-sourceLink { + position: absolute; + right: 4px; + top: 2px; + padding-left: 8px; + font-weight: bold; + color: var(--source-link-color); +} + +/******************************************************************************/ + +.objectLink-event, +.objectLink-eventLog, +.objectLink-regexp, +.objectLink-object, +.objectLink-Date { + font-weight: bold; + color: var(--object-color); + white-space: pre-wrap; +} + +/******************************************************************************/ + +.objectLink-object .nodeName, +.objectLink-NamedNodeMap .nodeName, +.objectLink-NamedNodeMap .objectEqual, +.objectLink-NamedNodeMap .arrayLeftBracket, +.objectLink-NamedNodeMap .arrayRightBracket, +.objectLink-Attr .attrEqual, +.objectLink-Attr .attrTitle { + color: var(--node-color); +} + +.objectLink-object .nodeName { + font-weight: normal; +} + +/******************************************************************************/ + +.objectLeftBrace, +.objectRightBrace, +.arrayLeftBracket, +.arrayRightBracket { + cursor: pointer; + font-weight: bold; +} + +.objectLeftBrace, +.arrayLeftBracket { + margin-right: 4px; +} + +.objectRightBrace, +.arrayRightBracket { + margin-left: 4px; +} + +/******************************************************************************/ +/* Cycle reference*/ + +.objectLink-Reference { + font-weight: bold; + color: var(--reference-color); +} + +.objectBox-array > .objectTitle { + font-weight: bold; + color: var(--object-color); +} + +.caption { + font-weight: bold; + color: var(--caption-color); +} + +/******************************************************************************/ +/* Themes */ + +.theme-dark .objectBox-null, +.theme-dark .objectBox-undefined, +.theme-light .objectBox-null, +.theme-light .objectBox-undefined { + font-style: normal; +} + +.theme-dark .objectBox-object, +.theme-light .objectBox-object { + font-weight: normal; + white-space: pre-wrap; +} + +.theme-dark .caption, +.theme-light .caption { + font-weight: normal; +} +/* vim:set ts=2 sw=2 sts=2 et: */ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +.search-container { + position: absolute; + top: 30px; + left: 0; + width: calc(100% - 1px); + height: calc(100% - 31px); + display: flex; + z-index: 200; + background-color: var(--theme-body-background); +} + +.search-container .autocomplete { + flex: 1; +} + +.searchinput-container { + display: flex; +} + +.searchinput-container .close-btn-big { + border-bottom: 1px solid var(--theme-splitter-color); +} + +.autocomplete { + width: 100%; +} + +.autocomplete .results * { + -moz-user-select: none; + user-select: none; +} + +.autocomplete .results-summary { + margin: 10px; +} + +.autocomplete ul { + list-style: none; + width: 100%; + max-height: calc(100% - 32px); + margin: 0px; + padding: 0px; + overflow: auto; +} + +.autocomplete li { + border: 2px solid var(--theme-splitter-color); + background-color: var(--theme-tab-toolbar-background); + padding: 10px; + margin: 10px; +} + +.autocomplete li:hover { + background: var(--theme-tab-toolbar-background); + cursor: pointer; +} + +.autocomplete li.selected { + border: 2px solid var(--theme-selection-background); +} + +.autocomplete li .title { + line-height: 1.5em; + word-break: break-all; +} + +.autocomplete li .subtitle { + line-height: 1.5em; + color: grey; + word-break: break-all; +} + +.autocomplete input { + width: 100%; + border: none; + background-color: var(--theme-body-background); + color: var(--theme-comment); + border-bottom: 1px solid var(--theme-splitter-color); + outline: none; + line-height: 30px; + font-size: 14px; + height: 40px; + padding-left: 30px; +} + +.autocomplete input::placeholder { + color: var(--theme-body-color-inactive); +} + +.autocomplete .magnifying-glass svg { + width: 16px; + position: absolute; + top: 12px; + left: 10px; +} + +.autocomplete.focused .magnifying-glass path, +.autocomplete.focused .magnifying-glass ellipse { + stroke: var(--theme-highlight-blue); +} + +.autocomplete .magnifying-glass path, +.autocomplete .magnifying-glass ellipse { + stroke: var(--theme-splitter-color); +} + +.autocomplete .no-result-msg { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + color: var(--theme-graphs-full-red); + font-size: 24px; +} + +.autocomplete .no-result-msg .sad-face { + width: 24px; + margin-right: 4px; + line-height: 0; +} + +.autocomplete .no-result-msg .sad-face svg { + fill: var(--theme-graphs-full-red); +} +.close-btn path { + fill: var(--theme-body-color); +} + +.close-btn .close { + cursor: pointer; + width: 12px; + height: 12px; + padding: 2px; + text-align: center; + margin-top: 2px; + line-height: 5px; + transition: all 0.25s easeinout; +} + +.close-btn .close svg { + width: 6px; +} + +.close-btn .close:hover { + background: var(--theme-selection-background); + border-radius: 2px; +} + +.close-btn .close:hover path { + fill: white; +} + +.close-btn-big { + padding: 13px; + width: 40px; + height: 40px; +} + +.close-btn-big path { + fill: var(--theme-body-color); +} + +.close-btn-big .close { + cursor: pointer; + display: inline-block; + padding: 2px; + text-align: center; + transition: all 0.25s easeinout; + line-height: 100%; + width: 16px; + height: 16px; +} + +.close-btn-big .close svg { + width: 9px; + height: 9px; +} + +.close-btn-big .close:hover { + background: var(--theme-selection-background); + border-radius: 2px; +} + +.close-btn-big .close:hover path { + fill: white; +} +.tree { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; + + flex: 1; + white-space: nowrap; + overflow: auto; +} + +.tree button { + display: block; +} + +.tree .node { + padding: 2px 5px; + position: relative; +} + +.tree .node.focused { + color: white; + background-color: var(--theme-selection-background); +} + +html:not([dir="rtl"]) .tree .node > div { + margin-left: 10px; +} + +html[dir="rtl"] .tree .node > div { + margin-right: 10px; +} + +.tree .node.focused svg { + fill: white; +} + +.tree-node button { + position: fixed; +} +.sources-panel { + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; +} + +.sources-panel * { + -moz-user-select: none; + user-select: none; +} + +.sources-header { + height: 30px; + border-bottom: 1px solid var(--theme-splitter-color); + padding-top: 0px; + padding-bottom: 0px; + line-height: 30px; + font-size: 1.2em; + display: flex; + align-items: baseline; + justify-content: space-between; + -moz-user-select: none; + user-select: none; +} + +html:not([dir="rtl"]) .sources-header { + padding-left: 10px; +} + +html[dir="rtl"] .sources-header { + padding-right: 10px; +} + +.sources-header-info { + font-size: 12px; + color: var(--theme-comment-alt); + font-weight: lighter; + white-space: nowrap; +} + +html:not([dir="rtl"]) .sources-header-info { + padding-right: 10px; + float: right; +} + +html[dir="rtl"] .sources-header-info { + padding-left: 10px; + float: left; +} + +.sources-list { + flex: 1; + display: flex; + overflow: hidden; +} + +.arrow, +.folder, +.domain, +.file, +.worker { + fill: var(--theme-splitter-color); +} + +.domain, +.file, +.worker { + position: relative; + top: 1px; +} + +.worker, +.folder { + position: relative; + top: 2px; +} + +.domain svg, +.folder svg, +.worker svg { + width: 15px; +} + +.file svg { + width: 13px; +} + +html:not([dir="rtl"]) .file svg, +html:not([dir="rtl"]) .domain svg, +html:not([dir="rtl"]) .folder svg, +html:not([dir="rtl"]) .worker svg { + margin-right: 5px; +} + +html[dir="rtl"] .file svg, +html[dir="rtl"] .domain svg, +html[dir="rtl"] .folder svg, +html[dir="rtl"] .worker svg { + margin-left: 5px; +} + +.tree { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; + + flex: 1; + white-space: nowrap; + overflow: auto; +} + +.tree button { + display: block; +} + +.tree .node { + padding: 2px 5px; + position: relative; + cursor: pointer; +} + +.tree .node:hover { + background: var(--theme-tab-toolbar-background); +} + +.tree .node.focused { + color: white; + background-color: var(--theme-selection-background); +} + +.tree .node > div { + margin-left: 10px; +} + +.tree .node.focused svg { + fill: white; +} + +.sources-list .tree-node button { + position: fixed; +} + +.source-footer { + background: var(--theme-body-background); + border-top: 1px solid var(--theme-splitter-color); + position: absolute; + bottom: 0; + left: 0; + right: 1px; + opacity: 1; + z-index: 100; + -moz-user-select: none; + user-select: none; +} + +html:not([dir="rtl"]) .source-footer .command-bar { + float: right; +} + +html[dir="rtl"] .source-footer .command-bar { + float: left; +} + +.source-footer .command-bar * { + -moz-user-select: none; + user-select: none; +} + +.command-bar > span { + cursor: pointer; + width: 1em; + height: 1.1em; + display: inline-block; + text-align: center; + transition: opacity 200ms; +} + +html:not([dir="rtl"]) .command-bar > span { + margin-right: 0.7em; +} + +html[dir="rtl"] .command-bar > span { + margin-left: 0.7em; +} + +.source-footer .prettyPrint.pretty { + stroke: var(--theme-highlight-blue); +} + +.source-footer input:focus { + border-color: var(--theme-highlight-blue); + outline: none; +} + +.source-footer input { + line-height: 16px; + margin: 7px; + border-radius: 2px; + border: 1px solid var(--theme-splitter-color); + padding-left: 4px; + font-size: 10px; +} +.search-bar { + width: calc(100% - 1px); + height: 40px; + background: white; + border-bottom: 1px solid var(--theme-splitter-color); + display: flex; +} + +.search-bar i { + display: block; + padding: 13px 0 0 13px; + width: 40px; +} + +.search-bar i svg { + width: 16px; +} + +.search-bar input { + border: none; + line-height: 30px; + font-size: 14px; + background-color: var(--theme-body-background); + color: var(--theme-comment); + width: calc(100% - 38px); + flex: 1; +} + +.search-bar .magnifying-glass { + background-color: var(--theme-body-background); + width: 40px; +} + +.search-bar .magnifying-glass path, +.search-bar .magnifying-glass ellipse { + stroke: var(--theme-splitter-color); +} + +.search-bar input::placeholder { + color: var(--theme-body-color-inactive); +} + +.search-bar input:focus { + outline-width: 0; +} + +.search-bar input.empty { + color: var(--theme-highlight-orange); +} + +.search-bar .summary { + line-height: 40px; + padding-right: 10px; + color: var(--theme-body-color-inactive); +} +/* vim:set ts=2 sw=2 sts=2 et: */ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * There's a known codemirror flex issue with chrome that this addresses. + * BUG https://github.com/devtools-html/debugger.html/issues/63 + */ +.editor-wrapper { + position: absolute; + height: calc(100% - 31px); + width: 100%; + top: 30px; + left: 0px; +} + +html[dir="rtl"] .editor-mount { + direction: ltr; +} + +.editor-wrapper .breakpoints { + position: absolute; + top: 0; + left: 0; +} + +.editor.new-breakpoint svg { + fill: var(--theme-selection-background); + width: 60px; + height: 14px; + position: absolute; + top: 0px; + right: -4px; +} + +.new-breakpoint.has-condition svg { + fill: var(--theme-graphs-yellow); +} + +.editor.new-breakpoint.breakpoint-disabled svg { + opacity: 0.3; +} + +.CodeMirror { + width: 100%; + height: 100%; +} + +.editor-wrapper .editor-mount { + width: 100%; + height: calc(100% - 32px); + background-color: var(--theme-body-background); +} + +.search-bar ~ .editor-mount { + height: calc(100% - 72px); +} + +.CodeMirror-linenumber { + font-size: 11px; + line-height: 14px; +} + +/* set the linenumber white when there is a breakpoint */ +.new-breakpoint .CodeMirror-gutter-wrapper .CodeMirror-linenumber { + color: white; +} + +/* move the breakpoint below the linenumber */ +.new-breakpoint .CodeMirror-gutter-elt:last-child { + z-index: 0; +} + +.editor-wrapper .CodeMirror-line { + font-size: 11px; + line-height: 14px; +} + +.debug-line .CodeMirror-line { + background-color: var(--breakpoint-active-color) !important; +} + +/* Don't display the highlight color since the debug line + is already highlighted */ +.debug-line .CodeMirror-activeline-background { + display: none; +} + +.highlight-line .CodeMirror-line { + animation: fade-highlight-out 1.5s normal forwards; +} + +@keyframes fade-highlight-out { + 0% { background-color: var(--theme-highlight-gray); } + 100% { background-color: transparent; } +} + +.welcomebox { + width: calc(100% - 1px); + + /* Offsetting it by 30px for the sources-header area */ + height: calc(100% - 30px); + position: absolute; + top: 30px; + left: 0; + padding: 50px 0; + text-align: center; + font-size: 1.25em; + color: var(--theme-comment-alt); + background-color: var(--theme-tab-toolbar-background); + font-weight: lighter; + z-index: 100; + -moz-user-select: none; + user-select: none; +} + +.conditional-breakpoint-panel { + cursor: initial; + margin: 1em 0; + position: relative; + background: var(--theme-toolbar-background); + border-top: 1px solid var(--theme-splitter-color); + border-bottom: 1px solid var(--theme-splitter-color); +} + +.conditional-breakpoint-panel input { + margin: 5px 10px; + width: calc(100% - 2em); + border: none; + background: var(--theme-toolbar-background); + font-size: 14px; + color: var(--theme-comment); + line-height: 30px; +} + +.conditional-breakpoint-panel input:focus { + outline-width: 0; +} +.breakpoints-list * { + -moz-user-select: none; + user-select: none; +} + +.breakpoints-list .breakpoint { + font-size: 12px; + color: var(--theme-content-color1); + padding: 0.5em 1px; + line-height: 1em; + position: relative; + border-left: 4px solid transparent; + transition: all 0.25s ease; +} + +.breakpoints-list .breakpoint:last-of-type { + padding-bottom: 0.45em; +} + +.breakpoints-list .breakpoint.paused { + background-color: var(--theme-toolbar-background-alt); + border-color: var(--breakpoint-active-color); +} + +.breakpoints-list .breakpoint.disabled .breakpoint-label { + color: var(--theme-content-color3); + transition: color 0.5s linear; +} + +.breakpoints-list .breakpoint:hover { + cursor: pointer; + background-color: var(--theme-search-overlays-semitransparent); +} + +.breakpoints-list .breakpoint.paused:hover { + border-color: var(--breakpoint-active-color-hover); +} + +.breakpoints-list .breakpoint-checkbox { + margin-left: 0; +} + +.breakpoints-list .breakpoint-label { + display: inline-block; + padding-left: 2px; + padding-bottom: 4px; +} + +.breakpoints-list .pause-indicator { + flex: 0 1 content; + order: 3; +} + +.breakpoint-snippet { + color: var(--theme-comment); + padding-left: 18px; +} + +.breakpoint .close-btn { + position: absolute; + right: 6px; + top: 12px; +} + +.breakpoint .close { + display: none; +} + +.breakpoint:hover .close { + display: block; +} +.input-expression { + width: 100%; + padding: 5px; + margin: 0px; + border: none; + cursor: hand; +} + +.expression-container { + border: 1px; + padding: 5px 2px 5px 5px; + margin: 1px; + width: 100%; + color: var(--theme-body-color) !important; + background-color: var(--theme-tab-toolbar-background); +} + +.expression-container:hover { + background-color: var(--theme-selection-background); + color: var(--theme-body-background) !important; +} + +.expression-output-container .close-btn { + width: 6px; + height: 6px; + float: right; + margin-right: 6px; + display: block; + cursor: pointer; +} + +.expression-input { + cursor: pointer; + max-width: 50%; +} + +.expression-value { + overflow-x: scroll; + color: var(--theme-content-color2); + max-width: 50% !important; +} + +.expression-error { + color: var(--theme-highlight-red); +} +.arrow svg { + fill: var(--theme-splitter-color); + margin-top: 3px; + transition: transform 0.25s ease; + width: 10px; +} + +html:not([dir="rtl"]) .arrow svg { + margin-right: 5px; + transform: rotate(-90deg); +} + +html[dir="rtl"] .arrow svg { + margin-left: 5px; + transform: rotate(90deg); +} + +/* TODO (Amit): html is just for specificity. keep it like this? */ +html .arrow.expanded svg { + transform: rotate(0deg); +} + +.arrow.hidden { + visibility: hidden; +} + +.object-label { + color: var(--theme-highlight-blue); +} + +.objectBox-object, +.objectBox-string, +.objectBox-text, +.objectBox-table, +.objectLink-textNode, +.objectLink-event, +.objectLink-eventLog, +.objectLink-regexp, +.objectLink-object, +.objectLink-Date, +.theme-dark .objectBox-object, +.theme-light .objectBox-object { + white-space: nowrap; +} + +.scopes-list .tree-node { + overflow: hidden; +} +.frames ul { + list-style: none; + margin: 0; + padding: 0; +} + +.frames ul li { + cursor: pointer; + padding: 7px 10px 7px 21px; + clear: both; + overflow: hidden; +} + +/* Style the focused call frame like so: +.frames ul li:focus { + border: 3px solid red; +} +*/ + +.frames ul li * { + -moz-user-select: none; + user-select: none; +} + +.frames ul li:nth-of-type(2n) { + background-color: var(--theme-tab-toolbar-background); +} + +.frames .location { + float: right; + color: var(--theme-comment); + font-weight: lighter; +} + +.frames .title { + float: left; + text-overflow: ellipsis; + overflow: hidden; + margin-right: 1em; +} + +.frames ul li.selected, +.frames ul li.selected .location { + background-color: var(--theme-selection-background); + color: white; +} + +.show-more { + cursor: pointer; + text-align: center; + padding: 8px 0px; + border-top: 1px solid var(--theme-splitter-color); + background-color: var(--theme-tab-toolbar-background); +} + +.show-more:hover { + background-color: var(--theme-search-overlays-semitransparent); +} +.accordion { + background-color: var(--theme-body-background); + width: 100%; +} + +.accordion ._header { + background-color: var(--theme-toolbar-background); + border-bottom: 1px solid var(--theme-splitter-color); + cursor: pointer; + font-size: 12px; + padding: 5px; + transition: all 0.25s ease; + width: 100%; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} + +.accordion ._header:hover { + background-color: var(--theme-search-overlays-semitransparent); +} + +.accordion ._header:hover svg { + fill: var(--theme-comment-alt); +} + +.accordion ._content { + border-bottom: 1px solid var(--theme-splitter-color); + font-size: 12px; +} +.right-sidebar { + display: flex; + flex-direction: column; + flex: 1; + white-space: nowrap; +} + +.right-siderbar * { + -moz-user-select: none; + user-select: none; +} + +.right-sidebar .accordion { + overflow-y: auto; + overflow-x: hidden; +} + +.right-sidebar .command-bar { + border-bottom: 1px solid var(--theme-splitter-color); +} + +.command-bar { + height: 30px; +} + +html:not([dir="rtl"]) .command-bar { + padding: 8px 5px 10px 1px; +} + +html[dir="rtl"] .command-bar { + padding: 8px 1px 10px 5px; +} + +.command-bar > span { + cursor: pointer; + width: 16px; + height: 17px; + display: inline-block; + text-align: center; + transition: all 0.25s ease; +} + +:root.theme-dark .command-bar > span { + fill: var(--theme-body-color); +} + +:root.theme-dark .command-bar > span:hover { + fill: var(--theme-selection-color); +} + +html:not([dir="rtl"]) .command-bar > span { + margin-right: 0.7em; +} + +html[dir="rtl"] .command-bar > span { + margin-left: 0.7em; +} + +.command-bar > span.disabled { + opacity: 0.3; + cursor: default; +} + +html:not([dir="rtl"]) .command-bar .stepOut { + margin-right: 2em; +} + +html[dir="rtl"] .command-bar .stepOut { + margin-left: 2em; +} + +.command-bar .subSettings { + float: right; +} + +.pane { + color: var(--theme-body-color); +} + +.pane .pane-info { + font-style: italic; + text-align: center; + padding: 0.5em; + -moz-user-select: none; + user-select: none; +} + +.toggleBreakpoints.breakpoints-disabled path { + stroke: var(--theme-highlight-blue); +} + +span.pause-exceptions.uncaught { + stroke: var(--theme-highlight-purple); +} + +span.pause-exceptions.all { + stroke: var(--theme-highlight-blue); +} +.source-header { + border-bottom: 1px solid var(--theme-splitter-color); + height: 30px; + flex: 1; +} + +.source-header * { + -moz-user-select: none; + user-select: none; +} + +.source-tabs { + min-width: 50px; + max-width: calc(100% - 60px); + overflow: hidden; + float: left; +} + +.source-header .new-tab-btn { + width: 16px; + display: inline-block; + position: relative; + top: 4px; + margin: 4px; + line-height: 0; +} + +.source-header .new-tab-btn path { + fill: var(--theme-splitter-color); +} + +.source-header .new-tab-btn:hover path { + fill: var(--theme-comment); +} + +.source-tab { + background-color: var(--theme-toolbar-background-alt); + color: var(--theme-faded-tab-color); + border: 1px solid var(--theme-splitter-color); + border-top-left-radius: 2px; + border-top-right-radius: 2px; + height: 23px; + line-height: 20px; + display: inline-block; + border-bottom: none; + position: relative; + transition: all 0.25s ease; + min-width: 40px; + overflow: hidden; +} + +html:not([dir="rtl"]) .source-tab { + padding: 2px 20px 2px 12px; + margin: 6px 0 0 8px; +} + +html[dir="rtl"] .source-tab { + padding: 2px 12px 2px 20px; + margin: 6px 8px 0 0; +} + +.source-tab:hover { + background: var(--theme-toolbar-background); + cursor: pointer; +} + +.source-tab.active { + color: var(--theme-body-color); + background-color: var(--theme-body-background); +} + +.source-tab path { + fill: var(--theme-faded-tab-color); +} + +.source-tab.active path { + fill: var(--theme-body-color); +} + +.source-tab .close-btn { + position: absolute; + top: 3px; +} + +.source-tab .filename { + text-overflow: ellipsis; + overflow: hidden; +} + +html:not([dir="rtl"]) .source-tab .close-btn { + right: 4px; +} + +html[dir="rtl"] .source-tab .close-btn { + left: 4px; +} + +.source-tab .close { + display: none; +} + +.source-tab:hover .close { + display: block; +} +.dropdown { + background: var(--theme-body-background); + border: 1px solid var(--theme-splitter-color); + box-shadow: 0 4px 4px 0 var(--theme-search-overlays-semitransparent); + max-height: 300px; + position: absolute; + right: 8px; + top: 35px; + width: 150px; + z-index: 1000; +} + +.dropdown-button { + position: absolute; + right: 12px; + top: 5px; + font-size: 16px; + color: var(--theme-body-color); + cursor: pointer; +} + +.dropdown li { + transition: all 0.25s ease; + padding: 2px 10px 10px 5px; + overflow: hidden; + height: 30px; + text-overflow: ellipsis; +} + +.dropdown li:hover { + background-color: var(--theme-search-overlays-semitransparent); + cursor: pointer; +} + +.dropdown ul { + list-style: none; + line-height: 2em; + font-size: 1em; + margin: 0; + padding: 0; +} + +.dropdown-mask { + position: fixed; + width: 100%; + height: 100%; + background: transparent; + z-index: 999; + left: 0; + top: 0; +} + +/*# sourceMappingURL=styles.css.map*/
\ No newline at end of file diff --git a/devtools/client/debugger/new/test/mochitest/.eslintrc b/devtools/client/debugger/new/test/mochitest/.eslintrc new file mode 100644 index 000000000..017b921f8 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/.eslintrc @@ -0,0 +1,80 @@ +{ + "globals": { + "add_task": false, + "Assert": false, + "BrowserTestUtils": false, + "content": false, + "ContentTask": false, + "ContentTaskUtils": false, + "EventUtils": false, + "executeSoon": false, + "expectUncaughtException": false, + "export_assertions": false, + "extractJarToTmp": false, + "finish": false, + "getJar": false, + "getRootDirectory": false, + "getTestFilePath": false, + "gBrowser": false, + "gTestPath": false, + "info": false, + "is": false, + "isnot": false, + "ok": false, + "registerCleanupFunction": false, + "requestLongerTimeout": false, + "SimpleTest": false, + "SpecialPowers": false, + "TestUtils": false, + "thisTestLeaksUncaughtRejectionsAndShouldBeFixed": false, + "todo": false, + "todo_is": false, + "todo_isnot": false, + "waitForClipboard": false, + "waitForExplicitFinish": false, + "waitForFocus": false, + + // Globals introduced in debugger-specific head.js + "promise": false, + "BrowserToolboxProcess": false, + "OS": false, + "waitForNextDispatch": false, + "waitForDispatch": false, + "waitForThreadEvents": false, + "waitForState": false, + "waitForElement": false, + "waitForPaused": false, + "waitForSources": false, + "isPaused": false, + "assertPausedLocation": false, + "assertHighlightLocation": false, + "createDebuggerContext": false, + "initDebugger": false, + "invokeInTab": false, + "findSource": false, + "findElement": false, + "findElementWithSelector": false, + "findAllElements": false, + "openNewTabAndToolbox": false, + "selectSource": false, + "stepOver": false, + "stepIn": false, + "stepOut": false, + "resume": false, + "reload": false, + "navigate": false, + "removeBreakpoint": false, + "addBreakpoint": false, + "toggleCallStack": false, + "toggleScopes": false, + "isVisibleWithin": false, + "clickElement": false, + "rightClickElement": false, + "selectMenuItem": false, + "togglePauseOnExceptions": false, + "type": false, + "pressKey": false, + "EXAMPLE_URL": false, + "waitUntil": false + } +} diff --git a/devtools/client/debugger/new/test/mochitest/browser.ini b/devtools/client/debugger/new/test/mochitest/browser.ini new file mode 100644 index 000000000..d0e40a4a7 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser.ini @@ -0,0 +1,60 @@ +[DEFAULT] +tags = devtools +subsuite = devtools +skip-if = (os == 'linux' && debug && bits == 32) +support-files = + head.js + !/devtools/client/commandline/test/helpers.js + !/devtools/client/framework/test/shared-head.js + examples/bundle.js + examples/bundle.js.map + examples/doc-scripts.html + examples/doc-script-switching.html + examples/doc-exceptions.html + examples/doc-iframes.html + examples/doc-frames.html + examples/doc-debugger-statements.html + examples/doc-minified.html + examples/doc-sourcemaps.html + examples/doc-sourcemap-bogus.html + examples/doc-sources.html + examples/bogus-map.js + examples/entry.js + examples/exceptions.js + examples/long.js + examples/math.min.js + examples/nested/nested-source.js + examples/opts.js + examples/output.js + examples/simple1.js + examples/simple2.js + examples/frames.js + examples/script-switching-02.js + examples/script-switching-01.js + examples/times2.js + +[browser_dbg-breaking.js] +[browser_dbg-breaking-from-console.js] +[browser_dbg-breakpoints.js] +[browser_dbg-breakpoints-cond.js] +[browser_dbg-call-stack.js] +[browser_dbg-scopes.js] +[browser_dbg-chrome-create.js] +[browser_dbg-chrome-debugging.js] +[browser_dbg-console.js] +[browser_dbg-debugger-buttons.js] +[browser_dbg-editor-gutter.js] +[browser_dbg-editor-mode.js] +[browser_dbg-editor-select.js] +[browser_dbg-editor-highlight.js] +[browser_dbg-iframes.js] +[browser_dbg_keyboard-shortcuts.js] +[browser_dbg-pause-exceptions.js] +[browser_dbg-navigation.js] +[browser_dbg-pretty-print.js] +[browser_dbg-pretty-print-paused.js] +[browser_dbg-searching.js] +skip-if = true +[browser_dbg-sourcemaps.js] +[browser_dbg-sourcemaps-bogus.js] +[browser_dbg-sources.js]
\ No newline at end of file diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-breaking-from-console.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-breaking-from-console.js new file mode 100644 index 000000000..8005b518d --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-breaking-from-console.js @@ -0,0 +1,31 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests that `debugger` statements are hit before the debugger even +// initializes and it properly highlights the right location in the +// debugger. + +add_task(function* () { + const url = EXAMPLE_URL + "doc-script-switching.html"; + const toolbox = yield openNewTabAndToolbox(url, "webconsole"); + + // Type "debugger" into console + let jsterm = toolbox.getPanel("webconsole").hud.jsterm; + jsterm.execute("debugger"); + + // Wait for the debugger to be selected and make sure it's paused + yield new Promise((resolve) => { + toolbox.on("jsdebugger-selected", resolve); + }); + is(toolbox.threadClient.state, "paused"); + + // Create a dbg context + const dbg = createDebuggerContext(toolbox); + const { selectors: { getSelectedSource }, getState } = dbg; + + // Make sure the thread is paused in the right source and location + yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT"); + is(dbg.win.cm.getValue(), "debugger"); + const source = getSelectedSource(getState()).toJS(); + assertPausedLocation(dbg, source, 1); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-breaking.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-breaking.js new file mode 100644 index 000000000..8994897c4 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-breaking.js @@ -0,0 +1,32 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests the breakpoints are hit in various situations. + +add_task(function* () { + const dbg = yield initDebugger("doc-scripts.html"); + const { selectors: { getSelectedSource }, getState } = dbg; + + // Make sure we can set a top-level breakpoint and it will be hit on + // reload. + yield addBreakpoint(dbg, "scripts.html", 18); + reload(dbg); + yield waitForPaused(dbg); + assertPausedLocation(dbg, "scripts.html", 18); + yield resume(dbg); + + const paused = waitForPaused(dbg); + + // Create an eval script that pauses itself. + invokeInTab("doEval"); + + yield paused; + yield resume(dbg); + const source = getSelectedSource(getState()).toJS(); + ok(!source.url, "It is an eval source"); + + yield addBreakpoint(dbg, source, 5); + invokeInTab("evaledFunc"); + yield waitForPaused(dbg); + assertPausedLocation(dbg, source, 5); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints-cond.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints-cond.js new file mode 100644 index 000000000..b6f7fb021 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints-cond.js @@ -0,0 +1,50 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function findBreakpoint(dbg, url, line) { + const { selectors: { getBreakpoint }, getState } = dbg; + const source = findSource(dbg, url); + return getBreakpoint(getState(), { sourceId: source.id, line }); +} + +function setConditionalBreakpoint(dbg, index, condition) { + return Task.spawn(function* () { + rightClickElement(dbg, "gutter", index); + selectMenuItem(dbg, 2); + yield waitForElement(dbg, ".conditional-breakpoint-panel input"); + findElementWithSelector(dbg, ".conditional-breakpoint-panel input").focus(); + type(dbg, condition); + pressKey(dbg, "Enter"); + }); +} + +add_task(function* () { + const dbg = yield initDebugger("doc-scripts.html"); + yield selectSource(dbg, "simple2"); + + // Adding a conditional Breakpoint + yield setConditionalBreakpoint(dbg, 5, "1"); + yield waitForDispatch(dbg, "ADD_BREAKPOINT"); + let bp = findBreakpoint(dbg, "simple2", 5); + is(bp.condition, "1", "breakpoint is created with the condition"); + + // Editing a conditional Breakpoint + yield setConditionalBreakpoint(dbg, 5, "2"); + yield waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION"); + bp = findBreakpoint(dbg, "simple2", 5); + is(bp.condition, "21", "breakpoint is created with the condition"); + + // Removing a conditional breakpoint + clickElement(dbg, "gutter", 5); + yield waitForDispatch(dbg, "REMOVE_BREAKPOINT"); + bp = findBreakpoint(dbg, "simple2", 5); + is(bp, null, "breakpoint was removed"); + + // Adding a condition to a breakpoint + clickElement(dbg, "gutter", 5); + yield waitForDispatch(dbg, "ADD_BREAKPOINT"); + yield setConditionalBreakpoint(dbg, 5, "1"); + bp = findBreakpoint(dbg, "simple2", 5); + is(bp.condition, "1", "breakpoint is created with the condition"); +}); + diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints.js new file mode 100644 index 000000000..10bf44957 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints.js @@ -0,0 +1,101 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function toggleBreakpoint(dbg, index) { + const bp = findElement(dbg, "breakpointItem", index); + const input = bp.querySelector("input"); + input.click(); +} + +function removeBreakpoint(dbg, index) { + return Task.spawn(function* () { + const bp = findElement(dbg, "breakpointItem", index); + bp.querySelector(".close-btn").click(); + yield waitForDispatch(dbg, "REMOVE_BREAKPOINT"); + }); +} + +function disableBreakpoint(dbg, index) { + return Task.spawn(function* () { + toggleBreakpoint(dbg, index); + yield waitForDispatch(dbg, "REMOVE_BREAKPOINT"); + }); +} + +function enableBreakpoint(dbg, index) { + return Task.spawn(function* () { + toggleBreakpoint(dbg, index); + yield waitForDispatch(dbg, "ADD_BREAKPOINT"); + }); +} + +function toggleBreakpoints(dbg) { + return Task.spawn(function* () { + const btn = findElement(dbg, "toggleBreakpoints"); + btn.click(); + yield waitForDispatch(dbg, "TOGGLE_BREAKPOINTS"); + }); +} + +function findBreakpoint(dbg, url, line) { + const { selectors: { getBreakpoint }, getState } = dbg; + const source = findSource(dbg, url); + return getBreakpoint(getState(), { sourceId: source.id, line }); +} + +function findBreakpoints(dbg) { + const { selectors: { getBreakpoints }, getState } = dbg; + return getBreakpoints(getState()); +} + +add_task(function* () { + const dbg = yield initDebugger("doc-scripts.html"); + + // Create two breakpoints + yield selectSource(dbg, "simple2"); + yield addBreakpoint(dbg, "simple2", 3); + yield addBreakpoint(dbg, "simple2", 5); + + // Disable the first one + yield disableBreakpoint(dbg, 1); + let bp1 = findBreakpoint(dbg, "simple2", 3); + let bp2 = findBreakpoint(dbg, "simple2", 5); + is(bp1.disabled, true, "first breakpoint is disabled"); + is(bp2.disabled, false, "second breakpoint is enabled"); + + // Disable and Re-Enable the second one + yield disableBreakpoint(dbg, 2); + yield enableBreakpoint(dbg, 2); + bp2 = findBreakpoint(dbg, "simple2", 5); + is(bp2.disabled, false, "second breakpoint is enabled"); +}); + +// toggle all +add_task(function* () { + const dbg = yield initDebugger("doc-scripts.html"); + + // Create two breakpoints + yield selectSource(dbg, "simple2"); + yield addBreakpoint(dbg, "simple2", 3); + yield addBreakpoint(dbg, "simple2", 5); + + // Disable all of the breakpoints + yield toggleBreakpoints(dbg); + let bp1 = findBreakpoint(dbg, "simple2", 3); + let bp2 = findBreakpoint(dbg, "simple2", 5); + is(bp1.disabled, true, "first breakpoint is disabled"); + is(bp2.disabled, true, "second breakpoint is disabled"); + + // Enable all of the breakpoints + yield toggleBreakpoints(dbg); + bp1 = findBreakpoint(dbg, "simple2", 3); + bp2 = findBreakpoint(dbg, "simple2", 5); + is(bp1.disabled, false, "first breakpoint is enabled"); + is(bp2.disabled, false, "second breakpoint is enabled"); + + // Remove the breakpoints + yield removeBreakpoint(dbg, 1); + yield removeBreakpoint(dbg, 1); + const bps = findBreakpoints(dbg); + is(bps.size, 0, "breakpoints are removed"); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-call-stack.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-call-stack.js new file mode 100644 index 000000000..54a401eeb --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-call-stack.js @@ -0,0 +1,62 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// checks to see if the frame is selected and the title is correct +function isFrameSelected(dbg, index, title) { + const $frame = findElement(dbg, "frame", index); + const frame = dbg.selectors.getSelectedFrame(dbg.getState()); + + const elSelected = $frame.classList.contains("selected"); + const titleSelected = frame.displayName == title; + + return elSelected && titleSelected; +} + +function toggleButton(dbg) { + const callStackBody = findElement(dbg, "callStackBody"); + return callStackBody.querySelector(".show-more"); +} + +add_task(function* () { + const dbg = yield initDebugger("doc-script-switching.html"); + + toggleCallStack(dbg); + + const notPaused = findElement(dbg, "callStackBody").innerText; + is(notPaused, "Not Paused", "Not paused message is shown"); + + invokeInTab("firstCall"); + yield waitForPaused(dbg); + + ok(isFrameSelected(dbg, 1, "secondCall"), "the first frame is selected"); + + clickElement(dbg, "frame", 2); + ok(isFrameSelected(dbg, 2, "firstCall"), "the second frame is selected"); + + let button = toggleButton(dbg); + ok(!button, "toggle button shouldn't be there"); +}); + +add_task(function* () { + const dbg = yield initDebugger("doc-frames.html"); + + toggleCallStack(dbg); + + invokeInTab("startRecursion"); + yield waitForPaused(dbg); + + ok(isFrameSelected(dbg, 1, "recurseA"), "the first frame is selected"); + + // check to make sure that the toggle button isn't there + let button = toggleButton(dbg); + let frames = findAllElements(dbg, "frames"); + is(button.innerText, "Expand Rows", "toggle button should be expand"); + is(frames.length, 7, "There should be at most seven frames"); + + button.click(); + + button = toggleButton(dbg); + frames = findAllElements(dbg, "frames"); + is(button.innerText, "Collapse Rows", "toggle button should be collapse"); + is(frames.length, 22, "All of the frames should be shown"); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-chrome-create.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-chrome-create.js new file mode 100644 index 000000000..a2d88c064 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-chrome-create.js @@ -0,0 +1,72 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests that a chrome debugger can be created in a new process. + */ + +const { BrowserToolboxProcess } = Cu.import("resource://devtools/client/framework/ToolboxProcess.jsm", {}); +let gProcess = undefined; + +function initChromeDebugger() { + info("Initializing a chrome debugger process."); + return new Promise(resolve => { + BrowserToolboxProcess.init(onClose, (event, _process) => { + info("Browser toolbox process started successfully."); + resolve(_process); + }); + }); +} + +function onClose() { + ok(!gProcess._dbgProcess.isRunning, + "The remote debugger process isn't closed as it should be!"); + is(gProcess._dbgProcess.exitValue, (Services.appinfo.OS == "WINNT" ? 0 : 256), + "The remote debugger process didn't die cleanly."); + + info("process exit value: " + gProcess._dbgProcess.exitValue); + + info("profile path: " + gProcess._dbgProfilePath); + + finish(); +} + +registerCleanupFunction(function() { + Services.prefs.clearUserPref("devtools.debugger.remote-enabled"); + gProcess = null; +}); + +add_task(function* () { + // Windows XP and 8.1 test slaves are terribly slow at this test. + requestLongerTimeout(5); + Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true); + + gProcess = yield initChromeDebugger(); + + ok(gProcess._dbgProcess, + "The remote debugger process wasn't created properly!"); + ok(gProcess._dbgProcess.isRunning, + "The remote debugger process isn't running!"); + is(typeof gProcess._dbgProcess.pid, "number", + "The remote debugger process doesn't have a pid (?!)"); + + info("process location: " + gProcess._dbgProcess.location); + info("process pid: " + gProcess._dbgProcess.pid); + info("process name: " + gProcess._dbgProcess.processName); + info("process sig: " + gProcess._dbgProcess.processSignature); + + ok(gProcess._dbgProfilePath, + "The remote debugger profile wasn't created properly!"); + + is( + gProcess._dbgProfilePath, + OS.Path.join(OS.Constants.Path.profileDir, "chrome_debugger_profile"), + "The remote debugger profile isn't where we expect it!" + ); + + info("profile path: " + gProcess._dbgProfilePath); + + gProcess.close(); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-chrome-debugging.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-chrome-debugging.js new file mode 100644 index 000000000..3933c919b --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-chrome-debugging.js @@ -0,0 +1,88 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests that chrome debugging works. + */ + +var gClient, gThreadClient; +var gNewGlobal = promise.defer(); +var gNewChromeSource = promise.defer(); + +var { DevToolsLoader } = Cu.import("resource://devtools/shared/Loader.jsm", {}); +var customLoader = new DevToolsLoader(); +customLoader.invisibleToDebugger = true; +var { DebuggerServer } = customLoader.require("devtools/server/main"); +var { DebuggerClient } = require("devtools/shared/client/main"); + +function initDebuggerClient() { + if (!DebuggerServer.initialized) { + DebuggerServer.init(); + DebuggerServer.addBrowserActors(); + } + DebuggerServer.allowChromeProcess = true; + + let transport = DebuggerServer.connectPipe(); + return new DebuggerClient(transport); +} + +function attachThread(client, actor) { + return new Promise(resolve => { + client.attachTab(actor, (response, tabClient) => { + tabClient.attachThread(null, (r, threadClient) => { + resolve(threadClient); + }); + }); + }); +} + +function onNewGlobal() { + ok(true, "Received a new chrome global."); + gClient.removeListener("newGlobal", onNewGlobal); + gNewGlobal.resolve(); +} + +function onNewSource(event, packet) { + if (packet.source.url.startsWith("chrome:")) { + ok(true, "Received a new chrome source: " + packet.source.url); + gThreadClient.removeListener("newSource", onNewSource); + gNewChromeSource.resolve(); + } +} + +function resumeAndCloseConnection() { + return new Promise(resolve => { + gThreadClient.resume(() => resolve(gClient.close())); + }); +} + +registerCleanupFunction(function() { + gClient = null; + gThreadClient = null; + gNewGlobal = null; + gNewChromeSource = null; + + customLoader = null; + DebuggerServer = null; +}); + +add_task(function* () { + gClient = initDebuggerClient(); + + const [type] = yield gClient.connect(); + is(type, "browser", "Root actor should identify itself as a browser."); + + const response = yield gClient.getProcess(); + let actor = response.form.actor; + gThreadClient = yield attachThread(gClient, actor); + gBrowser.selectedTab = gBrowser.addTab("about:mozilla"); + + // listen for a new source and global + gThreadClient.addListener("newSource", onNewSource); + gClient.addListener("newGlobal", onNewGlobal); + yield promise.all([ gNewGlobal.promise, gNewChromeSource.promise ]); + + yield resumeAndCloseConnection(); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-console.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-console.js new file mode 100644 index 000000000..c57103663 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-console.js @@ -0,0 +1,34 @@ +// Return a promise with a reference to jsterm, opening the split +// console if necessary. This cleans up the split console pref so +// it won't pollute other tests. +function getSplitConsole(dbg) { + const { toolbox, win } = dbg; + + registerCleanupFunction(() => { + Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled"); + }); + + if (!win) { + win = toolbox.win; + } + + if (!toolbox.splitConsole) { + EventUtils.synthesizeKey("VK_ESCAPE", {}, win); + } + + return new Promise(resolve => { + toolbox.getPanelWhenReady("webconsole").then(() => { + ok(toolbox.splitConsole, "Split console is shown."); + let jsterm = toolbox.getPanel("webconsole").hud.jsterm; + resolve(jsterm); + }); + }); +} + +add_task(function* () { + Services.prefs.setBoolPref("devtools.toolbox.splitconsoleEnabled", true); + const dbg = yield initDebugger("doc-script-switching.html"); + + yield getSplitConsole(dbg); + ok(dbg.toolbox.splitConsole, "Split console is shown."); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-debugger-buttons.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-debugger-buttons.js new file mode 100644 index 000000000..0094650bc --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-debugger-buttons.js @@ -0,0 +1,54 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function clickStepOver(dbg) { + clickElement(dbg, "stepOver"); + return waitForPaused(dbg); +} + +function clickStepIn(dbg) { + clickElement(dbg, "stepIn"); + return waitForPaused(dbg); +} + +function clickStepOut(dbg) { + clickElement(dbg, "stepOut"); + return waitForPaused(dbg); +} + +/** + * Test debugger buttons + * 1. resume + * 2. stepOver + * 3. stepIn + * 4. stepOver to the end of a function + * 5. stepUp at the end of a function + */ +add_task(function* () { + const dbg = yield initDebugger("doc-debugger-statements.html"); + + yield reload(dbg); + yield waitForPaused(dbg); + assertPausedLocation(dbg, "debugger-statements.html", 8); + + // resume + clickElement(dbg, "resume"); + yield waitForPaused(dbg); + assertPausedLocation(dbg, "debugger-statements.html", 12); + + // step over + yield clickStepOver(dbg); + assertPausedLocation(dbg, "debugger-statements.html", 13); + + // step into + yield clickStepIn(dbg); + assertPausedLocation(dbg, "debugger-statements.html", 18); + + // step over + yield clickStepOver(dbg); + assertPausedLocation(dbg, "debugger-statements.html", 20); + + // step out + yield clickStepOut(dbg); + assertPausedLocation(dbg, "debugger-statements.html", 20); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-gutter.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-gutter.js new file mode 100644 index 000000000..12a771c31 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-gutter.js @@ -0,0 +1,64 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests the breakpoint gutter and making sure breakpoint icons exist +// correctly + +// Utilities for interacting with the editor +function clickGutter(dbg, line) { + clickElement(dbg, "gutter", line); +} + +function getLineEl(dbg, line) { + const lines = dbg.win.document.querySelectorAll(".CodeMirror-code > div"); + return lines[line - 1]; +} + +function assertEditorBreakpoint(dbg, line, shouldExist) { + const exists = !!getLineEl(dbg, line).querySelector(".new-breakpoint"); + ok(exists === shouldExist, + "Breakpoint " + (shouldExist ? "exists" : "does not exist") + + " on line " + line); +} + +add_task(function* () { + const dbg = yield initDebugger("doc-scripts.html"); + const { selectors: { getBreakpoints, getBreakpoint }, getState } = dbg; + const source = findSource(dbg, "simple1.js"); + + yield selectSource(dbg, source.url); + + // Make sure that clicking the gutter creates a breakpoint icon. + clickGutter(dbg, 4); + yield waitForDispatch(dbg, "ADD_BREAKPOINT"); + is(getBreakpoints(getState()).size, 1, "One breakpoint exists"); + assertEditorBreakpoint(dbg, 4, true); + + // Make sure clicking at the same place removes the icon. + clickGutter(dbg, 4); + yield waitForDispatch(dbg, "REMOVE_BREAKPOINT"); + is(getBreakpoints(getState()).size, 0, "No breakpoints exist"); + assertEditorBreakpoint(dbg, 4, false); + + // Test that a breakpoint icon slides down to the correct line. + clickGutter(dbg, 2); + yield waitForDispatch(dbg, "ADD_BREAKPOINT"); + is(getBreakpoints(getState()).size, 1, "One breakpoint exists"); + ok(getBreakpoint(getState(), { sourceId: source.id, line: 4 }), + "Breakpoint has correct line"); + assertEditorBreakpoint(dbg, 2, false); + assertEditorBreakpoint(dbg, 4, true); + + // Do the same sliding and make sure it works if there's already a + // breakpoint. + clickGutter(dbg, 2); + yield waitForDispatch(dbg, "ADD_BREAKPOINT"); + is(getBreakpoints(getState()).size, 1, "One breakpoint exists"); + assertEditorBreakpoint(dbg, 2, false); + assertEditorBreakpoint(dbg, 4, true); + + clickGutter(dbg, 4); + yield waitForDispatch(dbg, "REMOVE_BREAKPOINT"); + is(getBreakpoints(getState()).size, 0, "No breakpoints exist"); + assertEditorBreakpoint(dbg, 4, false); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-highlight.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-highlight.js new file mode 100644 index 000000000..d7892e629 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-highlight.js @@ -0,0 +1,46 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests that the editor will always highight the right line, no +// matter if the source text doesn't exist yet or even if the source +// doesn't exist. + +add_task(function* () { + const dbg = yield initDebugger("doc-scripts.html"); + const { selectors: { getSourceText }, getState } = dbg; + const sourceUrl = EXAMPLE_URL + "long.js"; + + // The source itself doesn't even exist yet, and using + // `selectSourceURL` will set a pending request to load this source + // and highlight a specific line. + dbg.actions.selectSourceURL(sourceUrl, { line: 66 }); + + // Wait for the source text to load and make sure we're in the right + // place. + yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT"); + assertHighlightLocation(dbg, "long.js", 66); + + // Jump to line 16 and make sure the editor scrolled. + yield selectSource(dbg, "long.js", 16); + assertHighlightLocation(dbg, "long.js", 16); + + // Make sure only one line is ever highlighted and the flash + // animation is cancelled on old lines. + yield selectSource(dbg, "long.js", 17); + yield selectSource(dbg, "long.js", 18); + assertHighlightLocation(dbg, "long.js", 18); + is(findAllElements(dbg, "highlightLine").length, 1, + "Only 1 line is highlighted"); + + // Test jumping to a line in a source that exists but hasn't been + // loaded yet. + selectSource(dbg, "simple1.js", 6); + + // Make sure the source is in the loading state, wait for it to be + // fully loaded, and check the highlighted line. + const simple1 = findSource(dbg, "simple1.js"); + ok(getSourceText(getState(), simple1.id).get("loading")); + yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT"); + ok(getSourceText(getState(), simple1.id).get("text")); + assertHighlightLocation(dbg, "simple1.js", 6); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-mode.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-mode.js new file mode 100644 index 000000000..2a23aa09f --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-mode.js @@ -0,0 +1,14 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests that the editor sets the correct mode for different file +// types +add_task(function* () { + const dbg = yield initDebugger("doc-scripts.html"); + + yield selectSource(dbg, "simple1.js"); + is(dbg.win.cm.getOption("mode").name, "javascript", "Mode is correct"); + + yield selectSource(dbg, "doc-scripts.html"); + is(dbg.win.cm.getOption("mode").name, "htmlmixed", "Mode is correct"); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-select.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-select.js new file mode 100644 index 000000000..8b954f899 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-editor-select.js @@ -0,0 +1,54 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests that the editor highlights the correct location when the +// debugger pauses + +// checks to see if the first breakpoint is visible +function isElementVisible(dbg, elementName) { + const bpLine = findElement(dbg, elementName); + const cm = findElement(dbg, "codeMirror"); + return bpLine && isVisibleWithin(cm, bpLine); +} + +add_task(function* () { + // This test runs too slowly on linux debug. I'd like to figure out + // which is the slowest part of this and make it run faster, but to + // fix a frequent failure allow a longer timeout. + requestLongerTimeout(2); + + const dbg = yield initDebugger("doc-scripts.html"); + const { selectors: { getSelectedSource }, getState } = dbg; + const simple1 = findSource(dbg, "simple1.js"); + const simple2 = findSource(dbg, "simple2.js"); + + // Set the initial breakpoint. + yield addBreakpoint(dbg, simple1, 4); + ok(!getSelectedSource(getState()), "No selected source"); + + // Call the function that we set a breakpoint in. + invokeInTab("main"); + yield waitForPaused(dbg); + assertPausedLocation(dbg, simple1, 4); + + // Step through to another file and make sure it's paused in the + // right place. + yield stepIn(dbg); + assertPausedLocation(dbg, simple2, 2); + + // Step back out to the initial file. + yield stepOut(dbg); + yield stepOut(dbg); + assertPausedLocation(dbg, simple1, 5); + yield resume(dbg); + + // Make sure that we can set a breakpoint on a line out of the + // viewport, and that pausing there scrolls the editor to it. + let longSrc = findSource(dbg, "long.js"); + yield addBreakpoint(dbg, longSrc, 66); + + invokeInTab("testModel"); + yield waitForPaused(dbg); + assertPausedLocation(dbg, longSrc, 66); + ok(isElementVisible(dbg, "breakpoint"), "Breakpoint is visible"); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-iframes.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-iframes.js new file mode 100644 index 000000000..9039da1be --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-iframes.js @@ -0,0 +1,26 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test debugging a page with iframes + * 1. pause in the main thread + * 2. pause in the iframe + */ +add_task(function* () { + const dbg = yield initDebugger("doc-iframes.html"); + + // test pausing in the main thread + yield reload(dbg); + yield waitForPaused(dbg); + assertPausedLocation(dbg, "iframes.html", 8); + + // test pausing in the iframe + yield resume(dbg); + yield waitForPaused(dbg); + assertPausedLocation(dbg, "debugger-statements.html", 8); + + // test pausing in the iframe + yield resume(dbg); + yield waitForPaused(dbg); + assertPausedLocation(dbg, "debugger-statements.html", 12); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-navigation.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-navigation.js new file mode 100644 index 000000000..381b6b7fd --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-navigation.js @@ -0,0 +1,47 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function countSources(dbg) { + const sources = dbg.selectors.getSources(dbg.getState()); + return sources.size; +} + +/** + * Test navigating + * navigating while paused will reset the pause state and sources + */ +add_task(function* () { + const dbg = yield initDebugger("doc-script-switching.html"); + const { selectors: { getSelectedSource, getPause }, getState } = dbg; + + invokeInTab("firstCall"); + yield waitForPaused(dbg); + + yield navigate(dbg, "doc-scripts.html", "simple1.js"); + yield addBreakpoint(dbg, "simple1.js", 4); + invokeInTab("main"); + yield waitForPaused(dbg); + assertPausedLocation(dbg, "simple1.js", 4); + is(countSources(dbg), 4, "4 sources are loaded."); + + yield navigate(dbg, "about:blank"); + yield waitForDispatch(dbg, "NAVIGATE"); + is(countSources(dbg), 0, "0 sources are loaded."); + ok(!getPause(getState()), "No pause state exists"); + + yield navigate(dbg, + "doc-scripts.html", + "simple1.js", + "simple2.js", + "long.js", + "scripts.html" + ); + + is(countSources(dbg), 4, "4 sources are loaded."); + + // Test that the current select source persists across reloads + yield selectSource(dbg, "long.js"); + yield reload(dbg, "long.js"); + ok(getSelectedSource(getState()).get("url").includes("long.js"), + "Selected source is long.js"); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-pause-exceptions.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-pause-exceptions.js new file mode 100644 index 000000000..133316b54 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-pause-exceptions.js @@ -0,0 +1,46 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function uncaughtException() { + return invokeInTab("uncaughtException").catch(() => {}); +} + +function caughtException() { + return invokeInTab("caughtException"); +} + +/* + Tests Pausing on exception + 1. skip an uncaught exception + 2. pause on an uncaught exception + 3. pause on a caught error + 4. skip a caught error +*/ +add_task(function* () { + const dbg = yield initDebugger("doc-exceptions.html"); + + // test skipping an uncaught exception + yield togglePauseOnExceptions(dbg, false, false); + yield uncaughtException(); + ok(!isPaused(dbg)); + + // Test pausing on an uncaught exception + yield togglePauseOnExceptions(dbg, true, false); + uncaughtException(); + yield waitForPaused(dbg); + assertPausedLocation(dbg, "exceptions.js", 2); + yield resume(dbg); + + // Test pausing on a caught Error + caughtException(); + yield waitForPaused(dbg); + assertPausedLocation(dbg, "exceptions.js", 15); + yield resume(dbg); + + // Test skipping a caught error + yield togglePauseOnExceptions(dbg, true, true); + caughtException(); + yield waitForPaused(dbg); + assertPausedLocation(dbg, "exceptions.js", 17); + yield resume(dbg); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print-paused.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print-paused.js new file mode 100644 index 000000000..73919e65e --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print-paused.js @@ -0,0 +1,22 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests pretty-printing a source that is currently paused. + +add_task(function* () { + const dbg = yield initDebugger("doc-minified.html"); + + yield selectSource(dbg, "math.min.js"); + yield addBreakpoint(dbg, "math.min.js", 2); + + invokeInTab("arithmetic"); + yield waitForPaused(dbg); + assertPausedLocation(dbg, "math.min.js", 2); + + clickElement(dbg, "prettyPrintButton"); + yield waitForDispatch(dbg, "TOGGLE_PRETTY_PRINT"); + + assertPausedLocation(dbg, "math.min.js:formatted", 18); + + yield resume(dbg); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print.js new file mode 100644 index 000000000..260bfef38 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print.js @@ -0,0 +1,31 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests basic pretty-printing functionality. + +add_task(function* () { + const dbg = yield initDebugger("doc-minified.html"); + + yield selectSource(dbg, "math.min.js"); + clickElement(dbg, "prettyPrintButton"); + yield waitForDispatch(dbg, "TOGGLE_PRETTY_PRINT"); + + const ppSrc = findSource(dbg, "math.min.js:formatted"); + ok(ppSrc, "Pretty-printed source exists"); + + yield addBreakpoint(dbg, ppSrc, 18); + + invokeInTab("arithmetic"); + yield waitForPaused(dbg); + assertPausedLocation(dbg, ppSrc, 18); + yield stepOver(dbg); + assertPausedLocation(dbg, ppSrc, 27); + yield resume(dbg); + + // The pretty-print button should go away in the pretty-printed + // source. + ok(!findElement(dbg, "sourceFooter"), "Footer is hidden"); + + yield selectSource(dbg, "math.min.js"); + ok(findElement(dbg, "sourceFooter"), "Footer is hidden"); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-scopes.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-scopes.js new file mode 100644 index 000000000..adb99be84 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-scopes.js @@ -0,0 +1,27 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function toggleNode(dbg, index) { + clickElement(dbg, "scopeNode", index); +} + +function getLabel(dbg, index) { + return findElement(dbg, "scopeNode", index).innerText; +} + +add_task(function* () { + const dbg = yield initDebugger("doc-script-switching.html"); + + toggleScopes(dbg); + + invokeInTab("firstCall"); + yield waitForPaused(dbg); + + toggleNode(dbg, 1); + toggleNode(dbg, 2); + + yield waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES"); + + is(getLabel(dbg, 1), "secondCall"); + is(getLabel(dbg, 2), "<this>"); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-searching.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-searching.js new file mode 100644 index 000000000..dd25e2b54 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-searching.js @@ -0,0 +1,28 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Testing source search +add_task(function* () { + const dbg = yield initDebugger("doc-script-switching.html"); + + pressKey(dbg, "sourceSearch"); + yield waitForElement(dbg, "input"); + findElementWithSelector(dbg, "input").focus(); + type(dbg, "sw"); + pressKey(dbg, "Enter"); + + yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT"); + let source = dbg.selectors.getSelectedSource(dbg.getState()); + ok(source.get("url").match(/switching-01/), "first source is selected"); + + // 2. arrow keys and check to see if source is selected + pressKey(dbg, "sourceSearch"); + findElementWithSelector(dbg, "input").focus(); + type(dbg, "sw"); + pressKey(dbg, "Down"); + pressKey(dbg, "Enter"); + + yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT"); + source = dbg.selectors.getSelectedSource(dbg.getState()); + ok(source.get("url").match(/switching-02/), "second source is selected"); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps-bogus.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps-bogus.js new file mode 100644 index 000000000..e8c6070fc --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps-bogus.js @@ -0,0 +1,23 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that an error while loading a sourcemap does not break +// debugging. + +add_task(function* () { + const dbg = yield initDebugger("doc-sourcemap-bogus.html"); + const { selectors: { getSources }, getState } = dbg; + + yield selectSource(dbg, "bogus-map.js"); + + // We should still be able to set breakpoints and pause in the + // generated source. + yield addBreakpoint(dbg, "bogus-map.js", 4); + invokeInTab("runCode"); + yield waitForPaused(dbg); + assertPausedLocation(dbg, "bogus-map.js", 4); + + // Make sure that only the single generated source exists. The + // sourcemap failed to download. + is(getSources(getState()).size, 1, "Only 1 source exists"); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps.js new file mode 100644 index 000000000..30fd7b70c --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps.js @@ -0,0 +1,44 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests loading sourcemapped sources, setting breakpoints, and +// stepping in them. + +add_task(function* () { + const dbg = yield initDebugger("doc-sourcemaps.html"); + const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg; + + yield waitForSources(dbg, "entry.js", "output.js", "times2.js", "opts.js"); + ok(true, "Original sources exist"); + const entrySrc = findSource(dbg, "entry.js"); + + yield selectSource(dbg, entrySrc); + ok(dbg.win.cm.getValue().includes("window.keepMeAlive"), + "Original source text loaded correctly"); + + // Test that breakpoint sliding is not attempted. The breakpoint + // should not move anywhere. + yield addBreakpoint(dbg, entrySrc, 13); + is(getBreakpoints(getState()).size, 1, "One breakpoint exists"); + ok(getBreakpoint(getState(), { sourceId: entrySrc.id, line: 13 }), + "Breakpoint has correct line"); + + // Test breaking on a breakpoint + yield addBreakpoint(dbg, "entry.js", 15); + is(getBreakpoints(getState()).size, 2, "Two breakpoints exist"); + ok(getBreakpoint(getState(), { sourceId: entrySrc.id, line: 15 }), + "Breakpoint has correct line"); + + invokeInTab("keepMeAlive"); + yield waitForPaused(dbg); + assertPausedLocation(dbg, entrySrc, 15); + + yield stepIn(dbg); + assertPausedLocation(dbg, "times2.js", 2); + yield stepOver(dbg); + assertPausedLocation(dbg, "times2.js", 3); + + yield stepOut(dbg); + yield stepOut(dbg); + assertPausedLocation(dbg, "entry.js", 16); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-sources.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-sources.js new file mode 100644 index 000000000..64b7f56ae --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sources.js @@ -0,0 +1,58 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests that the source tree works. + +function* waitForSourceCount(dbg, i) { + // We are forced to wait until the DOM nodes appear because the + // source tree batches its rendering. + yield waitUntil(() => { + return findAllElements(dbg, "sourceNodes").length === i; + }); +} + +add_task(function* () { + const dbg = yield initDebugger("doc-sources.html"); + const { selectors: { getSelectedSource }, getState } = dbg; + + // Expand nodes and make sure more sources appear. + is(findAllElements(dbg, "sourceNodes").length, 2); + + clickElement(dbg, "sourceArrow", 2); + is(findAllElements(dbg, "sourceNodes").length, 7); + + clickElement(dbg, "sourceArrow", 3); + is(findAllElements(dbg, "sourceNodes").length, 8); + + // Select a source. + ok(!findElementWithSelector(dbg, ".sources-list .focused"), + "Source is not focused"); + const selected = waitForDispatch(dbg, "SELECT_SOURCE"); + clickElement(dbg, "sourceNode", 4); + yield selected; + ok(findElementWithSelector(dbg, ".sources-list .focused"), + "Source is focused"); + ok(getSelectedSource(getState()).get("url").includes("nested-source.js"), + "The right source is selected"); + + // Make sure new sources appear in the list. + ContentTask.spawn(gBrowser.selectedBrowser, null, function() { + const script = content.document.createElement("script"); + script.src = "math.min.js"; + content.document.body.appendChild(script); + }); + + yield waitForSourceCount(dbg, 9); + is(findElement(dbg, "sourceNode", 7).querySelector("span").innerText, + "math.min.js", + "The dynamic script exists"); + + // Make sure named eval sources appear in the list. + ContentTask.spawn(gBrowser.selectedBrowser, null, function() { + content.eval("window.evaledFunc = function() {} //# sourceURL=evaled.js"); + }); + yield waitForSourceCount(dbg, 11); + is(findElement(dbg, "sourceNode", 2).querySelector("span").innerText, + "evaled.js", + "The eval script exists"); +}); diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg_keyboard-shortcuts.js b/devtools/client/debugger/new/test/mochitest/browser_dbg_keyboard-shortcuts.js new file mode 100644 index 000000000..0d7e572ef --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg_keyboard-shortcuts.js @@ -0,0 +1,46 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test keyboard shortcuts. + */ + +function pressResume(dbg) { + pressKey(dbg, "resumeKey"); + return waitForPaused(dbg); +} + +function pressStepOver(dbg) { + pressKey(dbg, "stepOverKey"); + return waitForPaused(dbg); +} + +function pressStepIn(dbg) { + pressKey(dbg, "stepInKey"); + return waitForPaused(dbg); +} + +function pressStepOut(dbg) { + pressKey(dbg, "stepOutKey"); + return waitForPaused(dbg); +} + +add_task(function*() { + const dbg = yield initDebugger("doc-debugger-statements.html"); + + yield reload(dbg); + yield waitForPaused(dbg); + assertPausedLocation(dbg, "debugger-statements.html", 8); + + yield pressResume(dbg); + assertPausedLocation(dbg, "debugger-statements.html", 12); + + yield pressStepIn(dbg); + assertPausedLocation(dbg, "debugger-statements.html", 13); + + yield pressStepOut(dbg); + assertPausedLocation(dbg, "debugger-statements.html", 14); + + yield pressStepOver(dbg); + assertPausedLocation(dbg, "debugger-statements.html", 9); +}); diff --git a/devtools/client/debugger/new/test/mochitest/examples/README.md b/devtools/client/debugger/new/test/mochitest/examples/README.md new file mode 100644 index 000000000..1be42619d --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/README.md @@ -0,0 +1,7 @@ +### Test Examples + +##### Pages +* **doc_script-switching-01** - includes two scripts that reference each other. The second function has a debugger. +* **doc-scripts** - includes three sources, a long source and two sources that reference each other. +* **doc-iframes** - includes an iframe with the debugger statements source. +* **debugger-statements** - inline script with functions for testing stepping. diff --git a/devtools/client/debugger/new/test/mochitest/examples/bogus-map.js b/devtools/client/debugger/new/test/mochitest/examples/bogus-map.js new file mode 100644 index 000000000..20b5bbf7e --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/bogus-map.js @@ -0,0 +1,8 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +function runCode(){ + var a=1; + a=a*2; + return a; +} +//# sourceMappingURL=bogus.map diff --git a/devtools/client/debugger/new/test/mochitest/examples/bundle.js b/devtools/client/debugger/new/test/mochitest/examples/bundle.js new file mode 100644 index 000000000..a03ace934 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/bundle.js @@ -0,0 +1,96 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; +/******/ +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + const times2 = __webpack_require__(1); + const { output } = __webpack_require__(2); + const opts = __webpack_require__(3); + + output(times2(1)); + output(times2(2)); + + if(opts.extra) { + output(times2(3)); + } + + window.keepMeAlive = function() { + // This function exists to make sure this script is never garbage + // collected. It is also callable from tests. + return times2(4); + } + + +/***/ }, +/* 1 */ +/***/ function(module, exports) { + + module.exports = function(x) { + return x * 2; + } + + +/***/ }, +/* 2 */ +/***/ function(module, exports) { + + function output(str) { + console.log(str); + } + + module.exports = { output }; + + +/***/ }, +/* 3 */ +/***/ function(module, exports) { + + module.exports = { + extra: true + }; + + +/***/ } +/******/ ]); +//# sourceMappingURL=bundle.js.map
\ No newline at end of file diff --git a/devtools/client/debugger/new/test/mochitest/examples/bundle.js.map b/devtools/client/debugger/new/test/mochitest/examples/bundle.js.map new file mode 100644 index 000000000..ed7336ad1 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/bundle.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/bootstrap 4ef8c7ec7c1df790781e","webpack:///./entry.js","webpack:///./times2.js","webpack:///./output.js","webpack:///./opts.js"],"names":[],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uBAAe;AACf;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;ACtCA;AACA,QAAO,SAAS;AAChB;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;;;;;ACfA;AACA;AACA;;;;;;;ACFA;AACA;AACA;;AAEA,mBAAkB;;;;;;;ACJlB;AACA;AACA","file":"bundle.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 4ef8c7ec7c1df790781e","const times2 = require(\"./times2\");\nconst { output } = require(\"./output\");\nconst opts = require(\"./opts\");\n\noutput(times2(1));\noutput(times2(2));\n\nif(opts.extra) {\n output(times2(3));\n}\n\nwindow.keepMeAlive = function() {\n // This function exists to make sure this script is never garbage\n // collected. It is also callable from tests.\n return times2(4);\n}\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./entry.js\n// module id = 0\n// module chunks = 0","module.exports = function(x) {\n return x * 2;\n}\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./times2.js\n// module id = 1\n// module chunks = 0","function output(str) {\n console.log(str);\n}\n\nmodule.exports = { output };\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./output.js\n// module id = 2\n// module chunks = 0","module.exports = {\n extra: true\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./opts.js\n// module id = 3\n// module chunks = 0"],"sourceRoot":""}
\ No newline at end of file diff --git a/devtools/client/debugger/new/test/mochitest/examples/doc-debugger-statements.html b/devtools/client/debugger/new/test/mochitest/examples/doc-debugger-statements.html new file mode 100644 index 000000000..967619d31 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/doc-debugger-statements.html @@ -0,0 +1,27 @@ +<html> + <head> + <title>Debugger Statements</title> + </head> + + <body> + <script> + debugger; + test(); + + function test() { + debugger; + stepIntoMe(); + } + + function stepIntoMe() { + // step in + stepOverMe(); + // step out + } + + function stepOverMe() { + } + </script> + </body> + +</html> diff --git a/devtools/client/debugger/new/test/mochitest/examples/doc-exceptions.html b/devtools/client/debugger/new/test/mochitest/examples/doc-exceptions.html new file mode 100644 index 000000000..5ca65b755 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/doc-exceptions.html @@ -0,0 +1,7 @@ +<html> + <head> + <title>Debugger test page</title> + <script type="text/javascript" src="exceptions.js"></script> + </head> + <body></body> +</html> diff --git a/devtools/client/debugger/new/test/mochitest/examples/doc-frames.html b/devtools/client/debugger/new/test/mochitest/examples/doc-frames.html new file mode 100644 index 000000000..408c55b28 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/doc-frames.html @@ -0,0 +1,17 @@ +<html> + <head> + <title>Frames</title> + </head> + + <body> + <script> + debugger; + // This inline script allows this HTML page to show up as a + // source. It also needs to introduce a new global variable so + // it's not immediately garbage collected. + function inline_script() { var x = 5; } + </script> + <script type="text/javascript" src="frames.js"></script> + </body> + +</html> diff --git a/devtools/client/debugger/new/test/mochitest/examples/doc-iframes.html b/devtools/client/debugger/new/test/mochitest/examples/doc-iframes.html new file mode 100644 index 000000000..26446eaa1 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/doc-iframes.html @@ -0,0 +1,17 @@ +<html> + <head> + <title>Iframe</title> + </head> + + <body> + <script> + debugger; + // This inline script allows this HTML page to show up as a + // source. It also needs to introduce a new global variable so + // it's not immediately garbage collected. + function inline_script() { var x = 5; } + </script> + <iframe src="doc-debugger-statements.html"></iframe> + </body> + +</html> diff --git a/devtools/client/debugger/new/test/mochitest/examples/doc-minified.html b/devtools/client/debugger/new/test/mochitest/examples/doc-minified.html new file mode 100644 index 000000000..4c95a9b4a --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/doc-minified.html @@ -0,0 +1,14 @@ +<!-- Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ --> +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Debugger test page</title> + </head> + + <body> + <script src="math.min.js"></script> + </body> +</html> diff --git a/devtools/client/debugger/new/test/mochitest/examples/doc-script-switching.html b/devtools/client/debugger/new/test/mochitest/examples/doc-script-switching.html new file mode 100644 index 000000000..3c71497c2 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/doc-script-switching.html @@ -0,0 +1,18 @@ +<!-- Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ --> +<!doctype html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Debugger test page</title> + </head> + + <body> + <button onclick="firstCall()">Click me!</button> + + <script type="text/javascript" src="script-switching-01.js"></script> + <script type="text/javascript" src="script-switching-02.js"></script> + </body> + +</html> diff --git a/devtools/client/debugger/new/test/mochitest/examples/doc-scripts.html b/devtools/client/debugger/new/test/mochitest/examples/doc-scripts.html new file mode 100644 index 000000000..212b4802f --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/doc-scripts.html @@ -0,0 +1,21 @@ +<!-- Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"/> + <title>Debugger test page</title> + </head> + + <body> + <script src="simple1.js"></script> + <script src="simple2.js"></script> + <script src="long.js"></script> + <script> + // This inline script allows this HTML page to show up as a + // source. It also needs to introduce a new global variable so + // it's not immediately garbage collected. + function inline_script() { var x = 5; } + </script> + </body> +</html> diff --git a/devtools/client/debugger/new/test/mochitest/examples/doc-sourcemap-bogus.html b/devtools/client/debugger/new/test/mochitest/examples/doc-sourcemap-bogus.html new file mode 100644 index 000000000..da448a2cd --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/doc-sourcemap-bogus.html @@ -0,0 +1,13 @@ +<!-- Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"/> + <title>Debugger test page</title> + </head> + + <body> + <script src="bogus-map.js"></script> + </body> +</html> diff --git a/devtools/client/debugger/new/test/mochitest/examples/doc-sourcemaps.html b/devtools/client/debugger/new/test/mochitest/examples/doc-sourcemaps.html new file mode 100644 index 000000000..10f5da047 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/doc-sourcemaps.html @@ -0,0 +1,13 @@ +<!-- Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"/> + <title>Debugger test page</title> + </head> + + <body> + <script src="bundle.js"></script> + </body> +</html> diff --git a/devtools/client/debugger/new/test/mochitest/examples/doc-sources.html b/devtools/client/debugger/new/test/mochitest/examples/doc-sources.html new file mode 100644 index 000000000..14cc86701 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/doc-sources.html @@ -0,0 +1,23 @@ +<!-- Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"/> + <title>Debugger test page</title> + </head> + + <body> + <script src="simple1.js"></script> + <script src="simple2.js"></script> + <script src="long.js"></script> + <script> + // This inline script allows this HTML page to show up as a + // source. It also needs to introduce a new global variable so + // it's not immediately garbage collected. + function inline_script() { var x = 5; } + </script> + <script src="nested/nested-source.js"></script> + <script src="nested/deeper/deeper-source.js"></script> + </body> +</html> diff --git a/devtools/client/debugger/new/test/mochitest/examples/entry.js b/devtools/client/debugger/new/test/mochitest/examples/entry.js new file mode 100644 index 000000000..d397a966b --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/entry.js @@ -0,0 +1,16 @@ +const times2 = require("./times2"); +const { output } = require("./output"); +const opts = require("./opts"); + +output(times2(1)); +output(times2(2)); + +if(opts.extra) { + output(times2(3)); +} + +window.keepMeAlive = function() { + // This function exists to make sure this script is never garbage + // collected. It is also callable from tests. + return times2(4); +} diff --git a/devtools/client/debugger/new/test/mochitest/examples/exceptions.js b/devtools/client/debugger/new/test/mochitest/examples/exceptions.js new file mode 100644 index 000000000..9523f00ca --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/exceptions.js @@ -0,0 +1,19 @@ +function uncaughtException() { + throw "unreachable" +} + +function caughtError() { + try { + throw new Error("error"); + } catch (e) { + debugger; + } +} + +function caughtException() { + try { + throw "reachable"; + } catch (e) { + debugger; + } +} diff --git a/devtools/client/debugger/new/test/mochitest/examples/frames.js b/devtools/client/debugger/new/test/mochitest/examples/frames.js new file mode 100644 index 000000000..0f031582e --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/frames.js @@ -0,0 +1,24 @@ +function recurseA(i) { + if (i == 20) { + debugger; + return; + } + + // down into the rabbit hole we go + return (i % 2) ? recurseA(++i) : recurseB(++i); +} + +function recurseB(i) { + if (i == 20) { + debugger; + return; + } + + // down into the rabbit hole we go + return (i % 2) ? recurseA(++i) : recurseB(++i); +} + + +window.startRecursion = function() { + return recurseA(0); +} diff --git a/devtools/client/debugger/new/test/mochitest/examples/long.js b/devtools/client/debugger/new/test/mochitest/examples/long.js new file mode 100644 index 000000000..58d605b36 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/long.js @@ -0,0 +1,76 @@ +var app = {}; + +// Generic "model" object. You can use whatever +// framework you want. For this application it +// may not even be worth separating this logic +// out, but we do this to demonstrate one way to +// separate out parts of your application. +app.TodoModel = function (key) { + this.key = key; + this.todos = []; + this.onChanges = []; +}; + +app.TodoModel.prototype.addTodo = function (title) { + this.todos = this.todos.concat([{ + id: Utils.uuid(), + title: title, + completed: false + }]); +}; + +app.TodoModel.prototype.inform = function() { + // Something changed, but we do nothing + return null; +}; + +app.TodoModel.prototype.toggleAll = function (checked) { + // Note: it's usually better to use immutable data structures since they're + // easier to reason about and React works very well with them. That's why + // we use map() and filter() everywhere instead of mutating the array or + // todo items themselves. + this.todos = this.todos.map(function (todo) { + return Object.assign({}, todo, {completed: checked}); + }); + + this.inform(); +}; + +app.TodoModel.prototype.toggle = function (todoToToggle) { + this.todos = this.todos.map(function (todo) { + return todo !== todoToToggle ? + todo : + Object.assign({}, todo, {completed: !todo.completed}); + }); + + this.inform(); +}; + +app.TodoModel.prototype.destroy = function (todo) { + this.todos = this.todos.filter(function (candidate) { + return candidate !== todo; + }); + + this.inform(); +}; + +app.TodoModel.prototype.save = function (todoToSave, text) { + this.todos = this.todos.map(function (todo) { + return todo !== todoToSave ? todo : Object.assign({}, todo, {title: text}); + }); + + this.inform(); +}; + +app.TodoModel.prototype.clearCompleted = function () { + this.todos = this.todos.filter(function (todo) { + return !todo.completed; + }); + + this.inform(); +}; + +function testModel() { + const model = new app.TodoModel(); + model.clearCompleted(); +} diff --git a/devtools/client/debugger/new/test/mochitest/examples/math.min.js b/devtools/client/debugger/new/test/mochitest/examples/math.min.js new file mode 100644 index 000000000..5a8593345 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/math.min.js @@ -0,0 +1,3 @@ +function add(a,b,k){var result=a+b;return k(result)}function sub(a,b,k){var result=a-b;return k(result)}function mul(a,b,k){var result=a*b;return k(result)}function div(a,b,k){var result=a/b;return k(result)}function arithmetic(){ + add(4,4,function(a){ + sub(a,2,function(b){mul(b,3,function(c){div(c,2,function(d){console.log(d)})})})})}; diff --git a/devtools/client/debugger/new/test/mochitest/examples/nested/nested-source.js b/devtools/client/debugger/new/test/mochitest/examples/nested/nested-source.js new file mode 100644 index 000000000..a7b20f015 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/nested/nested-source.js @@ -0,0 +1,3 @@ +function computeSomething() { + return 1; +} diff --git a/devtools/client/debugger/new/test/mochitest/examples/opts.js b/devtools/client/debugger/new/test/mochitest/examples/opts.js new file mode 100644 index 000000000..20988fa4a --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/opts.js @@ -0,0 +1,3 @@ +module.exports = { + extra: true +}; diff --git a/devtools/client/debugger/new/test/mochitest/examples/output.js b/devtools/client/debugger/new/test/mochitest/examples/output.js new file mode 100644 index 000000000..14281fdbf --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/output.js @@ -0,0 +1,5 @@ +function output(str) { + console.log(str); +} + +module.exports = { output }; diff --git a/devtools/client/debugger/new/test/mochitest/examples/script-switching-01.js b/devtools/client/debugger/new/test/mochitest/examples/script-switching-01.js new file mode 100644 index 000000000..4ba2772de --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/script-switching-01.js @@ -0,0 +1,6 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function firstCall() { + secondCall(); +} diff --git a/devtools/client/debugger/new/test/mochitest/examples/script-switching-02.js b/devtools/client/debugger/new/test/mochitest/examples/script-switching-02.js new file mode 100644 index 000000000..feb74315f --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/script-switching-02.js @@ -0,0 +1,13 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function secondCall() { + // This comment is useful: ☺ + debugger; + function foo() {} + if (x) { + foo(); + } +} + +var x = true; diff --git a/devtools/client/debugger/new/test/mochitest/examples/simple1.js b/devtools/client/debugger/new/test/mochitest/examples/simple1.js new file mode 100644 index 000000000..87cc50f44 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/simple1.js @@ -0,0 +1,31 @@ +function main() { + // A comment so we can test that breakpoint sliding works across + // multiple lines + const func = foo(1, 2); + const result = func(); + return result; +} + +function doEval() { + eval("(" + function() { + debugger; + + window.evaledFunc = function() { + var foo = 1; + var bar = 2; + return foo + bar; + }; + }.toString() + ")()"); +} + +function doNamedEval() { + eval("(" + function() { + debugger; + + window.evaledFunc = function() { + var foo = 1; + var bar = 2; + return foo + bar; + }; + }.toString() + ")();\n //# sourceURL=evaled.js"); +} diff --git a/devtools/client/debugger/new/test/mochitest/examples/simple2.js b/devtools/client/debugger/new/test/mochitest/examples/simple2.js new file mode 100644 index 000000000..40c280edf --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/simple2.js @@ -0,0 +1,6 @@ +function foo(x, y) { + function bar() { + return x + y; + } + return bar; +} diff --git a/devtools/client/debugger/new/test/mochitest/examples/times2.js b/devtools/client/debugger/new/test/mochitest/examples/times2.js new file mode 100644 index 000000000..2d51ed87a --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/times2.js @@ -0,0 +1,3 @@ +module.exports = function(x) { + return x * 2; +} diff --git a/devtools/client/debugger/new/test/mochitest/examples/webpack.config.js b/devtools/client/debugger/new/test/mochitest/examples/webpack.config.js new file mode 100644 index 000000000..ff22342ce --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/webpack.config.js @@ -0,0 +1,8 @@ + +module.exports = { + entry: "./entry.js", + output: { + filename: "bundle.js" + }, + devtool: "sourcemap" +} diff --git a/devtools/client/debugger/new/test/mochitest/head.js b/devtools/client/debugger/new/test/mochitest/head.js new file mode 100644 index 000000000..b0964d890 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/head.js @@ -0,0 +1,684 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * The Mochitest API documentation + * @module mochitest + */ + +/** + * The mochitest API to wait for certain events. + * @module mochitest/waits + * @parent mochitest + */ + +/** + * The mochitest API predefined asserts. + * @module mochitest/asserts + * @parent mochitest + */ + +/** + * The mochitest API for interacting with the debugger. + * @module mochitest/actions + * @parent mochitest + */ + +/** + * Helper methods for the mochitest API. + * @module mochitest/helpers + * @parent mochitest + */ + +// shared-head.js handles imports, constants, and utility functions +Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js", this); +var { Toolbox } = require("devtools/client/framework/toolbox"); +const EXAMPLE_URL = "http://example.com/browser/devtools/client/debugger/new/test/mochitest/examples/"; + +Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", true); +registerCleanupFunction(() => { + Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend"); + delete window.resumeTest; +}); + +// Wait until an action of `type` is dispatched. This is different +// then `_afterDispatchDone` because it doesn't wait for async actions +// to be done/errored. Use this if you want to listen for the "start" +// action of an async operation (somewhat rare). +function waitForNextDispatch(store, type) { + return new Promise(resolve => { + store.dispatch({ + // Normally we would use `services.WAIT_UNTIL`, but use the + // internal name here so tests aren't forced to always pass it + // in + type: "@@service/waitUntil", + predicate: action => action.type === type, + run: (dispatch, getState, action) => { + resolve(action); + } + }); + }); +} + +// Wait until an action of `type` is dispatched. If it's part of an +// async operation, wait until the `status` field is "done" or "error" +function _afterDispatchDone(store, type) { + return new Promise(resolve => { + store.dispatch({ + // Normally we would use `services.WAIT_UNTIL`, but use the + // internal name here so tests aren't forced to always pass it + // in + type: "@@service/waitUntil", + predicate: action => { + if (action.type === type) { + return action.status ? + (action.status === "done" || action.status === "error") : + true; + } + }, + run: (dispatch, getState, action) => { + resolve(action); + } + }); + }); +} + +/** + * Wait for a specific action type to be dispatch. + * If an async action, will wait for it to be done. + * + * @memberof mochitest/waits + * @param {Object} dbg + * @param {String} type + * @param {Number} eventRepeat + * @return {Promise} + * @static + */ +function waitForDispatch(dbg, type, eventRepeat = 1) { + let count = 0; + + return Task.spawn(function* () { + info("Waiting for " + type + " to dispatch " + eventRepeat + " time(s)"); + while (count < eventRepeat) { + yield _afterDispatchDone(dbg.store, type); + count++; + info(type + " dispatched " + count + " time(s)"); + } + }); +} + +/** + * Waits for specific thread events. + * + * @memberof mochitest/waits + * @param {Object} dbg + * @param {String} eventName + * @return {Promise} + * @static + */ +function waitForThreadEvents(dbg, eventName) { + info("Waiting for thread event '" + eventName + "' to fire."); + const thread = dbg.toolbox.threadClient; + + return new Promise(function(resolve, reject) { + thread.addListener(eventName, function onEvent(eventName, ...args) { + info("Thread event '" + eventName + "' fired."); + thread.removeListener(eventName, onEvent); + resolve.apply(resolve, args); + }); + }); +} + +/** + * Waits for `predicate(state)` to be true. `state` is the redux app state. + * + * @memberof mochitest/waits + * @param {Object} dbg + * @param {Function} predicate + * @return {Promise} + * @static + */ +function waitForState(dbg, predicate) { + return new Promise(resolve => { + const unsubscribe = dbg.store.subscribe(() => { + if (predicate(dbg.store.getState())) { + unsubscribe(); + resolve(); + } + }); + }); +} + +/** + * Waits for sources to be loaded. + * + * @memberof mochitest/waits + * @param {Object} dbg + * @param {Array} sources + * @return {Promise} + * @static + */ +function waitForSources(dbg, ...sources) { + if (sources.length === 0) { + return Promise.resolve(); + } + + info("Waiting on sources: " + sources.join(", ")); + const { selectors: { getSources }, store } = dbg; + return Promise.all(sources.map(url => { + function sourceExists(state) { + return getSources(state).some(s => { + return s.get("url").includes(url); + }); + } + + if (!sourceExists(store.getState())) { + return waitForState(dbg, sourceExists); + } + })); +} + +function waitForElement(dbg, selector) { + return waitUntil(() => findElementWithSelector(dbg, selector)) +} + +/** + * Assert that the debugger is paused at the correct location. + * + * @memberof mochitest/asserts + * @param {Object} dbg + * @param {String} source + * @param {Number} line + * @static + */ +function assertPausedLocation(dbg, source, line) { + const { selectors: { getSelectedSource, getPause }, getState } = dbg; + source = findSource(dbg, source); + + // Check the selected source + is(getSelectedSource(getState()).get("id"), source.id); + + // Check the pause location + const location = getPause(getState()).getIn(["frame", "location"]); + is(location.get("sourceId"), source.id); + is(location.get("line"), line); + + // Check the debug line + ok(dbg.win.cm.lineInfo(line - 1).wrapClass.includes("debug-line"), + "Line is highlighted as paused"); +} + +/** + * Assert that the debugger is highlighting the correct location. + * + * @memberof mochitest/asserts + * @param {Object} dbg + * @param {String} source + * @param {Number} line + * @static + */ +function assertHighlightLocation(dbg, source, line) { + const { selectors: { getSelectedSource, getPause }, getState } = dbg; + source = findSource(dbg, source); + + // Check the selected source + is(getSelectedSource(getState()).get("url"), source.url); + + // Check the highlight line + const lineEl = findElement(dbg, "highlightLine"); + ok(lineEl, "Line is highlighted"); + ok(isVisibleWithin(findElement(dbg, "codeMirror"), lineEl), + "Highlighted line is visible"); + ok(dbg.win.cm.lineInfo(line - 1).wrapClass.includes("highlight-line"), + "Line is highlighted"); +} + +/** + * Returns boolean for whether the debugger is paused. + * + * @memberof mochitest/asserts + * @param {Object} dbg + * @static + */ +function isPaused(dbg) { + const { selectors: { getPause }, getState } = dbg; + return !!getPause(getState()); +} + +/** + * Waits for the debugger to be fully paused. + * + * @memberof mochitest/waits + * @param {Object} dbg + * @static + */ +function waitForPaused(dbg) { + return Task.spawn(function* () { + // We want to make sure that we get both a real paused event and + // that the state is fully populated. The client may do some more + // work (call other client methods) before populating the state. + yield waitForThreadEvents(dbg, "paused"), + yield waitForState(dbg, state => { + const pause = dbg.selectors.getPause(state); + // Make sure we have the paused state. + if (!pause) { + return false; + } + // Make sure the source text is completely loaded for the + // source we are paused in. + const sourceId = pause.getIn(["frame", "location", "sourceId"]); + const sourceText = dbg.selectors.getSourceText(dbg.getState(), sourceId); + return sourceText && !sourceText.get("loading"); + }); + }); +} + +function createDebuggerContext(toolbox) { + const win = toolbox.getPanel("jsdebugger").panelWin; + const store = win.Debugger.store; + + return { + actions: win.Debugger.actions, + selectors: win.Debugger.selectors, + getState: store.getState, + store: store, + client: win.Debugger.client, + toolbox: toolbox, + win: win + }; +} + +/** + * Intilializes the debugger. + * + * @memberof mochitest + * @param {String} url + * @param {Array} sources + * @return {Promise} dbg + * @static + */ +function initDebugger(url, ...sources) { + return Task.spawn(function* () { + const toolbox = yield openNewTabAndToolbox(EXAMPLE_URL + url, "jsdebugger"); + return createDebuggerContext(toolbox); + }); +} + +window.resumeTest = undefined; +/** + * Pause the test and let you interact with the debugger. + * The test can be resumed by invoking `resumeTest` in the console. + * + * @memberof mochitest + * @static + */ +function pauseTest() { + info("Test paused. Invoke resumeTest to continue."); + return new Promise(resolve => resumeTest = resolve); +} + +// Actions +/** + * Returns a source that matches the URL. + * + * @memberof mochitest/actions + * @param {Object} dbg + * @param {String} url + * @return {Object} source + * @static + */ +function findSource(dbg, url) { + if (typeof url !== "string") { + // Support passing in a source object itelf all APIs that use this + // function support both styles + const source = url; + return source; + } + + const sources = dbg.selectors.getSources(dbg.getState()); + const source = sources.find(s => s.get("url").includes(url)); + + if (!source) { + throw new Error("Unable to find source: " + url); + } + + return source.toJS(); +} + +/** + * Selects the source. + * + * @memberof mochitest/actions + * @param {Object} dbg + * @param {String} url + * @param {Number} line + * @return {Promise} + * @static + */ +function selectSource(dbg, url, line) { + info("Selecting source: " + url); + const source = findSource(dbg, url); + const hasText = !!dbg.selectors.getSourceText(dbg.getState(), source.id); + dbg.actions.selectSource(source.id, { line }); + + if (!hasText) { + return waitForDispatch(dbg, "LOAD_SOURCE_TEXT"); + } +} + +/** + * Steps over. + * + * @memberof mochitest/actions + * @param {Object} dbg + * @return {Promise} + * @static + */ +function stepOver(dbg) { + info("Stepping over"); + dbg.actions.stepOver(); + return waitForPaused(dbg); +} + +/** + * Steps in. + * + * @memberof mochitest/actions + * @param {Object} dbg + * @return {Promise} + * @static + */ +function stepIn(dbg) { + info("Stepping in"); + dbg.actions.stepIn(); + return waitForPaused(dbg); +} + +/** + * Steps out. + * + * @memberof mochitest/actions + * @param {Object} dbg + * @return {Promise} + * @static + */ +function stepOut(dbg) { + info("Stepping out"); + dbg.actions.stepOut(); + return waitForPaused(dbg); +} + +/** + * Resumes. + * + * @memberof mochitest/actions + * @param {Object} dbg + * @return {Promise} + * @static + */ +function resume(dbg) { + info("Resuming"); + dbg.actions.resume(); + return waitForThreadEvents(dbg, "resumed"); +} + +/** + * Reloads the debuggee. + * + * @memberof mochitest/actions + * @param {Object} dbg + * @param {Array} sources + * @return {Promise} + * @static + */ +function reload(dbg, ...sources) { + return dbg.client.reload().then(() => waitForSources(...sources)); +} + +/** + * Navigates the debuggee to another url. + * + * @memberof mochitest/actions + * @param {Object} dbg + * @param {String} url + * @param {Array} sources + * @return {Promise} + * @static + */ +function navigate(dbg, url, ...sources) { + dbg.client.navigate(url); + return waitForSources(dbg, ...sources); +} + +/** + * Adds a breakpoint to a source at line/col. + * + * @memberof mochitest/actions + * @param {Object} dbg + * @param {String} source + * @param {Number} line + * @param {Number} col + * @return {Promise} + * @static + */ +function addBreakpoint(dbg, source, line, col) { + source = findSource(dbg, source); + const sourceId = source.id; + dbg.actions.addBreakpoint({ sourceId, line, col }); + return waitForDispatch(dbg, "ADD_BREAKPOINT"); +} + +/** + * Removes a breakpoint from a source at line/col. + * + * @memberof mochitest/actions + * @param {Object} dbg + * @param {String} source + * @param {Number} line + * @param {Number} col + * @return {Promise} + * @static + */ +function removeBreakpoint(dbg, sourceId, line, col) { + return dbg.actions.removeBreakpoint({ sourceId, line, col }); +} + +/** + * Toggles the Pause on exceptions feature in the debugger. + * + * @memberof mochitest/actions + * @param {Object} dbg + * @param {Boolean} pauseOnExceptions + * @param {Boolean} ignoreCaughtExceptions + * @return {Promise} + * @static + */ +function togglePauseOnExceptions(dbg, + pauseOnExceptions, ignoreCaughtExceptions) { + const command = dbg.actions.pauseOnExceptions( + pauseOnExceptions, + ignoreCaughtExceptions + ); + + if (!isPaused(dbg)) { + return waitForThreadEvents(dbg, "resumed"); + } + + return command; +} + +// Helpers + +/** + * Invokes a global function in the debuggee tab. + * + * @memberof mochitest/helpers + * @param {String} fnc + * @return {Promise} + * @static + */ +function invokeInTab(fnc) { + info(`Invoking function ${fnc} in tab`); + return ContentTask.spawn(gBrowser.selectedBrowser, fnc, function* (fnc) { + content.wrappedJSObject[fnc](); // eslint-disable-line mozilla/no-cpows-in-tests, max-len + }); +} + +const isLinux = Services.appinfo.OS === "Linux"; +const cmdOrCtrl = isLinux ? { ctrlKey: true } : { metaKey: true }; +const keyMappings = { + sourceSearch: { code: "p", modifiers: cmdOrCtrl}, + fileSearch: { code: "f", modifiers: cmdOrCtrl}, + "Enter": { code: "VK_RETURN" }, + "Up": { code: "VK_UP" }, + "Down": { code: "VK_DOWN" }, + pauseKey: { code: "VK_F8" }, + resumeKey: { code: "VK_F8" }, + stepOverKey: { code: "VK_F10" }, + stepInKey: { code: "VK_F11", modifiers: { ctrlKey: isLinux }}, + stepOutKey: { code: "VK_F11", modifiers: { ctrlKey: isLinux, shiftKey: true }} +}; + +/** + * Simulates a key press in the debugger window. + * + * @memberof mochitest/helpers + * @param {Object} dbg + * @param {String} keyName + * @return {Promise} + * @static + */ +function pressKey(dbg, keyName) { + let keyEvent = keyMappings[keyName]; + + const { code, modifiers } = keyEvent; + return EventUtils.synthesizeKey( + code, + modifiers || {}, + dbg.win + ); +} + +function type(dbg, string) { + string.split("").forEach(char => { + EventUtils.synthesizeKey(char, {}, dbg.win); + }); +} + +function isVisibleWithin(outerEl, innerEl) { + const innerRect = innerEl.getBoundingClientRect(); + const outerRect = outerEl.getBoundingClientRect(); + return innerRect.top > outerRect.top && + innerRect.bottom < outerRect.bottom; +} + +const selectors = { + callStackHeader: ".call-stack-pane ._header", + callStackBody: ".call-stack-pane .pane", + scopesHeader: ".scopes-pane ._header", + breakpointItem: i => `.breakpoints-list .breakpoint:nth-child(${i})`, + scopeNode: i => `.scopes-list .tree-node:nth-child(${i}) .object-label`, + frame: i => `.frames ul li:nth-child(${i})`, + frames: ".frames ul li", + gutter: i => `.CodeMirror-code *:nth-child(${i}) .CodeMirror-linenumber`, + menuitem: i => `menupopup menuitem:nth-child(${i})`, + pauseOnExceptions: ".pause-exceptions", + breakpoint: ".CodeMirror-code > .new-breakpoint", + highlightLine: ".CodeMirror-code > .highlight-line", + codeMirror: ".CodeMirror", + resume: ".resume.active", + stepOver: ".stepOver.active", + stepOut: ".stepOut.active", + stepIn: ".stepIn.active", + toggleBreakpoints: ".toggleBreakpoints", + prettyPrintButton: ".prettyPrint", + sourceFooter: ".source-footer", + sourceNode: i => `.sources-list .tree-node:nth-child(${i})`, + sourceNodes: ".sources-list .tree-node", + sourceArrow: i => `.sources-list .tree-node:nth-child(${i}) .arrow`, +}; + +function getSelector(elementName, ...args) { + let selector = selectors[elementName]; + if (!selector) { + throw new Error(`The selector ${elementName} is not defined`); + } + + if (typeof selector == "function") { + selector = selector(...args); + } + + return selector; +} + +function findElement(dbg, elementName, ...args) { + const selector = getSelector(elementName, ...args); + return findElementWithSelector(dbg, selector); +} + +function findElementWithSelector(dbg, selector) { + return dbg.win.document.querySelector(selector); +} + +function findAllElements(dbg, elementName, ...args) { + const selector = getSelector(elementName, ...args); + return dbg.win.document.querySelectorAll(selector); +} + +/** + * Simulates a mouse click in the debugger DOM. + * + * @memberof mochitest/helpers + * @param {Object} dbg + * @param {String} elementName + * @param {Array} args + * @return {Promise} + * @static + */ +function clickElement(dbg, elementName, ...args) { + const selector = getSelector(elementName, ...args); + return EventUtils.synthesizeMouseAtCenter( + findElementWithSelector(dbg, selector), + {}, + dbg.win + ); +} + +function rightClickElement(dbg, elementName, ...args) { + const selector = getSelector(elementName, ...args); + const doc = dbg.win.document; + return EventUtils.synthesizeMouseAtCenter( + doc.querySelector(selector), + {type: "contextmenu"}, + dbg.win + ); +} + +function selectMenuItem(dbg, index) { + // the context menu is in the toolbox window + const doc = dbg.toolbox.win.document; + + // there are several context menus, we want the one with the menu-api + const popup = doc.querySelector("menupopup[menu-api=\"true\"]"); + + const item = popup.querySelector(`menuitem:nth-child(${index})`); + return EventUtils.synthesizeMouseAtCenter(item, {}, dbg.toolbox.win ); +} + +/** + * Toggles the debugger call stack accordian. + * + * @memberof mochitest/actions + * @param {Object} dbg + * @return {Promise} + * @static + */ +function toggleCallStack(dbg) { + return findElement(dbg, "callStackHeader").click(); +} + +function toggleScopes(dbg) { + return findElement(dbg, "scopesHeader").click(); +} |