diff --git a/.gitignore b/.gitignore index da1b8c22..e9c84876 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,9 @@ tests/data_*.js utils/rebind.so utils/websockify -node_modules -build -lib +/node_modules +/build +/lib recordings +*.swp +*~ diff --git a/.travis.yml b/.travis.yml index a7fe4233..ba5c50be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ node_js: - '6.1' env: matrix: - - TEST_BROWSER_NAME=PhantomJS - TEST_BROWSER_NAME=chrome TEST_BROWSER_OS='Windows 10,Linux,OS X 10.11' - TEST_BROWSER_NAME=firefox TEST_BROWSER_OS='Windows 10,Linux,OS X 10.11' - TEST_BROWSER_NAME='internet explorer' TEST_BROWSER_OS='Windows 10' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4bcea104..2d2e68cf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,20 +35,8 @@ Contributing Guidelines Running the unit tests ---------------------- -There are two ways to run the unit tests. For both ways, you should first run -`npm install` (not as root). - -The first way to run the tests is to run `npm test`. This will run all the -tests in the headless PhantomJS browser (which uses WebKit). - -The second way to run the tests is using the `tests/run_from_console.js` file. -This way is a bit more flexible, and can provide more information about what -went wrong. To run all the tests, simply run `tests/run_from_console.js`. -To run a specific test file, you can use the `-t path/to/test/file.js` option. -If you wish to simply generate the HTML for the test, use the `-g` option, and -the path to the temporary HTML file will be written to standard out. To open -this file in your default browser automatically, pass the `-o` option as well. -More information can be found by passing the `--help` or `-h` option. - +We use Karma to run our tests. You can launch karma manually, or simply +run `npm test`. The Karma debug page will display the tests in normal +mocha form, if you need it. Thanks, and happy coding! diff --git a/LICENSE.txt b/LICENSE.txt index 7b5de592..a8d24e39 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -5,19 +5,9 @@ Public License 2.0). The noVNC core library is composed of the Javascript code necessary for full noVNC operation. This includes (but is not limited to): - core/base64.js - core/des.js - core/display.js - core/input/devices.js - core/input/keysym.js - core/logo.js - core/playback.js - core/rfb.js - app/ui.js - core/util.js - core/websock.js - app/webutil.js - core/input/xtscancodes.js + core/**/*.js + app/*.js + test/playback.js The HTML, CSS, font and images files that included with the noVNC source distibution (or repository) are not considered part of the @@ -49,8 +39,11 @@ licenses (all MPL 2.0 compatible): core/des.js : Various BSD style licenses - utils/inflator.mod.js - include/inflator.js : MIT (for pako) + vendor/pako/ : MIT + + vendor/browser-es-module-loader: MIT + + vendor/promise.js : MIT Any other files not mentioned above are typically marked with a copyright/license header at the top of the file. The default noVNC @@ -66,7 +59,7 @@ The following license texts are included: docs/LICENSE.BSD-2-Clause (Simplified BSD / FreeBSD) docs/LICENSE.zlib docs/LICENSE.Apache-2.0 - docs/LICENSE.pako + vendor/pako/LICENSE (MIT) Or alternatively the license texts may be found here: @@ -77,3 +70,4 @@ Or alternatively the license texts may be found here: http://en.wikipedia.org/wiki/BSD_licenses http://www.gzip.org/zlib/zlib_license.html http://www.apache.org/licenses/LICENSE-2.0.html + https://opensource.org/licenses/MIT diff --git a/app/error-handler.js b/app/error-handler.js new file mode 100644 index 00000000..30f77068 --- /dev/null +++ b/app/error-handler.js @@ -0,0 +1,61 @@ +// NB: this should *not* be included as a module until we have +// native support in the browsers, so that our error handler +// can catch script-loading errors. + + +(function(){ + "use strict"; + + function convertNewlines(msg, parentElem) { + const lines = msg.split("\n"); + lines.forEach(function (line) { + parentElem.appendChild(document.createElement("br")); + parentElem.appendChild(document.createTextNode(line)); + }); + parentElem.removeChild(parentElem.firstChild); + return parentElem; + } + + // Fallback for all uncought errors + function handleError (event, err) { + try { + const msg = document.getElementById('noVNC_fallback_errormsg'); + + // Only show the initial error + if (msg.hasChildNodes()) { + return false; + } + + var div = document.createElement("div"); + div.classList.add('noVNC_message'); + convertNewlines(event.message, div); + msg.appendChild(div); + + if (event.filename !== undefined && event.lineno !== undefined && event.colno !== undefined) { + div = document.createElement("div"); + div.className = 'noVNC_location'; + const text = event.filename + ":" + event.lineno + ":" + event.colno; + div.appendChild(document.createTextNode(text)); + msg.appendChild(div); + } + + if ((err !== undefined) && + (err.stack !== undefined)) { + div = document.createElement("div"); + div.className = 'noVNC_stack'; + div.appendChild(document.createTextNode(err.stack)); + msg.appendChild(div); + } + + document.getElementById('noVNC_fallback_error') + .classList.add("noVNC_open"); + } catch (exc) { + document.write("noVNC encountered an error."); + } + // Don't return true since this would prevent the error + // from being printed to the browser console. + return false; + } + window.addEventListener('error', function (evt) { handleError(evt, evt.error); }); + window.addEventListener('unhandledrejection', function (evt) { handleError(evt.reason, evt.reason); }); +})(); diff --git a/app/locale/de.js b/app/locale/de.json similarity index 77% rename from app/locale/de.js rename to app/locale/de.json index 6819c486..b8ef1623 100644 --- a/app/locale/de.js +++ b/app/locale/de.json @@ -1,11 +1,4 @@ -/* - * Translations for de - * - * This file was autotomatically generated from de.po - * DO NOT EDIT! - */ - -Language = { +{ "Connecting...": "Verbunden...", "Connected (encrypted) to ": "Verbunden mit (verschlüsselt) ", "Connected (unencrypted) to ": "Verbunden mit (unverschlüsselt) ", @@ -14,5 +7,5 @@ Language = { "Must set host and port": "Richten Sie Host und Port ein", "Password is required": "Passwort ist erforderlich", "Forcing clipping mode since scrollbars aren't supported by IE in fullscreen": "'Clipping-Modus' aktiviert, Scrollbalken in 'IE-Vollbildmodus' werden nicht unterstützt", - "Disconnect timeout": "Timeout beim trennen", -}; + "Disconnect timeout": "Timeout beim trennen" +} diff --git a/app/locale/el.js b/app/locale/el.json similarity index 95% rename from app/locale/el.js rename to app/locale/el.json index 3ce6c389..1bf1f845 100644 --- a/app/locale/el.js +++ b/app/locale/el.json @@ -1,11 +1,4 @@ -/* - * Translations for el - * - * This file was autotomatically generated from el.po - * DO NOT EDIT! - */ - -Language = { +{ "Connecting...": "Συνδέεται...", "Connected (encrypted) to ": "Συνδέθηκε (κρυπτογραφημένα) με το ", "Connected (unencrypted) to ": "Συνδέθηκε (μη κρυπτογραφημένα) με το ", @@ -15,7 +8,7 @@ Language = { "Password is required": "Απαιτείται ο κωδικός πρόσβασης", "Forcing clipping mode since scrollbars aren't supported by IE in fullscreen": "Εφαρμογή λειτουργίας αποκοπής αφού δεν υποστηρίζονται οι λωρίδες κύλισης σε πλήρη οθόνη στον IE", "Disconnect timeout": "Παρέλευση χρονικού ορίου αποσύνδεσης", - "noVNC encountered an error:": "το noVNC αντιμετώπισε ένα σφάλμα", + "noVNC encountered an error:": "το noVNC αντιμετώπισε ένα σφάλμα:", "Hide/Show the control bar": "Απόκρυψη/Εμφάνιση γραμμής ελέγχου", "Move/Drag Viewport": "Μετακίνηση/Σύρσιμο Θεατού πεδίου", "viewport drag": "σύρσιμο θεατού πεδίου", @@ -65,10 +58,13 @@ Language = { "default": "προεπιλεγμένο", "Logging:": "Καταγραφή:", "Apply": "Εφαρμογή", + "Connect": "Σύνδεση", + "Disconnect": "Αποσύνδεση", + "Connection": "Σύνδεση", "Host:": "Όνομα διακομιστή:", "Port:": "Πόρτα διακομιστή:", "Password:": "Κωδικός Πρόσβασης:", "Token:": "Διακριτικό:", "Send Password": "Αποστολή Κωδικού Πρόσβασης", - "Canvas not supported.": "Δεν υποστηρίζεται το στοιχείο Canvas", -}; + "Canvas not supported.": "Δεν υποστηρίζεται το στοιχείο Canvas" +} diff --git a/app/locale/nl.js b/app/locale/nl.json similarity index 83% rename from app/locale/nl.js rename to app/locale/nl.json index cacab302..74e31ec3 100644 --- a/app/locale/nl.js +++ b/app/locale/nl.json @@ -1,11 +1,4 @@ -/* - * Translations for nl - * - * This file was autotomatically generated from nl.po - * DO NOT EDIT! - */ - -Language = { +{ "Connecting...": "Verbinden...", "Connected (encrypted) to ": "Verbonden (versleuteld) met ", "Connected (unencrypted) to ": "Verbonden (onversleuteld) met ", @@ -14,5 +7,5 @@ Language = { "Must set host and port": "Host en poort moeten worden ingesteld", "Password is required": "Wachtwoord is vereist", "Forcing clipping mode since scrollbars aren't supported by IE in fullscreen": "''Clipping mode' ingeschakeld, omdat schuifbalken in volledige-scherm-modus in IE niet worden ondersteund", - "Disconnect timeout": "Timeout tijdens verbreken van verbinding", -}; + "Disconnect timeout": "Timeout tijdens verbreken van verbinding" +} diff --git a/app/locale/sv.js b/app/locale/sv.json similarity index 93% rename from app/locale/sv.js rename to app/locale/sv.json index b7f4c1fb..c6469564 100644 --- a/app/locale/sv.js +++ b/app/locale/sv.json @@ -1,11 +1,4 @@ -/* - * Translations for sv - * - * This file was autotomatically generated from sv.po - * DO NOT EDIT! - */ - -Language = { +{ "Connecting...": "Ansluter...", "Connected (encrypted) to ": "Ansluten (krypterat) till ", "Connected (unencrypted) to ": "Ansluten (okrypterat) till ", @@ -73,5 +66,5 @@ Language = { "Password:": "Lösenord:", "Token:": "Token:", "Send Password": "Skicka Lösenord", - "Canvas not supported.": "Canvas stöds ej", -}; + "Canvas not supported.": "Canvas stöds ej" +} diff --git a/app/styles/base.css b/app/styles/base.css index 6bb23a47..30146963 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -247,6 +247,11 @@ select:active { font-weight: normal; } +#noVNC_fallback_errormsg .noVNC_message { + display: inline-block; + text-align: left; +} + #noVNC_fallback_error .noVNC_location { font-style: italic; font-size: 0.8em; @@ -774,6 +779,7 @@ select:active { justify-content: center; flex-direction: column; } +:root.noVNC_loading #noVNC_transition, :root.noVNC_connecting #noVNC_transition, :root.noVNC_disconnecting #noVNC_transition, :root.noVNC_reconnecting #noVNC_transition { diff --git a/app/ui.js b/app/ui.js index 33cd1d48..46826221 100644 --- a/app/ui.js +++ b/app/ui.js @@ -11,463 +11,407 @@ /* jslint white: false, browser: true */ /* global window, document.getElementById, Util, WebUtil, RFB, Display */ -/* [module] - * import Util from "../core/util"; - * import KeyTable from "../core/input/keysym"; - * import keysyms from "./keysymdef"; - * import RFB from "../core/rfb"; - * import Display from "../core/display"; - * import WebUtil from "./webutil"; - */ +import * as Log from '../core/util/logging.js'; +import _, { l10n } from '../core/util/localization.js' +import { isTouchDevice, browserSupportsCursorURIs as cursorURIsSupported } from '../core/util/browsers.js'; +import { setCapture, getPointerEvent } from '../core/util/events.js'; +import KeyTable from "../core/input/keysym.js"; +import keysyms from "../core/input/keysymdef.js"; +import RFB from "../core/rfb.js"; +import Display from "../core/display.js"; +import * as WebUtil from "./webutil.js"; -var UI; +const UI = { -(function () { - "use strict"; + connected: false, + desktopName: "", - // Fallback for all uncought errors - window.addEventListener('error', function(event) { - try { - var msg, div, text; + resizeTimeout: null, + statusTimeout: null, + hideKeyboardTimeout: null, + idleControlbarTimeout: null, + closeControlbarTimeout: null, - msg = document.getElementById('noVNC_fallback_errormsg'); + controlbarGrabbed: false, + controlbarDrag: false, + controlbarMouseDownClientY: 0, + controlbarMouseDownOffsetY: 0, - // Only show the initial error - if (msg.hasChildNodes()) { - return false; - } + isSafari: false, + rememberedClipSetting: null, + lastKeyboardinput: null, + defaultKeyboardinputLen: 100, - div = document.createElement("div"); - div.appendChild(document.createTextNode(event.message)); - msg.appendChild(div); + inhibit_reconnect: true, + reconnect_callback: null, + reconnect_password: null, - div = document.createElement("div"); - div.className = 'noVNC_location'; - text = event.filename + ":" + event.lineno + ":" + event.colno; - div.appendChild(document.createTextNode(text)); - msg.appendChild(div); - - if ((event.error !== undefined) && - (event.error.stack !== undefined)) { - div = document.createElement("div"); - div.className = 'noVNC_stack'; - div.appendChild(document.createTextNode(event.error.stack)); - msg.appendChild(div); - } - - document.getElementById('noVNC_fallback_error') - .classList.add("noVNC_open"); - } catch (exc) { - document.write("noVNC encountered an error."); + prime: function(callback) { + if (document.readyState === "interactive" || document.readyState === "complete") { + UI.load(callback); + } else { + document.addEventListener('DOMContentLoaded', UI.load.bind(UI, callback)); } - // Don't return true since this would prevent the error - // from being printed to the browser console. - return false; - }); + }, - // Set up translations - var LINGUAS = ["de", "el", "nl", "sv"]; - Util.Localisation.setup(LINGUAS); - if (Util.Localisation.language !== "en") { - WebUtil.load_scripts( - {'app': ["locale/" + Util.Localisation.language + ".js"]}); - } + // Setup rfb object, load settings from browser storage, then call + // UI.init to setup the UI/menus + load: function(callback) { + WebUtil.initSettings(UI.start, callback); + }, - /* [begin skip-as-module] */ - // Load supporting scripts - WebUtil.load_scripts( - {'core': ["base64.js", "websock.js", "des.js", "input/keysymdef.js", - "input/xtscancodes.js", "input/util.js", "input/devices.js", - "display.js", "inflator.js", "rfb.js", "input/keysym.js"]}); + // Render default UI and initialize settings menu + start: function(callback) { - window.onscriptsload = function () { UI.load(); }; - /* [end skip-as-module] */ + // Setup global variables first + UI.isSafari = (navigator.userAgent.indexOf('Safari') !== -1 && + navigator.userAgent.indexOf('Chrome') === -1); - var _ = Util.Localisation.get; + UI.initSettings(); - UI = { + // Translate the DOM + l10n.translateDOM(); - connected: false, - desktopName: "", + // Adapt the interface for touch screen devices + if (isTouchDevice) { + document.documentElement.classList.add("noVNC_touch"); + // Remove the address bar + setTimeout(function() { window.scrollTo(0, 1); }, 100); + } - resizeTimeout: null, - statusTimeout: null, - hideKeyboardTimeout: null, - idleControlbarTimeout: null, - closeControlbarTimeout: null, + // Restore control bar position + if (WebUtil.readSetting('controlbar_pos') === 'right') { + UI.toggleControlbarSide(); + } - controlbarGrabbed: false, - controlbarDrag: false, - controlbarMouseDownClientY: 0, - controlbarMouseDownOffsetY: 0, + UI.initFullscreen(); - isSafari: false, - rememberedClipSetting: null, - lastKeyboardinput: null, - defaultKeyboardinputLen: 100, + // Setup event handlers + UI.addResizeHandlers(); + UI.addControlbarHandlers(); + UI.addTouchSpecificHandlers(); + UI.addExtraKeysHandlers(); + UI.addXvpHandlers(); + UI.addConnectionControlHandlers(); + UI.addClipboardHandlers(); + UI.addSettingsHandlers(); + document.getElementById("noVNC_status") + .addEventListener('click', UI.hideStatus); - inhibit_reconnect: true, - reconnect_callback: null, - reconnect_password: null, + UI.openControlbar(); - // Setup rfb object, load settings from browser storage, then call - // UI.init to setup the UI/menus - load: function(callback) { - WebUtil.initSettings(UI.start, callback); - }, + // Show the connect panel on first load unless autoconnecting + if (!autoconnect) { + UI.openConnectPanel(); + } - // Render default UI and initialize settings menu - start: function(callback) { + UI.updateViewClip(); - // Setup global variables first - UI.isSafari = (navigator.userAgent.indexOf('Safari') !== -1 && - navigator.userAgent.indexOf('Chrome') === -1); + UI.updateVisualState(); - UI.initSettings(); + document.getElementById('noVNC_setting_host').focus(); + document.documentElement.classList.remove("noVNC_loading"); - // Translate the DOM - Util.Localisation.translateDOM(); + var autoconnect = WebUtil.getConfigVar('autoconnect', false); + if (autoconnect === 'true' || autoconnect == '1') { + autoconnect = true; + UI.connect(); + } else { + autoconnect = false; + } - // Adapt the interface for touch screen devices - if (Util.isTouchDevice) { - document.documentElement.classList.add("noVNC_touch"); - // Remove the address bar - setTimeout(function() { window.scrollTo(0, 1); }, 100); + if (typeof callback === "function") { + callback(UI.rfb); + } + }, + + initFullscreen: function() { + // Only show the button if fullscreen is properly supported + // * Safari doesn't support alphanumerical input while in fullscreen + if (!UI.isSafari && + (document.documentElement.requestFullscreen || + document.documentElement.mozRequestFullScreen || + document.documentElement.webkitRequestFullscreen || + document.body.msRequestFullscreen)) { + document.getElementById('noVNC_fullscreen_button') + .classList.remove("noVNC_hidden"); + UI.addFullscreenHandlers(); + } + }, + + initSettings: function() { + var i; + + // Logging selection dropdown + var llevels = ['error', 'warn', 'info', 'debug']; + for (i = 0; i < llevels.length; i += 1) { + UI.addOption(document.getElementById('noVNC_setting_logging'),llevels[i], llevels[i]); + } + + // Settings with immediate effects + UI.initSetting('logging', 'warn'); + UI.updateLogging(); + + // if port == 80 (or 443) then it won't be present and should be + // set manually + var port = window.location.port; + if (!port) { + if (window.location.protocol.substring(0,5) == 'https') { + port = 443; } - - // Restore control bar position - if (WebUtil.readSetting('controlbar_pos') === 'right') { - UI.toggleControlbarSide(); + else if (window.location.protocol.substring(0,4) == 'http') { + port = 80; } + } - UI.initFullscreen(); + /* Populate the controls if defaults are provided in the URL */ + UI.initSetting('host', window.location.hostname); + UI.initSetting('port', port); + UI.initSetting('encrypt', (window.location.protocol === "https:")); + UI.initSetting('true_color', true); + UI.initSetting('cursor', !isTouchDevice); + UI.initSetting('clip', false); + UI.initSetting('resize', 'off'); + UI.initSetting('shared', true); + UI.initSetting('view_only', false); + UI.initSetting('path', 'websockify'); + UI.initSetting('repeaterID', ''); + UI.initSetting('reconnect', false); + UI.initSetting('reconnect_delay', 5000); - // Setup event handlers - UI.addResizeHandlers(); - UI.addControlbarHandlers(); - UI.addTouchSpecificHandlers(); - UI.addExtraKeysHandlers(); - UI.addXvpHandlers(); - UI.addConnectionControlHandlers(); - UI.addClipboardHandlers(); - UI.addSettingsHandlers(); - document.getElementById("noVNC_status") - .addEventListener('click', UI.hideStatus); - - UI.openControlbar(); - - // Show the connect panel on first load unless autoconnecting - if (!autoconnect) { - UI.openConnectPanel(); - } - - UI.updateViewClip(); - - UI.updateVisualState(); - - document.getElementById('noVNC_setting_host').focus(); - - var autoconnect = WebUtil.getConfigVar('autoconnect', false); - if (autoconnect === 'true' || autoconnect == '1') { - autoconnect = true; - UI.connect(); + UI.setupSettingLabels(); + }, + // Adds a link to the label elements on the corresponding input elements + setupSettingLabels: function() { + var labels = document.getElementsByTagName('LABEL'); + for (var i = 0; i < labels.length; i++) { + var htmlFor = labels[i].htmlFor; + if (htmlFor != '') { + var elem = document.getElementById(htmlFor); + if (elem) elem.label = labels[i]; } else { - autoconnect = false; - } - - if (typeof callback === "function") { - callback(UI.rfb); - } - }, - - initFullscreen: function() { - // Only show the button if fullscreen is properly supported - // * Safari doesn't support alphanumerical input while in fullscreen - if (!UI.isSafari && - (document.documentElement.requestFullscreen || - document.documentElement.mozRequestFullScreen || - document.documentElement.webkitRequestFullscreen || - document.body.msRequestFullscreen)) { - document.getElementById('noVNC_fullscreen_button') - .classList.remove("noVNC_hidden"); - UI.addFullscreenHandlers(); - } - }, - - initSettings: function() { - var i; - - // Logging selection dropdown - var llevels = ['error', 'warn', 'info', 'debug']; - for (i = 0; i < llevels.length; i += 1) { - UI.addOption(document.getElementById('noVNC_setting_logging'),llevels[i], llevels[i]); - } - - // Settings with immediate effects - UI.initSetting('logging', 'warn'); - UI.updateLogging(); - - // if port == 80 (or 443) then it won't be present and should be - // set manually - var port = window.location.port; - if (!port) { - if (window.location.protocol.substring(0,5) == 'https') { - port = 443; - } - else if (window.location.protocol.substring(0,4) == 'http') { - port = 80; - } - } - - /* Populate the controls if defaults are provided in the URL */ - UI.initSetting('host', window.location.hostname); - UI.initSetting('port', port); - UI.initSetting('encrypt', (window.location.protocol === "https:")); - UI.initSetting('true_color', true); - UI.initSetting('cursor', !Util.isTouchDevice); - UI.initSetting('clip', false); - UI.initSetting('resize', 'off'); - UI.initSetting('shared', true); - UI.initSetting('view_only', false); - UI.initSetting('path', 'websockify'); - UI.initSetting('repeaterID', ''); - UI.initSetting('reconnect', false); - UI.initSetting('reconnect_delay', 5000); - - UI.setupSettingLabels(); - }, - - // Adds a link to the label elements on the corresponding input elements - setupSettingLabels: function() { - var labels = document.getElementsByTagName('LABEL'); - for (var i = 0; i < labels.length; i++) { - var htmlFor = labels[i].htmlFor; - if (htmlFor != '') { - var elem = document.getElementById(htmlFor); - if (elem) elem.label = labels[i]; - } else { - // If 'for' isn't set, use the first input element child - var children = labels[i].children; - for (var j = 0; j < children.length; j++) { - if (children[j].form !== undefined) { - children[j].label = labels[i]; - break; - } + // If 'for' isn't set, use the first input element child + var children = labels[i].children; + for (var j = 0; j < children.length; j++) { + if (children[j].form !== undefined) { + children[j].label = labels[i]; + break; } } } - }, + } + }, - initRFB: function() { - try { - UI.rfb = new RFB({'target': document.getElementById('noVNC_canvas'), - 'onNotification': UI.notification, - 'onUpdateState': UI.updateState, - 'onDisconnected': UI.disconnectFinished, - 'onPasswordRequired': UI.passwordRequired, - 'onXvpInit': UI.updateXvpButton, - 'onClipboard': UI.clipboardReceive, - 'onBell': UI.bell, - 'onFBUComplete': UI.initialResize, - 'onFBResize': UI.updateSessionSize, - 'onDesktopName': UI.updateDesktopName}); - return true; - } catch (exc) { - var msg = "Unable to create RFB client -- " + exc; - Util.Error(msg); - UI.showStatus(msg, 'error'); - return false; - } - }, + initRFB: function() { + try { + UI.rfb = new RFB({'target': document.getElementById('noVNC_canvas'), + 'onNotification': UI.notification, + 'onUpdateState': UI.updateState, + 'onDisconnected': UI.disconnectFinished, + 'onPasswordRequired': UI.passwordRequired, + 'onXvpInit': UI.updateXvpButton, + 'onClipboard': UI.clipboardReceive, + 'onBell': UI.bell, + 'onFBUComplete': UI.initialResize, + 'onFBResize': UI.updateSessionSize, + 'onDesktopName': UI.updateDesktopName}); + return true; + } catch (exc) { + var msg = "Unable to create RFB client -- " + exc; + Log.Error(msg); + UI.showStatus(msg, 'error'); + return false; + } + }, /* ------^------- - * /INIT - * ============== - * EVENT HANDLERS - * ------v------*/ +* /INIT +* ============== +* EVENT HANDLERS +* ------v------*/ - addResizeHandlers: function() { - window.addEventListener('resize', UI.applyResizeMode); - window.addEventListener('resize', UI.updateViewClip); - }, + addResizeHandlers: function() { + window.addEventListener('resize', UI.applyResizeMode); + window.addEventListener('resize', UI.updateViewClip); + }, - addControlbarHandlers: function() { - document.getElementById("noVNC_control_bar") - .addEventListener('mousemove', UI.activateControlbar); - document.getElementById("noVNC_control_bar") - .addEventListener('mouseup', UI.activateControlbar); - document.getElementById("noVNC_control_bar") - .addEventListener('mousedown', UI.activateControlbar); - document.getElementById("noVNC_control_bar") - .addEventListener('keypress', UI.activateControlbar); + addControlbarHandlers: function() { + document.getElementById("noVNC_control_bar") + .addEventListener('mousemove', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('mouseup', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('mousedown', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('keypress', UI.activateControlbar); - document.getElementById("noVNC_control_bar") - .addEventListener('mousedown', UI.keepControlbar); - document.getElementById("noVNC_control_bar") - .addEventListener('keypress', UI.keepControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('mousedown', UI.keepControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('keypress', UI.keepControlbar); - document.getElementById("noVNC_view_drag_button") - .addEventListener('click', UI.toggleViewDrag); + document.getElementById("noVNC_view_drag_button") + .addEventListener('click', UI.toggleViewDrag); - document.getElementById("noVNC_control_bar_handle") - .addEventListener('mousedown', UI.controlbarHandleMouseDown); - document.getElementById("noVNC_control_bar_handle") - .addEventListener('mouseup', UI.controlbarHandleMouseUp); - document.getElementById("noVNC_control_bar_handle") - .addEventListener('mousemove', UI.dragControlbarHandle); - // resize events aren't available for elements - window.addEventListener('resize', UI.updateControlbarHandle); + document.getElementById("noVNC_control_bar_handle") + .addEventListener('mousedown', UI.controlbarHandleMouseDown); + document.getElementById("noVNC_control_bar_handle") + .addEventListener('mouseup', UI.controlbarHandleMouseUp); + document.getElementById("noVNC_control_bar_handle") + .addEventListener('mousemove', UI.dragControlbarHandle); + // resize events aren't available for elements + window.addEventListener('resize', UI.updateControlbarHandle); - var exps = document.getElementsByClassName("noVNC_expander"); - for (var i = 0;i < exps.length;i++) { - exps[i].addEventListener('click', UI.toggleExpander); - } - }, + var exps = document.getElementsByClassName("noVNC_expander"); + for (var i = 0;i < exps.length;i++) { + exps[i].addEventListener('click', UI.toggleExpander); + } + }, - addTouchSpecificHandlers: function() { - document.getElementById("noVNC_mouse_button0") - .addEventListener('click', function () { UI.setMouseButton(1); }); - document.getElementById("noVNC_mouse_button1") - .addEventListener('click', function () { UI.setMouseButton(2); }); - document.getElementById("noVNC_mouse_button2") - .addEventListener('click', function () { UI.setMouseButton(4); }); - document.getElementById("noVNC_mouse_button4") - .addEventListener('click', function () { UI.setMouseButton(0); }); - document.getElementById("noVNC_keyboard_button") - .addEventListener('click', UI.toggleVirtualKeyboard); + addTouchSpecificHandlers: function() { + document.getElementById("noVNC_mouse_button0") + .addEventListener('click', function () { UI.setMouseButton(1); }); + document.getElementById("noVNC_mouse_button1") + .addEventListener('click', function () { UI.setMouseButton(2); }); + document.getElementById("noVNC_mouse_button2") + .addEventListener('click', function () { UI.setMouseButton(4); }); + document.getElementById("noVNC_mouse_button4") + .addEventListener('click', function () { UI.setMouseButton(0); }); + document.getElementById("noVNC_keyboard_button") + .addEventListener('click', UI.toggleVirtualKeyboard); - document.getElementById("noVNC_keyboardinput") - .addEventListener('input', UI.keyInput); - document.getElementById("noVNC_keyboardinput") - .addEventListener('focus', UI.onfocusVirtualKeyboard); - document.getElementById("noVNC_keyboardinput") - .addEventListener('blur', UI.onblurVirtualKeyboard); - document.getElementById("noVNC_keyboardinput") - .addEventListener('submit', function () { return false; }); + document.getElementById("noVNC_keyboardinput") + .addEventListener('input', UI.keyInput); + document.getElementById("noVNC_keyboardinput") + .addEventListener('focus', UI.onfocusVirtualKeyboard); + document.getElementById("noVNC_keyboardinput") + .addEventListener('blur', UI.onblurVirtualKeyboard); + document.getElementById("noVNC_keyboardinput") + .addEventListener('submit', function () { return false; }); - document.documentElement - .addEventListener('mousedown', UI.keepVirtualKeyboard, true); + document.documentElement + .addEventListener('mousedown', UI.keepVirtualKeyboard, true); - document.getElementById("noVNC_control_bar") - .addEventListener('touchstart', UI.activateControlbar); - document.getElementById("noVNC_control_bar") - .addEventListener('touchmove', UI.activateControlbar); - document.getElementById("noVNC_control_bar") - .addEventListener('touchend', UI.activateControlbar); - document.getElementById("noVNC_control_bar") - .addEventListener('input', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('touchstart', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('touchmove', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('touchend', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('input', UI.activateControlbar); - document.getElementById("noVNC_control_bar") - .addEventListener('touchstart', UI.keepControlbar); - document.getElementById("noVNC_control_bar") - .addEventListener('input', UI.keepControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('touchstart', UI.keepControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('input', UI.keepControlbar); - document.getElementById("noVNC_control_bar_handle") - .addEventListener('touchstart', UI.controlbarHandleMouseDown); - document.getElementById("noVNC_control_bar_handle") - .addEventListener('touchend', UI.controlbarHandleMouseUp); - document.getElementById("noVNC_control_bar_handle") - .addEventListener('touchmove', UI.dragControlbarHandle); + document.getElementById("noVNC_control_bar_handle") + .addEventListener('touchstart', UI.controlbarHandleMouseDown); + document.getElementById("noVNC_control_bar_handle") + .addEventListener('touchend', UI.controlbarHandleMouseUp); + document.getElementById("noVNC_control_bar_handle") + .addEventListener('touchmove', UI.dragControlbarHandle); - window.addEventListener('load', UI.keyboardinputReset); - }, + window.addEventListener('load', UI.keyboardinputReset); + }, - addExtraKeysHandlers: function() { - document.getElementById("noVNC_toggle_extra_keys_button") - .addEventListener('click', UI.toggleExtraKeys); - document.getElementById("noVNC_toggle_ctrl_button") - .addEventListener('click', UI.toggleCtrl); - document.getElementById("noVNC_toggle_alt_button") - .addEventListener('click', UI.toggleAlt); - document.getElementById("noVNC_send_tab_button") - .addEventListener('click', UI.sendTab); - document.getElementById("noVNC_send_esc_button") - .addEventListener('click', UI.sendEsc); - document.getElementById("noVNC_send_ctrl_alt_del_button") - .addEventListener('click', UI.sendCtrlAltDel); - }, + addExtraKeysHandlers: function() { + document.getElementById("noVNC_toggle_extra_keys_button") + .addEventListener('click', UI.toggleExtraKeys); + document.getElementById("noVNC_toggle_ctrl_button") + .addEventListener('click', UI.toggleCtrl); + document.getElementById("noVNC_toggle_alt_button") + .addEventListener('click', UI.toggleAlt); + document.getElementById("noVNC_send_tab_button") + .addEventListener('click', UI.sendTab); + document.getElementById("noVNC_send_esc_button") + .addEventListener('click', UI.sendEsc); + document.getElementById("noVNC_send_ctrl_alt_del_button") + .addEventListener('click', UI.sendCtrlAltDel); + }, - addXvpHandlers: function() { - document.getElementById("noVNC_xvp_shutdown_button") - .addEventListener('click', function() { UI.rfb.xvpShutdown(); }); - document.getElementById("noVNC_xvp_reboot_button") - .addEventListener('click', function() { UI.rfb.xvpReboot(); }); - document.getElementById("noVNC_xvp_reset_button") - .addEventListener('click', function() { UI.rfb.xvpReset(); }); - document.getElementById("noVNC_xvp_button") - .addEventListener('click', UI.toggleXvpPanel); - }, + addXvpHandlers: function() { + document.getElementById("noVNC_xvp_shutdown_button") + .addEventListener('click', function() { UI.rfb.xvpShutdown(); }); + document.getElementById("noVNC_xvp_reboot_button") + .addEventListener('click', function() { UI.rfb.xvpReboot(); }); + document.getElementById("noVNC_xvp_reset_button") + .addEventListener('click', function() { UI.rfb.xvpReset(); }); + document.getElementById("noVNC_xvp_button") + .addEventListener('click', UI.toggleXvpPanel); + }, - addConnectionControlHandlers: function() { - document.getElementById("noVNC_disconnect_button") - .addEventListener('click', UI.disconnect); - document.getElementById("noVNC_connect_button") - .addEventListener('click', UI.connect); - document.getElementById("noVNC_cancel_reconnect_button") - .addEventListener('click', UI.cancelReconnect); + addConnectionControlHandlers: function() { + document.getElementById("noVNC_disconnect_button") + .addEventListener('click', UI.disconnect); + document.getElementById("noVNC_connect_button") + .addEventListener('click', UI.connect); + document.getElementById("noVNC_cancel_reconnect_button") + .addEventListener('click', UI.cancelReconnect); - document.getElementById("noVNC_password_button") - .addEventListener('click', UI.setPassword); - }, + document.getElementById("noVNC_password_button") + .addEventListener('click', UI.setPassword); + }, - addClipboardHandlers: function() { - document.getElementById("noVNC_clipboard_button") - .addEventListener('click', UI.toggleClipboardPanel); - document.getElementById("noVNC_clipboard_text") - .addEventListener('focus', UI.displayBlur); - document.getElementById("noVNC_clipboard_text") - .addEventListener('blur', UI.displayFocus); - document.getElementById("noVNC_clipboard_text") - .addEventListener('change', UI.clipboardSend); - document.getElementById("noVNC_clipboard_clear_button") - .addEventListener('click', UI.clipboardClear); - }, + addClipboardHandlers: function() { + document.getElementById("noVNC_clipboard_button") + .addEventListener('click', UI.toggleClipboardPanel); + document.getElementById("noVNC_clipboard_text") + .addEventListener('focus', UI.displayBlur); + document.getElementById("noVNC_clipboard_text") + .addEventListener('blur', UI.displayFocus); + document.getElementById("noVNC_clipboard_text") + .addEventListener('change', UI.clipboardSend); + document.getElementById("noVNC_clipboard_clear_button") + .addEventListener('click', UI.clipboardClear); + }, - // Add a call to save settings when the element changes, - // unless the optional parameter changeFunc is used instead. - addSettingChangeHandler: function(name, changeFunc) { - var settingElem = document.getElementById("noVNC_setting_" + name); - if (changeFunc === undefined) { - changeFunc = function () { UI.saveSetting(name); }; - } - settingElem.addEventListener('change', changeFunc); - }, + // Add a call to save settings when the element changes, + // unless the optional parameter changeFunc is used instead. + addSettingChangeHandler: function(name, changeFunc) { + var settingElem = document.getElementById("noVNC_setting_" + name); + if (changeFunc === undefined) { + changeFunc = function () { UI.saveSetting(name); }; + } + settingElem.addEventListener('change', changeFunc); + }, - addSettingsHandlers: function() { - document.getElementById("noVNC_settings_button") - .addEventListener('click', UI.toggleSettingsPanel); + addSettingsHandlers: function() { + document.getElementById("noVNC_settings_button") + .addEventListener('click', UI.toggleSettingsPanel); - UI.addSettingChangeHandler('encrypt'); - UI.addSettingChangeHandler('true_color'); - UI.addSettingChangeHandler('cursor'); - UI.addSettingChangeHandler('cursor', UI.updateLocalCursor); - UI.addSettingChangeHandler('resize'); - UI.addSettingChangeHandler('resize', UI.enableDisableViewClip); - UI.addSettingChangeHandler('resize', UI.applyResizeMode); - UI.addSettingChangeHandler('clip'); - UI.addSettingChangeHandler('clip', UI.updateViewClip); - UI.addSettingChangeHandler('shared'); - UI.addSettingChangeHandler('view_only'); - UI.addSettingChangeHandler('view_only', UI.updateViewOnly); - UI.addSettingChangeHandler('host'); - UI.addSettingChangeHandler('port'); - UI.addSettingChangeHandler('path'); - UI.addSettingChangeHandler('repeaterID'); - UI.addSettingChangeHandler('logging'); - UI.addSettingChangeHandler('logging', UI.updateLogging); - UI.addSettingChangeHandler('reconnect'); - UI.addSettingChangeHandler('reconnect_delay'); - }, + UI.addSettingChangeHandler('encrypt'); + UI.addSettingChangeHandler('true_color'); + UI.addSettingChangeHandler('cursor'); + UI.addSettingChangeHandler('cursor', UI.updateLocalCursor); + UI.addSettingChangeHandler('resize'); + UI.addSettingChangeHandler('resize', UI.enableDisableViewClip); + UI.addSettingChangeHandler('resize', UI.applyResizeMode); + UI.addSettingChangeHandler('clip'); + UI.addSettingChangeHandler('clip', UI.updateViewClip); + UI.addSettingChangeHandler('shared'); + UI.addSettingChangeHandler('view_only'); + UI.addSettingChangeHandler('view_only', UI.updateViewOnly); + UI.addSettingChangeHandler('host'); + UI.addSettingChangeHandler('port'); + UI.addSettingChangeHandler('path'); + UI.addSettingChangeHandler('repeaterID'); + UI.addSettingChangeHandler('logging'); + UI.addSettingChangeHandler('logging', UI.updateLogging); + UI.addSettingChangeHandler('reconnect'); + UI.addSettingChangeHandler('reconnect_delay'); + }, - addFullscreenHandlers: function() { - document.getElementById("noVNC_fullscreen_button") - .addEventListener('click', UI.toggleFullscreen); + addFullscreenHandlers: function() { + document.getElementById("noVNC_fullscreen_button") + .addEventListener('click', UI.toggleFullscreen); - window.addEventListener('fullscreenchange', UI.updateFullscreenButton); - window.addEventListener('mozfullscreenchange', UI.updateFullscreenButton); - window.addEventListener('webkitfullscreenchange', UI.updateFullscreenButton); - window.addEventListener('msfullscreenchange', UI.updateFullscreenButton); - }, + window.addEventListener('fullscreenchange', UI.updateFullscreenButton); + window.addEventListener('mozfullscreenchange', UI.updateFullscreenButton); + window.addEventListener('webkitfullscreenchange', UI.updateFullscreenButton); + window.addEventListener('msfullscreenchange', UI.updateFullscreenButton); + }, /* ------^------- * /EVENT HANDLERS @@ -475,341 +419,341 @@ var UI; * VISUAL * ------v------*/ - updateState: function(rfb, state, oldstate) { - var msg; + updateState: function(rfb, state, oldstate) { + var msg; - document.documentElement.classList.remove("noVNC_connecting"); - document.documentElement.classList.remove("noVNC_connected"); - document.documentElement.classList.remove("noVNC_disconnecting"); - document.documentElement.classList.remove("noVNC_reconnecting"); + document.documentElement.classList.remove("noVNC_connecting"); + document.documentElement.classList.remove("noVNC_connected"); + document.documentElement.classList.remove("noVNC_disconnecting"); + document.documentElement.classList.remove("noVNC_reconnecting"); - switch (state) { - case 'connecting': - document.getElementById("noVNC_transition_text").textContent = _("Connecting..."); - document.documentElement.classList.add("noVNC_connecting"); - break; - case 'connected': - UI.connected = true; - UI.inhibit_reconnect = false; - document.documentElement.classList.add("noVNC_connected"); - if (rfb && rfb.get_encrypt()) { - msg = _("Connected (encrypted) to ") + UI.desktopName; - } else { - msg = _("Connected (unencrypted) to ") + UI.desktopName; - } - UI.showStatus(msg); - break; - case 'disconnecting': - UI.connected = false; - document.getElementById("noVNC_transition_text").textContent = _("Disconnecting..."); - document.documentElement.classList.add("noVNC_disconnecting"); - break; - case 'disconnected': - UI.showStatus(_("Disconnected")); - break; - default: - msg = "Invalid UI state"; - Util.Error(msg); - UI.showStatus(msg, 'error'); - break; - } + switch (state) { + case 'connecting': + document.getElementById("noVNC_transition_text").textContent = _("Connecting..."); + document.documentElement.classList.add("noVNC_connecting"); + break; + case 'connected': + UI.connected = true; + UI.inhibit_reconnect = false; + document.documentElement.classList.add("noVNC_connected"); + if (rfb && rfb.get_encrypt()) { + msg = _("Connected (encrypted) to ") + UI.desktopName; + } else { + msg = _("Connected (unencrypted) to ") + UI.desktopName; + } + UI.showStatus(msg); + break; + case 'disconnecting': + UI.connected = false; + document.getElementById("noVNC_transition_text").textContent = _("Disconnecting..."); + document.documentElement.classList.add("noVNC_disconnecting"); + break; + case 'disconnected': + UI.showStatus(_("Disconnected")); + break; + default: + msg = "Invalid UI state"; + Log.Error(msg); + UI.showStatus(msg, 'error'); + break; + } - UI.updateVisualState(); - }, + UI.updateVisualState(); + }, - // Disable/enable controls depending on connection state - updateVisualState: function() { - //Util.Debug(">> updateVisualState"); + // Disable/enable controls depending on connection state + updateVisualState: function() { + //Log.Debug(">> updateVisualState"); - UI.enableDisableViewClip(); + UI.enableDisableViewClip(); - if (Util.browserSupportsCursorURIs() && !Util.isTouchDevice) { - UI.enableSetting('cursor'); - } else { - UI.disableSetting('cursor'); - } + if (cursorURIsSupported() && !isTouchDevice) { + UI.enableSetting('cursor'); + } else { + UI.disableSetting('cursor'); + } - if (UI.connected) { - UI.disableSetting('encrypt'); - UI.disableSetting('true_color'); - UI.disableSetting('shared'); - UI.disableSetting('host'); - UI.disableSetting('port'); - UI.disableSetting('path'); - UI.disableSetting('repeaterID'); - UI.updateViewClip(); - UI.setMouseButton(1); + if (UI.connected) { + UI.disableSetting('encrypt'); + UI.disableSetting('true_color'); + UI.disableSetting('shared'); + UI.disableSetting('host'); + UI.disableSetting('port'); + UI.disableSetting('path'); + UI.disableSetting('repeaterID'); + UI.updateViewClip(); + UI.setMouseButton(1); - // Hide the controlbar after 2 seconds - UI.closeControlbarTimeout = setTimeout(UI.closeControlbar, 2000); - } else { - UI.enableSetting('encrypt'); - UI.enableSetting('true_color'); - UI.enableSetting('shared'); - UI.enableSetting('host'); - UI.enableSetting('port'); - UI.enableSetting('path'); - UI.enableSetting('repeaterID'); - UI.updateXvpButton(0); - UI.keepControlbar(); - } + // Hide the controlbar after 2 seconds + UI.closeControlbarTimeout = setTimeout(UI.closeControlbar, 2000); + } else { + UI.enableSetting('encrypt'); + UI.enableSetting('true_color'); + UI.enableSetting('shared'); + UI.enableSetting('host'); + UI.enableSetting('port'); + UI.enableSetting('path'); + UI.enableSetting('repeaterID'); + UI.updateXvpButton(0); + UI.keepControlbar(); + } - // Hide input related buttons in view only mode - if (UI.rfb && UI.rfb.get_view_only()) { - document.getElementById('noVNC_keyboard_button') - .classList.add('noVNC_hidden'); - document.getElementById('noVNC_toggle_extra_keys_button') - .classList.add('noVNC_hidden'); - } else { - document.getElementById('noVNC_keyboard_button') - .classList.remove('noVNC_hidden'); - document.getElementById('noVNC_toggle_extra_keys_button') - .classList.remove('noVNC_hidden'); - } + // Hide input related buttons in view only mode + if (UI.rfb && UI.rfb.get_view_only()) { + document.getElementById('noVNC_keyboard_button') + .classList.add('noVNC_hidden'); + document.getElementById('noVNC_toggle_extra_keys_button') + .classList.add('noVNC_hidden'); + } else { + document.getElementById('noVNC_keyboard_button') + .classList.remove('noVNC_hidden'); + document.getElementById('noVNC_toggle_extra_keys_button') + .classList.remove('noVNC_hidden'); + } - // State change disables viewport dragging. - // It is enabled (toggled) by direct click on the button - UI.setViewDrag(false); + // State change disables viewport dragging. + // It is enabled (toggled) by direct click on the button + UI.setViewDrag(false); - // State change also closes the password dialog - document.getElementById('noVNC_password_dlg') - .classList.remove('noVNC_open'); + // State change also closes the password dialog + document.getElementById('noVNC_password_dlg') + .classList.remove('noVNC_open'); - //Util.Debug("<< updateVisualState"); - }, + //Log.Debug("<< updateVisualState"); + }, - showStatus: function(text, status_type, time) { - var statusElem = document.getElementById('noVNC_status'); + showStatus: function(text, status_type, time) { + var statusElem = document.getElementById('noVNC_status'); - clearTimeout(UI.statusTimeout); + clearTimeout(UI.statusTimeout); - if (typeof status_type === 'undefined') { - status_type = 'normal'; - } + if (typeof status_type === 'undefined') { + status_type = 'normal'; + } - statusElem.classList.remove("noVNC_status_normal"); - statusElem.classList.remove("noVNC_status_warn"); - statusElem.classList.remove("noVNC_status_error"); + statusElem.classList.remove("noVNC_status_normal"); + statusElem.classList.remove("noVNC_status_warn"); + statusElem.classList.remove("noVNC_status_error"); - switch (status_type) { - case 'warning': - case 'warn': - statusElem.classList.add("noVNC_status_warn"); - break; - case 'error': - statusElem.classList.add("noVNC_status_error"); - break; - case 'normal': - case 'info': - default: - statusElem.classList.add("noVNC_status_normal"); - break; - } + switch (status_type) { + case 'warning': + case 'warn': + statusElem.classList.add("noVNC_status_warn"); + break; + case 'error': + statusElem.classList.add("noVNC_status_error"); + break; + case 'normal': + case 'info': + default: + statusElem.classList.add("noVNC_status_normal"); + break; + } - statusElem.textContent = text; - statusElem.classList.add("noVNC_open"); + statusElem.textContent = text; + statusElem.classList.add("noVNC_open"); - // If no time was specified, show the status for 1.5 seconds - if (typeof time === 'undefined') { - time = 1500; - } + // If no time was specified, show the status for 1.5 seconds + if (typeof time === 'undefined') { + time = 1500; + } - // Error messages do not timeout - if (status_type !== 'error') { - UI.statusTimeout = window.setTimeout(UI.hideStatus, time); - } - }, + // Error messages do not timeout + if (status_type !== 'error') { + UI.statusTimeout = window.setTimeout(UI.hideStatus, time); + } + }, - hideStatus: function() { - clearTimeout(UI.statusTimeout); - document.getElementById('noVNC_status').classList.remove("noVNC_open"); - }, + hideStatus: function() { + clearTimeout(UI.statusTimeout); + document.getElementById('noVNC_status').classList.remove("noVNC_open"); + }, - notification: function (rfb, msg, level, options) { - UI.showStatus(msg, level); - }, + notification: function (rfb, msg, level, options) { + UI.showStatus(msg, level); + }, - activateControlbar: function(event) { - clearTimeout(UI.idleControlbarTimeout); - // We manipulate the anchor instead of the actual control - // bar in order to avoid creating new a stacking group - document.getElementById('noVNC_control_bar_anchor') - .classList.remove("noVNC_idle"); - UI.idleControlbarTimeout = window.setTimeout(UI.idleControlbar, 2000); - }, + activateControlbar: function(event) { + clearTimeout(UI.idleControlbarTimeout); + // We manipulate the anchor instead of the actual control + // bar in order to avoid creating new a stacking group + document.getElementById('noVNC_control_bar_anchor') + .classList.remove("noVNC_idle"); + UI.idleControlbarTimeout = window.setTimeout(UI.idleControlbar, 2000); + }, - idleControlbar: function() { - document.getElementById('noVNC_control_bar_anchor') - .classList.add("noVNC_idle"); - }, + idleControlbar: function() { + document.getElementById('noVNC_control_bar_anchor') + .classList.add("noVNC_idle"); + }, - keepControlbar: function() { - clearTimeout(UI.closeControlbarTimeout); - }, + keepControlbar: function() { + clearTimeout(UI.closeControlbarTimeout); + }, - openControlbar: function() { - document.getElementById('noVNC_control_bar') - .classList.add("noVNC_open"); - }, + openControlbar: function() { + document.getElementById('noVNC_control_bar') + .classList.add("noVNC_open"); + }, - closeControlbar: function() { - UI.closeAllPanels(); - document.getElementById('noVNC_control_bar') - .classList.remove("noVNC_open"); - }, + closeControlbar: function() { + UI.closeAllPanels(); + document.getElementById('noVNC_control_bar') + .classList.remove("noVNC_open"); + }, - toggleControlbar: function() { - if (document.getElementById('noVNC_control_bar') - .classList.contains("noVNC_open")) { - UI.closeControlbar(); - } else { - UI.openControlbar(); - } - }, + toggleControlbar: function() { + if (document.getElementById('noVNC_control_bar') + .classList.contains("noVNC_open")) { + UI.closeControlbar(); + } else { + UI.openControlbar(); + } + }, - toggleControlbarSide: function () { - // Temporarily disable animation to avoid weird movement - var bar = document.getElementById('noVNC_control_bar'); - bar.style.transitionDuration = '0s'; - bar.addEventListener('transitionend', function () { this.style.transitionDuration = ""; }); + toggleControlbarSide: function () { + // Temporarily disable animation to avoid weird movement + var bar = document.getElementById('noVNC_control_bar'); + bar.style.transitionDuration = '0s'; + bar.addEventListener('transitionend', function () { this.style.transitionDuration = ""; }); - var anchor = document.getElementById('noVNC_control_bar_anchor'); + var anchor = document.getElementById('noVNC_control_bar_anchor'); + if (anchor.classList.contains("noVNC_right")) { + WebUtil.writeSetting('controlbar_pos', 'left'); + anchor.classList.remove("noVNC_right"); + } else { + WebUtil.writeSetting('controlbar_pos', 'right'); + anchor.classList.add("noVNC_right"); + } + + // Consider this a movement of the handle + UI.controlbarDrag = true; + }, + + dragControlbarHandle: function (e) { + if (!UI.controlbarGrabbed) return; + + var ptr = getPointerEvent(e); + + var anchor = document.getElementById('noVNC_control_bar_anchor'); + if (ptr.clientX < (window.innerWidth * 0.1)) { if (anchor.classList.contains("noVNC_right")) { - WebUtil.writeSetting('controlbar_pos', 'left'); - anchor.classList.remove("noVNC_right"); - } else { - WebUtil.writeSetting('controlbar_pos', 'right'); - anchor.classList.add("noVNC_right"); + UI.toggleControlbarSide(); } + } else if (ptr.clientX > (window.innerWidth * 0.9)) { + if (!anchor.classList.contains("noVNC_right")) { + UI.toggleControlbarSide(); + } + } + + if (!UI.controlbarDrag) { + // The goal is to trigger on a certain physical width, the + // devicePixelRatio brings us a bit closer but is not optimal. + var dragThreshold = 10 * (window.devicePixelRatio || 1); + var dragDistance = Math.abs(ptr.clientY - UI.controlbarMouseDownClientY); + + if (dragDistance < dragThreshold) return; - // Consider this a movement of the handle UI.controlbarDrag = true; - }, + } - dragControlbarHandle: function (e) { - if (!UI.controlbarGrabbed) return; + var eventY = ptr.clientY - UI.controlbarMouseDownOffsetY; - var ptr = Util.getPointerEvent(e); + UI.moveControlbarHandle(eventY); - var anchor = document.getElementById('noVNC_control_bar_anchor'); - if (ptr.clientX < (window.innerWidth * 0.1)) { - if (anchor.classList.contains("noVNC_right")) { - UI.toggleControlbarSide(); - } - } else if (ptr.clientX > (window.innerWidth * 0.9)) { - if (!anchor.classList.contains("noVNC_right")) { - UI.toggleControlbarSide(); - } - } + e.preventDefault(); + e.stopPropagation(); + UI.keepControlbar(); + UI.activateControlbar(); + }, - if (!UI.controlbarDrag) { - // The goal is to trigger on a certain physical width, the - // devicePixelRatio brings us a bit closer but is not optimal. - var dragThreshold = 10 * (window.devicePixelRatio || 1); - var dragDistance = Math.abs(ptr.clientY - UI.controlbarMouseDownClientY); + // Move the handle but don't allow any position outside the bounds + moveControlbarHandle: function (viewportRelativeY) { + var handle = document.getElementById("noVNC_control_bar_handle"); + var handleHeight = handle.getBoundingClientRect().height; + var controlbarBounds = document.getElementById("noVNC_control_bar") + .getBoundingClientRect(); + var margin = 10; - if (dragDistance < dragThreshold) return; + // These heights need to be non-zero for the below logic to work + if (handleHeight === 0 || controlbarBounds.height === 0) { + return; + } - UI.controlbarDrag = true; - } + var newY = viewportRelativeY; - var eventY = ptr.clientY - UI.controlbarMouseDownOffsetY; + // Check if the coordinates are outside the control bar + if (newY < controlbarBounds.top + margin) { + // Force coordinates to be below the top of the control bar + newY = controlbarBounds.top + margin; - UI.moveControlbarHandle(eventY); + } else if (newY > controlbarBounds.top + + controlbarBounds.height - handleHeight - margin) { + // Force coordinates to be above the bottom of the control bar + newY = controlbarBounds.top + + controlbarBounds.height - handleHeight - margin; + } + // Corner case: control bar too small for stable position + if (controlbarBounds.height < (handleHeight + margin * 2)) { + newY = controlbarBounds.top + + (controlbarBounds.height - handleHeight) / 2; + } + + // The transform needs coordinates that are relative to the parent + var parentRelativeY = newY - controlbarBounds.top; + handle.style.transform = "translateY(" + parentRelativeY + "px)"; + }, + + updateControlbarHandle: function () { + // Since the control bar is fixed on the viewport and not the page, + // the move function expects coordinates relative the the viewport. + var handle = document.getElementById("noVNC_control_bar_handle"); + var handleBounds = handle.getBoundingClientRect(); + UI.moveControlbarHandle(handleBounds.top); + }, + + controlbarHandleMouseUp: function(e) { + if ((e.type == "mouseup") && (e.button != 0)) return; + + // mouseup and mousedown on the same place toggles the controlbar + if (UI.controlbarGrabbed && !UI.controlbarDrag) { + UI.toggleControlbar(); e.preventDefault(); e.stopPropagation(); UI.keepControlbar(); UI.activateControlbar(); - }, + } + UI.controlbarGrabbed = false; + }, - // Move the handle but don't allow any position outside the bounds - moveControlbarHandle: function (viewportRelativeY) { - var handle = document.getElementById("noVNC_control_bar_handle"); - var handleHeight = handle.getBoundingClientRect().height; - var controlbarBounds = document.getElementById("noVNC_control_bar") - .getBoundingClientRect(); - var margin = 10; + controlbarHandleMouseDown: function(e) { + if ((e.type == "mousedown") && (e.button != 0)) return; - // These heights need to be non-zero for the below logic to work - if (handleHeight === 0 || controlbarBounds.height === 0) { - return; - } + var ptr = getPointerEvent(e); - var newY = viewportRelativeY; + var handle = document.getElementById("noVNC_control_bar_handle"); + var bounds = handle.getBoundingClientRect(); - // Check if the coordinates are outside the control bar - if (newY < controlbarBounds.top + margin) { - // Force coordinates to be below the top of the control bar - newY = controlbarBounds.top + margin; + setCapture(handle); + UI.controlbarGrabbed = true; + UI.controlbarDrag = false; - } else if (newY > controlbarBounds.top + - controlbarBounds.height - handleHeight - margin) { - // Force coordinates to be above the bottom of the control bar - newY = controlbarBounds.top + - controlbarBounds.height - handleHeight - margin; - } + UI.controlbarMouseDownClientY = ptr.clientY; + UI.controlbarMouseDownOffsetY = ptr.clientY - bounds.top; + e.preventDefault(); + e.stopPropagation(); + UI.keepControlbar(); + UI.activateControlbar(); + }, - // Corner case: control bar too small for stable position - if (controlbarBounds.height < (handleHeight + margin * 2)) { - newY = controlbarBounds.top + - (controlbarBounds.height - handleHeight) / 2; - } - - // The transform needs coordinates that are relative to the parent - var parentRelativeY = newY - controlbarBounds.top; - handle.style.transform = "translateY(" + parentRelativeY + "px)"; - }, - - updateControlbarHandle: function () { - // Since the control bar is fixed on the viewport and not the page, - // the move function expects coordinates relative the the viewport. - var handle = document.getElementById("noVNC_control_bar_handle"); - var handleBounds = handle.getBoundingClientRect(); - UI.moveControlbarHandle(handleBounds.top); - }, - - controlbarHandleMouseUp: function(e) { - if ((e.type == "mouseup") && (e.button != 0)) return; - - // mouseup and mousedown on the same place toggles the controlbar - if (UI.controlbarGrabbed && !UI.controlbarDrag) { - UI.toggleControlbar(); - e.preventDefault(); - e.stopPropagation(); - UI.keepControlbar(); - UI.activateControlbar(); - } - UI.controlbarGrabbed = false; - }, - - controlbarHandleMouseDown: function(e) { - if ((e.type == "mousedown") && (e.button != 0)) return; - - var ptr = Util.getPointerEvent(e); - - var handle = document.getElementById("noVNC_control_bar_handle"); - var bounds = handle.getBoundingClientRect(); - - Util.setCapture(handle); - UI.controlbarGrabbed = true; - UI.controlbarDrag = false; - - UI.controlbarMouseDownClientY = ptr.clientY; - UI.controlbarMouseDownOffsetY = ptr.clientY - bounds.top; - e.preventDefault(); - e.stopPropagation(); - UI.keepControlbar(); - UI.activateControlbar(); - }, - - toggleExpander: function(e) { - if (this.classList.contains("noVNC_open")) { - this.classList.remove("noVNC_open"); - } else { - this.classList.add("noVNC_open"); - } - }, + toggleExpander: function(e) { + if (this.classList.contains("noVNC_open")) { + this.classList.remove("noVNC_open"); + } else { + this.classList.add("noVNC_open"); + } + }, /* ------^------- * /VISUAL @@ -817,93 +761,93 @@ var UI; * SETTINGS * ------v------*/ - // Initial page load read/initialization of settings - initSetting: function(name, defVal) { - // Check Query string followed by cookie - var val = WebUtil.getConfigVar(name); - if (val === null) { - val = WebUtil.readSetting(name, defVal); - } - UI.updateSetting(name, val); - return val; - }, + // Initial page load read/initialization of settings + initSetting: function(name, defVal) { + // Check Query string followed by cookie + var val = WebUtil.getConfigVar(name); + if (val === null) { + val = WebUtil.readSetting(name, defVal); + } + UI.updateSetting(name, val); + return val; + }, - // Update cookie and form control setting. If value is not set, then - // updates from control to current cookie setting. - updateSetting: function(name, value) { + // Update cookie and form control setting. If value is not set, then + // updates from control to current cookie setting. + updateSetting: function(name, value) { - // Save the cookie for this session - if (typeof value !== 'undefined') { - WebUtil.writeSetting(name, value); - } + // Save the cookie for this session + if (typeof value !== 'undefined') { + WebUtil.writeSetting(name, value); + } - // Update the settings control - value = UI.getSetting(name); + // Update the settings control + value = UI.getSetting(name); - var ctrl = document.getElementById('noVNC_setting_' + name); - if (ctrl.type === 'checkbox') { - ctrl.checked = value; + var ctrl = document.getElementById('noVNC_setting_' + name); + if (ctrl.type === 'checkbox') { + ctrl.checked = value; - } else if (typeof ctrl.options !== 'undefined') { - for (var i = 0; i < ctrl.options.length; i += 1) { - if (ctrl.options[i].value === value) { - ctrl.selectedIndex = i; - break; - } + } else if (typeof ctrl.options !== 'undefined') { + for (var i = 0; i < ctrl.options.length; i += 1) { + if (ctrl.options[i].value === value) { + ctrl.selectedIndex = i; + break; } + } + } else { + /*Weird IE9 error leads to 'null' appearring + in textboxes instead of ''.*/ + if (value === null) { + value = ""; + } + ctrl.value = value; + } + }, + + // Save control setting to cookie + saveSetting: function(name) { + var val, ctrl = document.getElementById('noVNC_setting_' + name); + if (ctrl.type === 'checkbox') { + val = ctrl.checked; + } else if (typeof ctrl.options !== 'undefined') { + val = ctrl.options[ctrl.selectedIndex].value; + } else { + val = ctrl.value; + } + WebUtil.writeSetting(name, val); + //Log.Debug("Setting saved '" + name + "=" + val + "'"); + return val; + }, + + // Read form control compatible setting from cookie + getSetting: function(name) { + var ctrl = document.getElementById('noVNC_setting_' + name); + var val = WebUtil.readSetting(name); + if (typeof val !== 'undefined' && val !== null && ctrl.type === 'checkbox') { + if (val.toString().toLowerCase() in {'0':1, 'no':1, 'false':1}) { + val = false; } else { - /*Weird IE9 error leads to 'null' appearring - in textboxes instead of ''.*/ - if (value === null) { - value = ""; - } - ctrl.value = value; + val = true; } - }, + } + return val; + }, - // Save control setting to cookie - saveSetting: function(name) { - var val, ctrl = document.getElementById('noVNC_setting_' + name); - if (ctrl.type === 'checkbox') { - val = ctrl.checked; - } else if (typeof ctrl.options !== 'undefined') { - val = ctrl.options[ctrl.selectedIndex].value; - } else { - val = ctrl.value; - } - WebUtil.writeSetting(name, val); - //Util.Debug("Setting saved '" + name + "=" + val + "'"); - return val; - }, + // These helpers compensate for the lack of parent-selectors and + // previous-sibling-selectors in CSS which are needed when we want to + // disable the labels that belong to disabled input elements. + disableSetting: function(name) { + var ctrl = document.getElementById('noVNC_setting_' + name); + ctrl.disabled = true; + ctrl.label.classList.add('noVNC_disabled'); + }, - // Read form control compatible setting from cookie - getSetting: function(name) { - var ctrl = document.getElementById('noVNC_setting_' + name); - var val = WebUtil.readSetting(name); - if (typeof val !== 'undefined' && val !== null && ctrl.type === 'checkbox') { - if (val.toString().toLowerCase() in {'0':1, 'no':1, 'false':1}) { - val = false; - } else { - val = true; - } - } - return val; - }, - - // These helpers compensate for the lack of parent-selectors and - // previous-sibling-selectors in CSS which are needed when we want to - // disable the labels that belong to disabled input elements. - disableSetting: function(name) { - var ctrl = document.getElementById('noVNC_setting_' + name); - ctrl.disabled = true; - ctrl.label.classList.add('noVNC_disabled'); - }, - - enableSetting: function(name) { - var ctrl = document.getElementById('noVNC_setting_' + name); - ctrl.disabled = false; - ctrl.label.classList.remove('noVNC_disabled'); - }, + enableSetting: function(name) { + var ctrl = document.getElementById('noVNC_setting_' + name); + ctrl.disabled = false; + ctrl.label.classList.remove('noVNC_disabled'); + }, /* ------^------- * /SETTINGS @@ -911,12 +855,12 @@ var UI; * PANELS * ------v------*/ - closeAllPanels: function() { - UI.closeSettingsPanel(); - UI.closeXvpPanel(); - UI.closeClipboardPanel(); - UI.closeExtraKeys(); - }, + closeAllPanels: function() { + UI.closeSettingsPanel(); + UI.closeXvpPanel(); + UI.closeClipboardPanel(); + UI.closeExtraKeys(); + }, /* ------^------- * /PANELS @@ -924,50 +868,50 @@ var UI; * SETTINGS (panel) * ------v------*/ - openSettingsPanel: function() { - UI.closeAllPanels(); - UI.openControlbar(); + openSettingsPanel: function() { + UI.closeAllPanels(); + UI.openControlbar(); - // Refresh UI elements from saved cookies - UI.updateSetting('encrypt'); - UI.updateSetting('true_color'); - if (Util.browserSupportsCursorURIs()) { - UI.updateSetting('cursor'); - } else { - UI.updateSetting('cursor', !Util.isTouchDevice); - UI.disableSetting('cursor'); - } - UI.updateSetting('clip'); - UI.updateSetting('resize'); - UI.updateSetting('shared'); - UI.updateSetting('view_only'); - UI.updateSetting('path'); - UI.updateSetting('repeaterID'); - UI.updateSetting('logging'); - UI.updateSetting('reconnect'); - UI.updateSetting('reconnect_delay'); + // Refresh UI elements from saved cookies + UI.updateSetting('encrypt'); + UI.updateSetting('true_color'); + if (cursorURIsSupported()) { + UI.updateSetting('cursor'); + } else { + UI.updateSetting('cursor', !isTouchDevice); + UI.disableSetting('cursor'); + } + UI.updateSetting('clip'); + UI.updateSetting('resize'); + UI.updateSetting('shared'); + UI.updateSetting('view_only'); + UI.updateSetting('path'); + UI.updateSetting('repeaterID'); + UI.updateSetting('logging'); + UI.updateSetting('reconnect'); + UI.updateSetting('reconnect_delay'); - document.getElementById('noVNC_settings') - .classList.add("noVNC_open"); - document.getElementById('noVNC_settings_button') - .classList.add("noVNC_selected"); - }, + document.getElementById('noVNC_settings') + .classList.add("noVNC_open"); + document.getElementById('noVNC_settings_button') + .classList.add("noVNC_selected"); + }, - closeSettingsPanel: function() { - document.getElementById('noVNC_settings') - .classList.remove("noVNC_open"); - document.getElementById('noVNC_settings_button') - .classList.remove("noVNC_selected"); - }, + closeSettingsPanel: function() { + document.getElementById('noVNC_settings') + .classList.remove("noVNC_open"); + document.getElementById('noVNC_settings_button') + .classList.remove("noVNC_selected"); + }, - toggleSettingsPanel: function() { - if (document.getElementById('noVNC_settings') - .classList.contains("noVNC_open")) { - UI.closeSettingsPanel(); - } else { - UI.openSettingsPanel(); - } - }, + toggleSettingsPanel: function() { + if (document.getElementById('noVNC_settings') + .classList.contains("noVNC_open")) { + UI.closeSettingsPanel(); + } else { + UI.openSettingsPanel(); + } + }, /* ------^------- * /SETTINGS @@ -975,44 +919,44 @@ var UI; * XVP * ------v------*/ - openXvpPanel: function() { - UI.closeAllPanels(); - UI.openControlbar(); + openXvpPanel: function() { + UI.closeAllPanels(); + UI.openControlbar(); - document.getElementById('noVNC_xvp') - .classList.add("noVNC_open"); + document.getElementById('noVNC_xvp') + .classList.add("noVNC_open"); + document.getElementById('noVNC_xvp_button') + .classList.add("noVNC_selected"); + }, + + closeXvpPanel: function() { + document.getElementById('noVNC_xvp') + .classList.remove("noVNC_open"); + document.getElementById('noVNC_xvp_button') + .classList.remove("noVNC_selected"); + }, + + toggleXvpPanel: function() { + if (document.getElementById('noVNC_xvp') + .classList.contains("noVNC_open")) { + UI.closeXvpPanel(); + } else { + UI.openXvpPanel(); + } + }, + + // Disable/enable XVP button + updateXvpButton: function(ver) { + if (ver >= 1 && !UI.rfb.get_view_only()) { document.getElementById('noVNC_xvp_button') - .classList.add("noVNC_selected"); - }, - - closeXvpPanel: function() { - document.getElementById('noVNC_xvp') - .classList.remove("noVNC_open"); + .classList.remove("noVNC_hidden"); + } else { document.getElementById('noVNC_xvp_button') - .classList.remove("noVNC_selected"); - }, - - toggleXvpPanel: function() { - if (document.getElementById('noVNC_xvp') - .classList.contains("noVNC_open")) { - UI.closeXvpPanel(); - } else { - UI.openXvpPanel(); - } - }, - - // Disable/enable XVP button - updateXvpButton: function(ver) { - if (ver >= 1 && !UI.rfb.get_view_only()) { - document.getElementById('noVNC_xvp_button') - .classList.remove("noVNC_hidden"); - } else { - document.getElementById('noVNC_xvp_button') - .classList.add("noVNC_hidden"); - // Close XVP panel if open - UI.closeXvpPanel(); - } - }, + .classList.add("noVNC_hidden"); + // Close XVP panel if open + UI.closeXvpPanel(); + } + }, /* ------^------- * /XVP @@ -1020,49 +964,49 @@ var UI; * CLIPBOARD * ------v------*/ - openClipboardPanel: function() { - UI.closeAllPanels(); - UI.openControlbar(); + openClipboardPanel: function() { + UI.closeAllPanels(); + UI.openControlbar(); - document.getElementById('noVNC_clipboard') - .classList.add("noVNC_open"); - document.getElementById('noVNC_clipboard_button') - .classList.add("noVNC_selected"); - }, + document.getElementById('noVNC_clipboard') + .classList.add("noVNC_open"); + document.getElementById('noVNC_clipboard_button') + .classList.add("noVNC_selected"); + }, - closeClipboardPanel: function() { - document.getElementById('noVNC_clipboard') - .classList.remove("noVNC_open"); - document.getElementById('noVNC_clipboard_button') - .classList.remove("noVNC_selected"); - }, + closeClipboardPanel: function() { + document.getElementById('noVNC_clipboard') + .classList.remove("noVNC_open"); + document.getElementById('noVNC_clipboard_button') + .classList.remove("noVNC_selected"); + }, - toggleClipboardPanel: function() { - if (document.getElementById('noVNC_clipboard') - .classList.contains("noVNC_open")) { - UI.closeClipboardPanel(); - } else { - UI.openClipboardPanel(); - } - }, + toggleClipboardPanel: function() { + if (document.getElementById('noVNC_clipboard') + .classList.contains("noVNC_open")) { + UI.closeClipboardPanel(); + } else { + UI.openClipboardPanel(); + } + }, - clipboardReceive: function(rfb, text) { - Util.Debug(">> UI.clipboardReceive: " + text.substr(0,40) + "..."); - document.getElementById('noVNC_clipboard_text').value = text; - Util.Debug("<< UI.clipboardReceive"); - }, + clipboardReceive: function(rfb, text) { + Log.Debug(">> UI.clipboardReceive: " + text.substr(0,40) + "..."); + document.getElementById('noVNC_clipboard_text').value = text; + Log.Debug("<< UI.clipboardReceive"); + }, - clipboardClear: function() { - document.getElementById('noVNC_clipboard_text').value = ""; - UI.rfb.clipboardPasteFrom(""); - }, + clipboardClear: function() { + document.getElementById('noVNC_clipboard_text').value = ""; + UI.rfb.clipboardPasteFrom(""); + }, - clipboardSend: function() { - var text = document.getElementById('noVNC_clipboard_text').value; - Util.Debug(">> UI.clipboardSend: " + text.substr(0,40) + "..."); - UI.rfb.clipboardPasteFrom(text); - Util.Debug("<< UI.clipboardSend"); - }, + clipboardSend: function() { + var text = document.getElementById('noVNC_clipboard_text').value; + Log.Debug(">> UI.clipboardSend: " + text.substr(0,40) + "..."); + UI.rfb.clipboardPasteFrom(text); + Log.Debug("<< UI.clipboardSend"); + }, /* ------^------- * /CLIPBOARD @@ -1070,102 +1014,102 @@ var UI; * CONNECTION * ------v------*/ - openConnectPanel: function() { - document.getElementById('noVNC_connect_dlg') - .classList.add("noVNC_open"); - }, + openConnectPanel: function() { + document.getElementById('noVNC_connect_dlg') + .classList.add("noVNC_open"); + }, - closeConnectPanel: function() { - document.getElementById('noVNC_connect_dlg') - .classList.remove("noVNC_open"); - }, + closeConnectPanel: function() { + document.getElementById('noVNC_connect_dlg') + .classList.remove("noVNC_open"); + }, - connect: function(event, password) { - var host = UI.getSetting('host'); - var port = UI.getSetting('port'); - var path = UI.getSetting('path'); + connect: function(event, password) { + var host = UI.getSetting('host'); + var port = UI.getSetting('port'); + var path = UI.getSetting('path'); - if (typeof password === 'undefined') { - password = WebUtil.getConfigVar('password'); - } + if (typeof password === 'undefined') { + password = WebUtil.getConfigVar('password'); + } - if (password === null) { - password = undefined; - } + if (password === null) { + password = undefined; + } - if ((!host) || (!port)) { - var msg = _("Must set host and port"); - Util.Error(msg); - UI.showStatus(msg, 'error'); - return; - } + if ((!host) || (!port)) { + var msg = _("Must set host and port"); + Log.Error(msg); + UI.showStatus(msg, 'error'); + return; + } - if (!UI.initRFB()) return; + if (!UI.initRFB()) return; - UI.closeAllPanels(); - UI.closeConnectPanel(); + UI.closeAllPanels(); + UI.closeConnectPanel(); - UI.rfb.set_encrypt(UI.getSetting('encrypt')); - UI.rfb.set_true_color(UI.getSetting('true_color')); - UI.rfb.set_shared(UI.getSetting('shared')); - UI.rfb.set_repeaterID(UI.getSetting('repeaterID')); + UI.rfb.set_encrypt(UI.getSetting('encrypt')); + UI.rfb.set_true_color(UI.getSetting('true_color')); + UI.rfb.set_shared(UI.getSetting('shared')); + UI.rfb.set_repeaterID(UI.getSetting('repeaterID')); - UI.updateLocalCursor(); - UI.updateViewOnly(); + UI.updateLocalCursor(); + UI.updateViewOnly(); - UI.rfb.connect(host, port, password, path); - }, + UI.rfb.connect(host, port, password, path); + }, - disconnect: function() { - UI.closeAllPanels(); - UI.rfb.disconnect(); + disconnect: function() { + UI.closeAllPanels(); + UI.rfb.disconnect(); - // Disable automatic reconnecting - UI.inhibit_reconnect = true; + // Disable automatic reconnecting + UI.inhibit_reconnect = true; - // Restore the callback used for initial resize - UI.rfb.set_onFBUComplete(UI.initialResize); + // Restore the callback used for initial resize + UI.rfb.set_onFBUComplete(UI.initialResize); - // Don't display the connection settings until we're actually disconnected - }, + // Don't display the connection settings until we're actually disconnected + }, - reconnect: function() { + reconnect: function() { + UI.reconnect_callback = null; + + // if reconnect has been disabled in the meantime, do nothing. + if (UI.inhibit_reconnect) { + return; + } + + UI.connect(null, UI.reconnect_password); + }, + + disconnectFinished: function (rfb, reason) { + if (typeof reason !== 'undefined') { + UI.showStatus(reason, 'error'); + } else if (UI.getSetting('reconnect', false) === true && !UI.inhibit_reconnect) { + document.getElementById("noVNC_transition_text").textContent = _("Reconnecting..."); + document.documentElement.classList.add("noVNC_reconnecting"); + + var delay = parseInt(UI.getSetting('reconnect_delay')); + UI.reconnect_callback = setTimeout(UI.reconnect, delay); + return; + } + + UI.openControlbar(); + UI.openConnectPanel(); + }, + + cancelReconnect: function() { + if (UI.reconnect_callback !== null) { + clearTimeout(UI.reconnect_callback); UI.reconnect_callback = null; + } - // if reconnect has been disabled in the meantime, do nothing. - if (UI.inhibit_reconnect) { - return; - } - - UI.connect(null, UI.reconnect_password); - }, - - disconnectFinished: function (rfb, reason) { - if (typeof reason !== 'undefined') { - UI.showStatus(reason, 'error'); - } else if (UI.getSetting('reconnect', false) === true && !UI.inhibit_reconnect) { - document.getElementById("noVNC_transition_text").textContent = _("Reconnecting..."); - document.documentElement.classList.add("noVNC_reconnecting"); - - var delay = parseInt(UI.getSetting('reconnect_delay')); - UI.reconnect_callback = setTimeout(UI.reconnect, delay); - return; - } - - UI.openControlbar(); - UI.openConnectPanel(); - }, - - cancelReconnect: function() { - if (UI.reconnect_callback !== null) { - clearTimeout(UI.reconnect_callback); - UI.reconnect_callback = null; - } - - document.documentElement.classList.remove("noVNC_reconnecting"); - UI.openControlbar(); - UI.openConnectPanel(); - }, + document.documentElement.classList.remove("noVNC_reconnecting"); + UI.openControlbar(); + UI.openConnectPanel(); + }, /* ------^------- * /CONNECTION @@ -1173,31 +1117,31 @@ var UI; * PASSWORD * ------v------*/ - passwordRequired: function(rfb, msg) { + passwordRequired: function(rfb, msg) { - document.getElementById('noVNC_password_dlg') - .classList.add('noVNC_open'); + document.getElementById('noVNC_password_dlg') + .classList.add('noVNC_open'); - setTimeout(function () { - document.getElementById('noVNC_password_input').focus(); - }, 100); + setTimeout(function () { + document.getElementById('noVNC_password_input').focus(); + }, 100); - if (typeof msg === 'undefined') { - msg = _("Password is required"); - } - Util.Warn(msg); - UI.showStatus(msg, "warning"); - }, + if (typeof msg === 'undefined') { + msg = _("Password is required"); + } + Log.Warn(msg); + UI.showStatus(msg, "warning"); + }, - setPassword: function(e) { - var password = document.getElementById('noVNC_password_input').value; - UI.rfb.sendPassword(password); - UI.reconnect_password = password; - document.getElementById('noVNC_password_dlg') - .classList.remove('noVNC_open'); - // Prevent actually submitting the form - e.preventDefault(); - }, + setPassword: function(e) { + var password = document.getElementById('noVNC_password_input').value; + UI.rfb.sendPassword(password); + UI.reconnect_password = password; + document.getElementById('noVNC_password_dlg') + .classList.remove('noVNC_open'); + // Prevent actually submitting the form + e.preventDefault(); + }, /* ------^------- * /PASSWORD @@ -1205,47 +1149,47 @@ var UI; * FULLSCREEN * ------v------*/ - toggleFullscreen: function() { - if (document.fullscreenElement || // alternative standard method - document.mozFullScreenElement || // currently working methods - document.webkitFullscreenElement || - document.msFullscreenElement) { - if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.mozCancelFullScreen) { - document.mozCancelFullScreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } else if (document.msExitFullscreen) { - document.msExitFullscreen(); - } - } else { - if (document.documentElement.requestFullscreen) { - document.documentElement.requestFullscreen(); - } else if (document.documentElement.mozRequestFullScreen) { - document.documentElement.mozRequestFullScreen(); - } else if (document.documentElement.webkitRequestFullscreen) { - document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); - } else if (document.body.msRequestFullscreen) { - document.body.msRequestFullscreen(); - } + toggleFullscreen: function() { + if (document.fullscreenElement || // alternative standard method + document.mozFullScreenElement || // currently working methods + document.webkitFullscreenElement || + document.msFullscreenElement) { + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); } - UI.enableDisableViewClip(); - UI.updateFullscreenButton(); - }, + } else { + if (document.documentElement.requestFullscreen) { + document.documentElement.requestFullscreen(); + } else if (document.documentElement.mozRequestFullScreen) { + document.documentElement.mozRequestFullScreen(); + } else if (document.documentElement.webkitRequestFullscreen) { + document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); + } else if (document.body.msRequestFullscreen) { + document.body.msRequestFullscreen(); + } + } + UI.enableDisableViewClip(); + UI.updateFullscreenButton(); + }, - updateFullscreenButton: function() { - if (document.fullscreenElement || // alternative standard method - document.mozFullScreenElement || // currently working methods - document.webkitFullscreenElement || - document.msFullscreenElement ) { - document.getElementById('noVNC_fullscreen_button') - .classList.add("noVNC_selected"); - } else { - document.getElementById('noVNC_fullscreen_button') - .classList.remove("noVNC_selected"); - } - }, + updateFullscreenButton: function() { + if (document.fullscreenElement || // alternative standard method + document.mozFullScreenElement || // currently working methods + document.webkitFullscreenElement || + document.msFullscreenElement ) { + document.getElementById('noVNC_fullscreen_button') + .classList.add("noVNC_selected"); + } else { + document.getElementById('noVNC_fullscreen_button') + .classList.remove("noVNC_selected"); + } + }, /* ------^------- * /FULLSCREEN @@ -1253,62 +1197,62 @@ var UI; * RESIZE * ------v------*/ - // Apply remote resizing or local scaling - applyResizeMode: function() { - if (!UI.rfb) return; + // Apply remote resizing or local scaling + applyResizeMode: function() { + if (!UI.rfb) return; - var screen = UI.screenSize(); + var screen = UI.screenSize(); - if (screen && UI.connected && UI.rfb.get_display()) { + if (screen && UI.connected && UI.rfb.get_display()) { - var display = UI.rfb.get_display(); - var resizeMode = UI.getSetting('resize'); - display.set_scale(1); + var display = UI.rfb.get_display(); + var resizeMode = UI.getSetting('resize'); + display.set_scale(1); - // Make sure the viewport is adjusted first - UI.updateViewClip(); + // Make sure the viewport is adjusted first + UI.updateViewClip(); - if (resizeMode === 'remote') { + if (resizeMode === 'remote') { - // Request changing the resolution of the remote display to - // the size of the local browser viewport. + // Request changing the resolution of the remote display to + // the size of the local browser viewport. - // In order to not send multiple requests before the browser-resize - // is finished we wait 0.5 seconds before sending the request. - clearTimeout(UI.resizeTimeout); - UI.resizeTimeout = setTimeout(function(){ - // Request a remote size covering the viewport - if (UI.rfb.requestDesktopSize(screen.w, screen.h)) { - Util.Debug('Requested new desktop size: ' + - screen.w + 'x' + screen.h); - } - }, 500); + // In order to not send multiple requests before the browser-resize + // is finished we wait 0.5 seconds before sending the request. + clearTimeout(UI.resizeTimeout); + UI.resizeTimeout = setTimeout(function(){ + // Request a remote size covering the viewport + if (UI.rfb.requestDesktopSize(screen.w, screen.h)) { + Log.Debug('Requested new desktop size: ' + + screen.w + 'x' + screen.h); + } + }, 500); - } else if (resizeMode === 'scale' || resizeMode === 'downscale') { - var downscaleOnly = resizeMode === 'downscale'; - display.autoscale(screen.w, screen.h, downscaleOnly); - UI.fixScrollbars(); - } + } else if (resizeMode === 'scale' || resizeMode === 'downscale') { + var downscaleOnly = resizeMode === 'downscale'; + display.autoscale(screen.w, screen.h, downscaleOnly); + UI.fixScrollbars(); } - }, + } + }, - // Gets the the size of the available viewport in the browser window - screenSize: function() { - var screen = document.getElementById('noVNC_screen'); - return {w: screen.offsetWidth, h: screen.offsetHeight}; - }, + // Gets the the size of the available viewport in the browser window + screenSize: function() { + var screen = document.getElementById('noVNC_screen'); + return {w: screen.offsetWidth, h: screen.offsetHeight}; + }, - // Normally we only apply the current resize mode after a window resize - // event. This means that when a new connection is opened, there is no - // resize mode active. - // We have to wait until the first FBU because this is where the client - // will find the supported encodings of the server. Some calls later in - // the chain is dependant on knowing the server-capabilities. - initialResize: function(rfb, fbu) { - UI.applyResizeMode(); - // After doing this once, we remove the callback. - UI.rfb.set_onFBUComplete(function() { }); - }, + // Normally we only apply the current resize mode after a window resize + // event. This means that when a new connection is opened, there is no + // resize mode active. + // We have to wait until the first FBU because this is where the client + // will find the supported encodings of the server. Some calls later in + // the chain is dependant on knowing the server-capabilities. + initialResize: function(rfb, fbu) { + UI.applyResizeMode(); + // After doing this once, we remove the callback. + UI.rfb.set_onFBUComplete(function() { }); + }, /* ------^------- * /RESIZE @@ -1316,58 +1260,58 @@ var UI; * CLIPPING * ------v------*/ - // Set and configure viewport clipping - setViewClip: function(clip) { - UI.updateSetting('clip', clip); - UI.updateViewClip(); - }, + // Set and configure viewport clipping + setViewClip: function(clip) { + UI.updateSetting('clip', clip); + UI.updateViewClip(); + }, - // Update parameters that depend on the clip setting - updateViewClip: function() { - if (!UI.rfb) return; + // Update parameters that depend on the clip setting + updateViewClip: function() { + if (!UI.rfb) return; - var display = UI.rfb.get_display(); - var cur_clip = display.get_viewport(); - var new_clip = UI.getSetting('clip'); + var display = UI.rfb.get_display(); + var cur_clip = display.get_viewport(); + var new_clip = UI.getSetting('clip'); - var resizeSetting = UI.getSetting('resize'); - if (resizeSetting === 'downscale' || resizeSetting === 'scale') { - // Disable clipping if we are scaling - new_clip = false; - } else if (Util.isTouchDevice) { - // Touch devices usually have shit scrollbars - new_clip = true; - } + var resizeSetting = UI.getSetting('resize'); + if (resizeSetting === 'downscale' || resizeSetting === 'scale') { + // Disable clipping if we are scaling + new_clip = false; + } else if (isTouchDevice) { + // Touch devices usually have shit scrollbars + new_clip = true; + } - if (cur_clip !== new_clip) { - display.set_viewport(new_clip); - } + if (cur_clip !== new_clip) { + display.set_viewport(new_clip); + } - var size = UI.screenSize(); + var size = UI.screenSize(); - if (new_clip && size) { - // When clipping is enabled, the screen is limited to - // the size of the browser window. - display.viewportChangeSize(size.w, size.h); - UI.fixScrollbars(); - } + if (new_clip && size) { + // When clipping is enabled, the screen is limited to + // the size of the browser window. + display.viewportChangeSize(size.w, size.h); + UI.fixScrollbars(); + } - // Changing the viewport may change the state of - // the dragging button - UI.updateViewDrag(); - }, + // Changing the viewport may change the state of + // the dragging button + UI.updateViewDrag(); + }, - // Handle special cases where clipping is forced on/off or locked - enableDisableViewClip: function() { - var resizeSetting = UI.getSetting('resize'); - // Disable clipping if we are scaling, connected or on touch - if (resizeSetting === 'downscale' || resizeSetting === 'scale' || - Util.isTouchDevice) { - UI.disableSetting('clip'); - } else { - UI.enableSetting('clip'); - } - }, + // Handle special cases where clipping is forced on/off or locked + enableDisableViewClip: function() { + var resizeSetting = UI.getSetting('resize'); + // Disable clipping if we are scaling, connected or on touch + if (resizeSetting === 'downscale' || resizeSetting === 'scale' || + isTouchDevice) { + UI.disableSetting('clip'); + } else { + UI.enableSetting('clip'); + } + }, /* ------^------- * /CLIPPING @@ -1375,70 +1319,70 @@ var UI; * VIEWDRAG * ------v------*/ - toggleViewDrag: function() { - if (!UI.rfb) return; + toggleViewDrag: function() { + if (!UI.rfb) return; - var drag = UI.rfb.get_viewportDrag(); - UI.setViewDrag(!drag); - }, + var drag = UI.rfb.get_viewportDrag(); + UI.setViewDrag(!drag); + }, - // Set the view drag mode which moves the viewport on mouse drags - setViewDrag: function(drag) { - if (!UI.rfb) return; + // Set the view drag mode which moves the viewport on mouse drags + setViewDrag: function(drag) { + if (!UI.rfb) return; - UI.rfb.set_viewportDrag(drag); + UI.rfb.set_viewportDrag(drag); - UI.updateViewDrag(); - }, + UI.updateViewDrag(); + }, - updateViewDrag: function() { - var clipping = false; + updateViewDrag: function() { + var clipping = false; - if (!UI.connected) return; + if (!UI.connected) return; - // Check if viewport drag is possible. It is only possible - // if the remote display is clipping the client display. - if (UI.rfb.get_display().get_viewport() && - UI.rfb.get_display().clippingDisplay()) { - clipping = true; - } + // Check if viewport drag is possible. It is only possible + // if the remote display is clipping the client display. + if (UI.rfb.get_display().get_viewport() && + UI.rfb.get_display().clippingDisplay()) { + clipping = true; + } - var viewDragButton = document.getElementById('noVNC_view_drag_button'); + var viewDragButton = document.getElementById('noVNC_view_drag_button'); - if (!clipping && - UI.rfb.get_viewportDrag()) { - // The size of the remote display is the same or smaller - // than the client display. Make sure viewport drag isn't - // active when it can't be used. - UI.rfb.set_viewportDrag(false); - } + if (!clipping && + UI.rfb.get_viewportDrag()) { + // The size of the remote display is the same or smaller + // than the client display. Make sure viewport drag isn't + // active when it can't be used. + UI.rfb.set_viewportDrag(false); + } - if (UI.rfb.get_viewportDrag()) { - viewDragButton.classList.add("noVNC_selected"); - } else { - viewDragButton.classList.remove("noVNC_selected"); - } + if (UI.rfb.get_viewportDrag()) { + viewDragButton.classList.add("noVNC_selected"); + } else { + viewDragButton.classList.remove("noVNC_selected"); + } - // Different behaviour for touch vs non-touch - // The button is disabled instead of hidden on touch devices - if (Util.isTouchDevice) { - viewDragButton.classList.remove("noVNC_hidden"); + // Different behaviour for touch vs non-touch + // The button is disabled instead of hidden on touch devices + if (isTouchDevice) { + viewDragButton.classList.remove("noVNC_hidden"); - if (clipping) { - viewDragButton.disabled = false; - } else { - viewDragButton.disabled = true; - } - } else { + if (clipping) { viewDragButton.disabled = false; - - if (clipping) { - viewDragButton.classList.remove("noVNC_hidden"); - } else { - viewDragButton.classList.add("noVNC_hidden"); - } + } else { + viewDragButton.disabled = true; } - }, + } else { + viewDragButton.disabled = false; + + if (clipping) { + viewDragButton.classList.remove("noVNC_hidden"); + } else { + viewDragButton.classList.add("noVNC_hidden"); + } + } + }, /* ------^------- * /VIEWDRAG @@ -1446,155 +1390,155 @@ var UI; * KEYBOARD * ------v------*/ - showVirtualKeyboard: function() { - if (!Util.isTouchDevice) return; + showVirtualKeyboard: function() { + if (!isTouchDevice) return; - var input = document.getElementById('noVNC_keyboardinput'); + var input = document.getElementById('noVNC_keyboardinput'); - if (document.activeElement == input) return; + if (document.activeElement == input) return; - input.focus(); + input.focus(); - try { - var l = input.value.length; - // Move the caret to the end - input.setSelectionRange(l, l); - } catch (err) {} // setSelectionRange is undefined in Google Chrome - }, + try { + var l = input.value.length; + // Move the caret to the end + input.setSelectionRange(l, l); + } catch (err) {} // setSelectionRange is undefined in Google Chrome + }, - hideVirtualKeyboard: function() { - if (!Util.isTouchDevice) return; + hideVirtualKeyboard: function() { + if (!isTouchDevice) return; - var input = document.getElementById('noVNC_keyboardinput'); + var input = document.getElementById('noVNC_keyboardinput'); - if (document.activeElement != input) return; + if (document.activeElement != input) return; - input.blur(); - }, + input.blur(); + }, - toggleVirtualKeyboard: function () { - if (document.getElementById('noVNC_keyboard_button') - .classList.contains("noVNC_selected")) { - UI.hideVirtualKeyboard(); - } else { - UI.showVirtualKeyboard(); + toggleVirtualKeyboard: function () { + if (document.getElementById('noVNC_keyboard_button') + .classList.contains("noVNC_selected")) { + UI.hideVirtualKeyboard(); + } else { + UI.showVirtualKeyboard(); + } + }, + + onfocusVirtualKeyboard: function(event) { + document.getElementById('noVNC_keyboard_button') + .classList.add("noVNC_selected"); + }, + + onblurVirtualKeyboard: function(event) { + document.getElementById('noVNC_keyboard_button') + .classList.remove("noVNC_selected"); + }, + + keepVirtualKeyboard: function(event) { + var input = document.getElementById('noVNC_keyboardinput'); + + // Only prevent focus change if the virtual keyboard is active + if (document.activeElement != input) { + return; + } + + // Only allow focus to move to other elements that need + // focus to function properly + if (event.target.form !== undefined) { + switch (event.target.type) { + case 'text': + case 'email': + case 'search': + case 'password': + case 'tel': + case 'url': + case 'textarea': + case 'select-one': + case 'select-multiple': + return; } - }, + } - onfocusVirtualKeyboard: function(event) { - document.getElementById('noVNC_keyboard_button') - .classList.add("noVNC_selected"); - }, + event.preventDefault(); + }, - onblurVirtualKeyboard: function(event) { - document.getElementById('noVNC_keyboard_button') - .classList.remove("noVNC_selected"); - }, + keyboardinputReset: function() { + var kbi = document.getElementById('noVNC_keyboardinput'); + kbi.value = new Array(UI.defaultKeyboardinputLen).join("_"); + UI.lastKeyboardinput = kbi.value; + }, - keepVirtualKeyboard: function(event) { - var input = document.getElementById('noVNC_keyboardinput'); + // When normal keyboard events are left uncought, use the input events from + // the keyboardinput element instead and generate the corresponding key events. + // This code is required since some browsers on Android are inconsistent in + // sending keyCodes in the normal keyboard events when using on screen keyboards. + keyInput: function(event) { - // Only prevent focus change if the virtual keyboard is active - if (document.activeElement != input) { - return; + if (!UI.rfb) return; + + var newValue = event.target.value; + + if (!UI.lastKeyboardinput) { + UI.keyboardinputReset(); + } + var oldValue = UI.lastKeyboardinput; + + var newLen; + try { + // Try to check caret position since whitespace at the end + // will not be considered by value.length in some browsers + newLen = Math.max(event.target.selectionStart, newValue.length); + } catch (err) { + // selectionStart is undefined in Google Chrome + newLen = newValue.length; + } + var oldLen = oldValue.length; + + var backspaces; + var inputs = newLen - oldLen; + if (inputs < 0) { + backspaces = -inputs; + } else { + backspaces = 0; + } + + // Compare the old string with the new to account for + // text-corrections or other input that modify existing text + var i; + for (i = 0; i < Math.min(oldLen, newLen); i++) { + if (newValue.charAt(i) != oldValue.charAt(i)) { + inputs = newLen - i; + backspaces = oldLen - i; + break; } + } - // Only allow focus to move to other elements that need - // focus to function properly - if (event.target.form !== undefined) { - switch (event.target.type) { - case 'text': - case 'email': - case 'search': - case 'password': - case 'tel': - case 'url': - case 'textarea': - case 'select-one': - case 'select-multiple': - return; - } - } + // Send the key events + for (i = 0; i < backspaces; i++) { + UI.rfb.sendKey(KeyTable.XK_BackSpace); + } + for (i = newLen - inputs; i < newLen; i++) { + UI.rfb.sendKey(keysyms.fromUnicode(newValue.charCodeAt(i)).keysym); + } - event.preventDefault(); - }, - - keyboardinputReset: function() { - var kbi = document.getElementById('noVNC_keyboardinput'); - kbi.value = new Array(UI.defaultKeyboardinputLen).join("_"); - UI.lastKeyboardinput = kbi.value; - }, - - // When normal keyboard events are left uncought, use the input events from - // the keyboardinput element instead and generate the corresponding key events. - // This code is required since some browsers on Android are inconsistent in - // sending keyCodes in the normal keyboard events when using on screen keyboards. - keyInput: function(event) { - - if (!UI.rfb) return; - - var newValue = event.target.value; - - if (!UI.lastKeyboardinput) { - UI.keyboardinputReset(); - } - var oldValue = UI.lastKeyboardinput; - - var newLen; - try { - // Try to check caret position since whitespace at the end - // will not be considered by value.length in some browsers - newLen = Math.max(event.target.selectionStart, newValue.length); - } catch (err) { - // selectionStart is undefined in Google Chrome - newLen = newValue.length; - } - var oldLen = oldValue.length; - - var backspaces; - var inputs = newLen - oldLen; - if (inputs < 0) { - backspaces = -inputs; - } else { - backspaces = 0; - } - - // Compare the old string with the new to account for - // text-corrections or other input that modify existing text - var i; - for (i = 0; i < Math.min(oldLen, newLen); i++) { - if (newValue.charAt(i) != oldValue.charAt(i)) { - inputs = newLen - i; - backspaces = oldLen - i; - break; - } - } - - // Send the key events - for (i = 0; i < backspaces; i++) { - UI.rfb.sendKey(KeyTable.XK_BackSpace); - } - for (i = newLen - inputs; i < newLen; i++) { - UI.rfb.sendKey(keysyms.fromUnicode(newValue.charCodeAt(i)).keysym); - } - - // Control the text content length in the keyboardinput element - if (newLen > 2 * UI.defaultKeyboardinputLen) { - UI.keyboardinputReset(); - } else if (newLen < 1) { - // There always have to be some text in the keyboardinput - // element with which backspace can interact. - UI.keyboardinputReset(); - // This sometimes causes the keyboard to disappear for a second - // but it is required for the android keyboard to recognize that - // text has been added to the field - event.target.blur(); - // This has to be ran outside of the input handler in order to work - setTimeout(event.target.focus.bind(event.target), 0); - } else { - UI.lastKeyboardinput = newValue; - } - }, + // Control the text content length in the keyboardinput element + if (newLen > 2 * UI.defaultKeyboardinputLen) { + UI.keyboardinputReset(); + } else if (newLen < 1) { + // There always have to be some text in the keyboardinput + // element with which backspace can interact. + UI.keyboardinputReset(); + // This sometimes causes the keyboard to disappear for a second + // but it is required for the android keyboard to recognize that + // text has been added to the field + event.target.blur(); + // This has to be ran outside of the input handler in order to work + setTimeout(event.target.focus.bind(event.target), 0); + } else { + UI.lastKeyboardinput = newValue; + } + }, /* ------^------- * /KEYBOARD @@ -1602,65 +1546,65 @@ var UI; * EXTRA KEYS * ------v------*/ - openExtraKeys: function() { - UI.closeAllPanels(); - UI.openControlbar(); + openExtraKeys: function() { + UI.closeAllPanels(); + UI.openControlbar(); - document.getElementById('noVNC_modifiers') - .classList.add("noVNC_open"); - document.getElementById('noVNC_toggle_extra_keys_button') - .classList.add("noVNC_selected"); - }, + document.getElementById('noVNC_modifiers') + .classList.add("noVNC_open"); + document.getElementById('noVNC_toggle_extra_keys_button') + .classList.add("noVNC_selected"); + }, - closeExtraKeys: function() { - document.getElementById('noVNC_modifiers') - .classList.remove("noVNC_open"); - document.getElementById('noVNC_toggle_extra_keys_button') - .classList.remove("noVNC_selected"); - }, + closeExtraKeys: function() { + document.getElementById('noVNC_modifiers') + .classList.remove("noVNC_open"); + document.getElementById('noVNC_toggle_extra_keys_button') + .classList.remove("noVNC_selected"); + }, - toggleExtraKeys: function() { - if(document.getElementById('noVNC_modifiers') - .classList.contains("noVNC_open")) { - UI.closeExtraKeys(); - } else { - UI.openExtraKeys(); - } - }, + toggleExtraKeys: function() { + if(document.getElementById('noVNC_modifiers') + .classList.contains("noVNC_open")) { + UI.closeExtraKeys(); + } else { + UI.openExtraKeys(); + } + }, - sendEsc: function() { - UI.rfb.sendKey(KeyTable.XK_Escape); - }, + sendEsc: function() { + UI.rfb.sendKey(KeyTable.XK_Escape); + }, - sendTab: function() { - UI.rfb.sendKey(KeyTable.XK_Tab); - }, + sendTab: function() { + UI.rfb.sendKey(KeyTable.XK_Tab); + }, - toggleCtrl: function() { - var btn = document.getElementById('noVNC_toggle_ctrl_button'); - if (btn.classList.contains("noVNC_selected")) { - UI.rfb.sendKey(KeyTable.XK_Control_L, false); - btn.classList.remove("noVNC_selected"); - } else { - UI.rfb.sendKey(KeyTable.XK_Control_L, true); - btn.classList.add("noVNC_selected"); - } - }, + toggleCtrl: function() { + var btn = document.getElementById('noVNC_toggle_ctrl_button'); + if (btn.classList.contains("noVNC_selected")) { + UI.rfb.sendKey(KeyTable.XK_Control_L, false); + btn.classList.remove("noVNC_selected"); + } else { + UI.rfb.sendKey(KeyTable.XK_Control_L, true); + btn.classList.add("noVNC_selected"); + } + }, - toggleAlt: function() { - var btn = document.getElementById('noVNC_toggle_alt_button'); - if (btn.classList.contains("noVNC_selected")) { - UI.rfb.sendKey(KeyTable.XK_Alt_L, false); - btn.classList.remove("noVNC_selected"); - } else { - UI.rfb.sendKey(KeyTable.XK_Alt_L, true); - btn.classList.add("noVNC_selected"); - } - }, + toggleAlt: function() { + var btn = document.getElementById('noVNC_toggle_alt_button'); + if (btn.classList.contains("noVNC_selected")) { + UI.rfb.sendKey(KeyTable.XK_Alt_L, false); + btn.classList.remove("noVNC_selected"); + } else { + UI.rfb.sendKey(KeyTable.XK_Alt_L, true); + btn.classList.add("noVNC_selected"); + } + }, - sendCtrlAltDel: function() { - UI.rfb.sendCtrlAltDel(); - }, + sendCtrlAltDel: function() { + UI.rfb.sendCtrlAltDel(); + }, /* ------^------- * /EXTRA KEYS @@ -1668,94 +1612,109 @@ var UI; * MISC * ------v------*/ - setMouseButton: function(num) { - var view_only = UI.rfb.get_view_only(); - if (UI.rfb && !view_only) { - UI.rfb.get_mouse().set_touchButton(num); + setMouseButton: function(num) { + var view_only = UI.rfb.get_view_only(); + if (UI.rfb && !view_only) { + UI.rfb.get_mouse().set_touchButton(num); + } + + var blist = [0, 1,2,4]; + for (var b = 0; b < blist.length; b++) { + var button = document.getElementById('noVNC_mouse_button' + + blist[b]); + if (blist[b] === num && !view_only) { + button.classList.remove("noVNC_hidden"); + } else { + button.classList.add("noVNC_hidden"); } + } + }, - var blist = [0, 1,2,4]; - for (var b = 0; b < blist.length; b++) { - var button = document.getElementById('noVNC_mouse_button' + - blist[b]); - if (blist[b] === num && !view_only) { - button.classList.remove("noVNC_hidden"); - } else { - button.classList.add("noVNC_hidden"); - } - } - }, + displayBlur: function() { + if (UI.rfb && !UI.rfb.get_view_only()) { + UI.rfb.get_keyboard().set_focused(false); + UI.rfb.get_mouse().set_focused(false); + } + }, - displayBlur: function() { - if (UI.rfb && !UI.rfb.get_view_only()) { - UI.rfb.get_keyboard().set_focused(false); - UI.rfb.get_mouse().set_focused(false); - } - }, + displayFocus: function() { + if (UI.rfb && !UI.rfb.get_view_only()) { + UI.rfb.get_keyboard().set_focused(true); + UI.rfb.get_mouse().set_focused(true); + } + }, - displayFocus: function() { - if (UI.rfb && !UI.rfb.get_view_only()) { - UI.rfb.get_keyboard().set_focused(true); - UI.rfb.get_mouse().set_focused(true); - } - }, + updateLocalCursor: function() { + if (!UI.rfb) return; + UI.rfb.set_local_cursor(UI.getSetting('cursor')); + }, - updateLocalCursor: function() { - UI.rfb.set_local_cursor(UI.getSetting('cursor')); - }, + updateViewOnly: function() { + if (!UI.rfb) return; + UI.rfb.set_view_only(UI.getSetting('view_only')); + }, - updateViewOnly: function() { - UI.rfb.set_view_only(UI.getSetting('view_only')); - }, + updateLogging: function() { + WebUtil.init_logging(UI.getSetting('logging')); + }, - updateLogging: function() { - WebUtil.init_logging(UI.getSetting('logging')); - }, + updateSessionSize: function(rfb, width, height) { + UI.updateViewClip(); + UI.fixScrollbars(); + }, - updateSessionSize: function(rfb, width, height) { - UI.updateViewClip(); - UI.fixScrollbars(); - }, + fixScrollbars: function() { + // This is a hack because Chrome screws up the calculation + // for when scrollbars are needed. So to fix it we temporarily + // toggle them off and on. + var screen = document.getElementById('noVNC_screen'); + screen.style.overflow = 'hidden'; + // Force Chrome to recalculate the layout by asking for + // an element's dimensions + screen.getBoundingClientRect(); + screen.style.overflow = null; + }, - fixScrollbars: function() { - // This is a hack because Chrome screws up the calculation - // for when scrollbars are needed. So to fix it we temporarily - // toggle them off and on. - var screen = document.getElementById('noVNC_screen'); - screen.style.overflow = 'hidden'; - // Force Chrome to recalculate the layout by asking for - // an element's dimensions - screen.getBoundingClientRect(); - screen.style.overflow = null; - }, + updateDesktopName: function(rfb, name) { + UI.desktopName = name; + // Display the desktop name in the document title + document.title = name + " - noVNC"; + }, - updateDesktopName: function(rfb, name) { - UI.desktopName = name; - // Display the desktop name in the document title - document.title = name + " - noVNC"; - }, + bell: function(rfb) { + if (WebUtil.getConfigVar('bell', 'on') === 'on') { + document.getElementById('noVNC_bell').play(); + } + }, - bell: function(rfb) { - if (WebUtil.getConfigVar('bell', 'on') === 'on') { - document.getElementById('noVNC_bell').play(); - } - }, - - //Helper to add options to dropdown. - addOption: function(selectbox, text, value) { - var optn = document.createElement("OPTION"); - optn.text = text; - optn.value = value; - selectbox.options.add(optn); - }, + //Helper to add options to dropdown. + addOption: function(selectbox, text, value) { + var optn = document.createElement("OPTION"); + optn.text = text; + optn.value = value; + selectbox.options.add(optn); + }, /* ------^------- * /MISC * ============== */ - }; +}; - /* [module] UI.load(); */ -})(); +// Set up translations +var LINGUAS = ["de", "el", "nl", "sv"]; +l10n.setup(LINGUAS); +if (l10n.language !== "en" && l10n.dictionary === undefined) { + WebUtil.fetchJSON('app/locale/' + l10n.language + '.json', function (translations) { + l10n.dictionary = translations; -/* [module] export default UI; */ + // wait for translations to load before loading the UI + UI.prime(); + }, function (err) { + throw err; + }); +} else { + UI.prime(); +} + +export default UI; diff --git a/app/webutil.js b/app/webutil.js index e6e6afb7..7cee466c 100644 --- a/app/webutil.js +++ b/app/webutil.js @@ -10,62 +10,21 @@ /*jslint bitwise: false, white: false, browser: true, devel: true */ /*global Util, window, document */ -/* [module] - * import Util from "../core/util"; - */ - -// Globals defined here -var WebUtil = {}; - -/* - * ------------------------------------------------------ - * Namespaced in WebUtil - * ------------------------------------------------------ - */ +import { init_logging as main_init_logging } from '../core/util/logging.js'; // init log level reading the logging HTTP param -WebUtil.init_logging = function (level) { +export function init_logging (level) { "use strict"; if (typeof level !== "undefined") { - Util._log_level = level; + main_init_logging(level); } else { var param = document.location.href.match(/logging=([A-Za-z0-9\._\-]*)/); - Util._log_level = (param || ['', Util._log_level])[1]; + main_init_logging(param || undefined); } - Util.init_logging(); -}; - - -WebUtil.dirObj = function (obj, depth, parent) { - "use strict"; - if (! depth) { depth = 2; } - if (! parent) { parent = ""; } - - // Print the properties of the passed-in object - var msg = ""; - for (var i in obj) { - if ((depth > 1) && (typeof obj[i] === "object")) { - // Recurse attributes that are objects - msg += WebUtil.dirObj(obj[i], depth - 1, parent + "." + i); - } else { - //val = new String(obj[i]).replace("\n", " "); - var val = ""; - if (typeof(obj[i]) === "undefined") { - val = "undefined"; - } else { - val = obj[i].toString().replace("\n", " "); - } - if (val.length > 30) { - val = val.substr(0, 30) + "..."; - } - msg += parent + "." + i + ": " + val + "\n"; - } - } - return msg; }; // Read a query string variable -WebUtil.getQueryVar = function (name, defVal) { +export function getQueryVar (name, defVal) { "use strict"; var re = new RegExp('.*[?&]' + name + '=([^&#]*)'), match = document.location.href.match(re); @@ -78,7 +37,7 @@ WebUtil.getQueryVar = function (name, defVal) { }; // Read a hash fragment variable -WebUtil.getHashVar = function (name, defVal) { +export function getHashVar (name, defVal) { "use strict"; var re = new RegExp('.*[&#]' + name + '=([^&]*)'), match = document.location.hash.match(re); @@ -92,11 +51,11 @@ WebUtil.getHashVar = function (name, defVal) { // Read a variable from the fragment or the query string // Fragment takes precedence -WebUtil.getConfigVar = function (name, defVal) { +export function getConfigVar (name, defVal) { "use strict"; - var val = WebUtil.getHashVar(name); + var val = getHashVar(name); if (val === null) { - val = WebUtil.getQueryVar(name, defVal); + val = getQueryVar(name, defVal); } return val; }; @@ -106,7 +65,7 @@ WebUtil.getConfigVar = function (name, defVal) { */ // No days means only for this browser session -WebUtil.createCookie = function (name, value, days) { +export function createCookie (name, value, days) { "use strict"; var date, expires; if (days) { @@ -126,7 +85,7 @@ WebUtil.createCookie = function (name, value, days) { document.cookie = name + "=" + value + expires + "; path=/" + secure; }; -WebUtil.readCookie = function (name, defaultValue) { +export function readCookie (name, defaultValue) { "use strict"; var nameEQ = name + "=", ca = document.cookie.split(';'); @@ -139,22 +98,24 @@ WebUtil.readCookie = function (name, defaultValue) { return (typeof defaultValue !== 'undefined') ? defaultValue : null; }; -WebUtil.eraseCookie = function (name) { +export function eraseCookie (name) { "use strict"; - WebUtil.createCookie(name, "", -1); + createCookie(name, "", -1); }; /* * Setting handling. */ -WebUtil.initSettings = function (callback /*, ...callbackArgs */) { +var settings = {}; + +export function initSettings (callback /*, ...callbackArgs */) { "use strict"; var callbackArgs = Array.prototype.slice.call(arguments, 1); if (window.chrome && window.chrome.storage) { window.chrome.storage.sync.get(function (cfg) { - WebUtil.settings = cfg; - console.log(WebUtil.settings); + settings = cfg; + console.log(settings); if (callback) { callback.apply(this, callbackArgs); } @@ -168,24 +129,24 @@ WebUtil.initSettings = function (callback /*, ...callbackArgs */) { }; // No days means only for this browser session -WebUtil.writeSetting = function (name, value) { +export function writeSetting (name, value) { "use strict"; if (window.chrome && window.chrome.storage) { //console.log("writeSetting:", name, value); - if (WebUtil.settings[name] !== value) { - WebUtil.settings[name] = value; - window.chrome.storage.sync.set(WebUtil.settings); + if (settings[name] !== value) { + settings[name] = value; + window.chrome.storage.sync.set(settings); } } else { localStorage.setItem(name, value); } }; -WebUtil.readSetting = function (name, defaultValue) { +export function readSetting (name, defaultValue) { "use strict"; var value; if (window.chrome && window.chrome.storage) { - value = WebUtil.settings[name]; + value = settings[name]; } else { value = localStorage.getItem(name); } @@ -199,17 +160,17 @@ WebUtil.readSetting = function (name, defaultValue) { } }; -WebUtil.eraseSetting = function (name) { +export function eraseSetting (name) { "use strict"; if (window.chrome && window.chrome.storage) { window.chrome.storage.sync.remove(name); - delete WebUtil.settings[name]; + delete settings[name]; } else { localStorage.removeItem(name); } }; -WebUtil.injectParamIfMissing = function (path, param, value) { +export function injectParamIfMissing (path, param, value) { // force pretend that we're dealing with a relative path // (assume that we wanted an extra if we pass one in) path = "/" + path; @@ -239,73 +200,36 @@ WebUtil.injectParamIfMissing = function (path, param, value) { } }; -// Dynamically load scripts without using document.write() -// Reference: http://unixpapa.com/js/dyna.html -// -// Handles the case where load_scripts is invoked from a script that -// itself is loaded via load_scripts. Once all scripts are loaded the -// window.onscriptsloaded handler is called (if set). -WebUtil.get_include_uri = function (root_dir) { - return (typeof INCLUDE_URI !== "undefined") ? INCLUDE_URI + root_dir + '/' : root_dir + '/'; -}; -WebUtil._loading_scripts = []; -WebUtil._pending_scripts = []; -WebUtil.load_scripts = function (files_by_dir) { - "use strict"; - var head = document.getElementsByTagName('head')[0], script, - ls = WebUtil._loading_scripts, ps = WebUtil._pending_scripts; +// sadly, we can't use the Fetch API until we decide to drop +// IE11 support or polyfill promises and fetch in IE11. +// resolve will receive an object on success, while reject +// will receive either an event or an error on failure. +export function fetchJSON(path, resolve, reject) { + // NB: IE11 doesn't support JSON as a responseType + const req = new XMLHttpRequest(); + req.open('GET', path); - var loadFunc = function (e) { - while (ls.length > 0 && (ls[0].readyState === 'loaded' || - ls[0].readyState === 'complete')) { - // For IE, append the script to trigger execution - var s = ls.shift(); - //console.log("loaded script: " + s.src); - head.appendChild(s); - } - if (!this.readyState || - (Util.Engine.presto && this.readyState === 'loaded') || - this.readyState === 'complete') { - if (ps.indexOf(this) >= 0) { - this.onload = this.onreadystatechange = null; - //console.log("completed script: " + this.src); - ps.splice(ps.indexOf(this), 1); - - // Call window.onscriptsload after last script loads - if (ps.length === 0 && window.onscriptsload) { - window.onscriptsload(); - } + req.onload = function () { + if (req.status === 200) { + try { + var resObj = JSON.parse(req.responseText); + } catch (err) { + reject(err); + return; } + resolve(resObj); + } else { + reject(new Error("XHR got non-200 status while trying to load '" + path + "': " + req.status)); } }; - var root_dirs = Object.keys(files_by_dir); + req.onerror = function (evt) { + reject(new Error("XHR encountered an error while trying to load '" + path + "': " + evt.message)); + }; - for (var d = 0; d < root_dirs.length; d++) { - var root_dir = root_dirs[d]; - var files = files_by_dir[root_dir]; + req.ontimeout = function (evt) { + reject(new Error("XHR timed out while trying to load '" + path + "'")); + }; - for (var f = 0; f < files.length; f++) { - script = document.createElement('script'); - script.type = 'text/javascript'; - script.src = WebUtil.get_include_uri(root_dir) + files[f]; - //console.log("loading script: " + script.src); - script.onload = script.onreadystatechange = loadFunc; - // In-order script execution tricks - if (Util.Engine.trident) { - // For IE wait until readyState is 'loaded' before - // appending it which will trigger execution - // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order - ls.push(script); - } else { - // For webkit and firefox set async=false and append now - // https://developer.mozilla.org/en-US/docs/HTML/Element/script - script.async = false; - head.appendChild(script); - } - ps.push(script); - } - } -}; - -/* [module] export default WebUtil; */ + req.send(); +} diff --git a/core/base64.js b/core/base64.js index 2b4f948f..9d24a25f 100644 --- a/core/base64.js +++ b/core/base64.js @@ -7,7 +7,7 @@ /*jslint white: false */ /*global console */ -var Base64 = { +export default { /* Convert data (an array of integers) to a Base64 string. */ toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''), base64Pad : '=', @@ -15,7 +15,7 @@ var Base64 = { encode: function (data) { "use strict"; var result = ''; - var toBase64Table = Base64.toBase64Table; + var toBase64Table = this.toBase64Table; var length = data.length; var lengthpad = (length % 3); // Convert every three bytes to 4 ascii characters. @@ -63,8 +63,8 @@ var Base64 = { decode: function (data, offset) { "use strict"; offset = typeof(offset) !== 'undefined' ? offset : 0; - var toBinaryTable = Base64.toBinaryTable; - var base64Pad = Base64.base64Pad; + var toBinaryTable = this.toBinaryTable; + var base64Pad = this.base64Pad; var result, result_length; var leftbits = 0; // number of bits decoded, but yet to be appended var leftdata = 0; // bits decoded, but yet to be appended @@ -111,5 +111,3 @@ var Base64 = { return result; } }; /* End of Base64 namespace */ - -/* [module] export default Base64; */ diff --git a/core/des.js b/core/des.js index c9a4753a..62684936 100644 --- a/core/des.js +++ b/core/des.js @@ -77,7 +77,7 @@ /* jslint white: false */ -/* [module] export default */ function DES(passwd) { +export default function DES(passwd) { "use strict"; // Tables, permutations, S-boxes, etc. diff --git a/core/display.js b/core/display.js index f7c437b4..818c911d 100644 --- a/core/display.js +++ b/core/display.js @@ -10,12 +10,12 @@ /*jslint browser: true, white: false */ /*global Util, Base64, changeCursor */ -/* [module] - * import Util from "./util"; - * import Base64 from "./base64"; - */ +import { Engine, browserSupportsCursorURIs as cursorURIsSupported } from './util/browsers.js'; +import { set_defaults, make_properties } from './util/properties.js'; +import * as Log from './util/logging.js'; +import Base64 from "./base64.js"; -/* [module] export default */ function Display(defaults) { +export default function Display(defaults) { this._drawCtx = null; this._c_forceCanvas = false; @@ -32,7 +32,7 @@ this._tile_x = 0; this._tile_y = 0; - Util.set_defaults(this, defaults, { + set_defaults(this, defaults, { 'true_color': true, 'colourMap': [], 'scale': 1.0, @@ -41,7 +41,7 @@ "onFlush": function () {}, }); - Util.Debug(">> Display.constructor"); + Log.Debug(">> Display.constructor"); // The visible canvas if (!this._target) { @@ -69,11 +69,11 @@ right: this._backbuffer.width, bottom: this._backbuffer.height }; - Util.Debug("User Agent: " + navigator.userAgent); - if (Util.Engine.gecko) { Util.Debug("Browser: gecko " + Util.Engine.gecko); } - if (Util.Engine.webkit) { Util.Debug("Browser: webkit " + Util.Engine.webkit); } - if (Util.Engine.trident) { Util.Debug("Browser: trident " + Util.Engine.trident); } - if (Util.Engine.presto) { Util.Debug("Browser: presto " + Util.Engine.presto); } + Log.Debug("User Agent: " + navigator.userAgent); + if (Engine.gecko) { Log.Debug("Browser: gecko " + Engine.gecko); } + if (Engine.webkit) { Log.Debug("Browser: webkit " + Engine.webkit); } + if (Engine.trident) { Log.Debug("Browser: trident " + Engine.trident); } + if (Engine.presto) { Log.Debug("Browser: presto " + Engine.presto); } this.clear(); @@ -85,788 +85,783 @@ } if (this._prefer_js === null) { - Util.Info("Prefering javascript operations"); + Log.Info("Prefering javascript operations"); this._prefer_js = true; } // Determine browser support for setting the cursor via data URI scheme if (this._cursor_uri || this._cursor_uri === null || this._cursor_uri === undefined) { - this._cursor_uri = Util.browserSupportsCursorURIs(); + this._cursor_uri = cursorURIsSupported(); } - Util.Debug("<< Display.constructor"); + Log.Debug("<< Display.constructor"); }; -(function () { - "use strict"; +var SUPPORTS_IMAGEDATA_CONSTRUCTOR = false; +try { + new ImageData(new Uint8ClampedArray(4), 1, 1); + SUPPORTS_IMAGEDATA_CONSTRUCTOR = true; +} catch (ex) { + // ignore failure +} - var SUPPORTS_IMAGEDATA_CONSTRUCTOR = false; - try { - new ImageData(new Uint8ClampedArray(4), 1, 1); - SUPPORTS_IMAGEDATA_CONSTRUCTOR = true; - } catch (ex) { - // ignore failure - } +Display.prototype = { + // Public methods + viewportChangePos: function (deltaX, deltaY) { + var vp = this._viewportLoc; + deltaX = Math.floor(deltaX); + deltaY = Math.floor(deltaY); + if (!this._viewport) { + deltaX = -vp.w; // clamped later of out of bounds + deltaY = -vp.h; + } - Display.prototype = { - // Public methods - viewportChangePos: function (deltaX, deltaY) { - var vp = this._viewportLoc; - deltaX = Math.floor(deltaX); - deltaY = Math.floor(deltaY); + var vx2 = vp.x + vp.w - 1; + var vy2 = vp.y + vp.h - 1; - if (!this._viewport) { - deltaX = -vp.w; // clamped later of out of bounds - deltaY = -vp.h; - } + // Position change - var vx2 = vp.x + vp.w - 1; - var vy2 = vp.y + vp.h - 1; + if (deltaX < 0 && vp.x + deltaX < 0) { + deltaX = -vp.x; + } + if (vx2 + deltaX >= this._fb_width) { + deltaX -= vx2 + deltaX - this._fb_width + 1; + } - // Position change + if (vp.y + deltaY < 0) { + deltaY = -vp.y; + } + if (vy2 + deltaY >= this._fb_height) { + deltaY -= (vy2 + deltaY - this._fb_height + 1); + } - if (deltaX < 0 && vp.x + deltaX < 0) { - deltaX = -vp.x; - } - if (vx2 + deltaX >= this._fb_width) { - deltaX -= vx2 + deltaX - this._fb_width + 1; - } + if (deltaX === 0 && deltaY === 0) { + return; + } + Log.Debug("viewportChange deltaX: " + deltaX + ", deltaY: " + deltaY); - if (vp.y + deltaY < 0) { - deltaY = -vp.y; - } - if (vy2 + deltaY >= this._fb_height) { - deltaY -= (vy2 + deltaY - this._fb_height + 1); - } + vp.x += deltaX; + vp.y += deltaY; - if (deltaX === 0 && deltaY === 0) { - return; - } - Util.Debug("viewportChange deltaX: " + deltaX + ", deltaY: " + deltaY); + this._damage(vp.x, vp.y, vp.w, vp.h); - vp.x += deltaX; - vp.y += deltaY; + this.flip(); + }, + + viewportChangeSize: function(width, height) { + + if (!this._viewport || + typeof(width) === "undefined" || + typeof(height) === "undefined") { + + Log.Debug("Setting viewport to full display region"); + width = this._fb_width; + height = this._fb_height; + } + + if (width > this._fb_width) { + width = this._fb_width; + } + if (height > this._fb_height) { + height = this._fb_height; + } + + var vp = this._viewportLoc; + if (vp.w !== width || vp.h !== height) { + vp.w = width; + vp.h = height; + + var canvas = this._target; + canvas.width = width; + canvas.height = height; + + // The position might need to be updated if we've grown + this.viewportChangePos(0, 0); this._damage(vp.x, vp.y, vp.w, vp.h); - this.flip(); - }, - viewportChangeSize: function(width, height) { + // Update the visible size of the target canvas + this._rescale(this._scale); + } + }, - if (!this._viewport || - typeof(width) === "undefined" || - typeof(height) === "undefined") { + absX: function (x) { + return x / this._scale + this._viewportLoc.x; + }, - Util.Debug("Setting viewport to full display region"); - width = this._fb_width; - height = this._fb_height; + absY: function (y) { + return y / this._scale + this._viewportLoc.y; + }, + + resize: function (width, height) { + this._prevDrawStyle = ""; + + this._fb_width = width; + this._fb_height = height; + + var canvas = this._backbuffer; + if (canvas.width !== width || canvas.height !== height) { + + // We have to save the canvas data since changing the size will clear it + var saveImg = null; + if (canvas.width > 0 && canvas.height > 0) { + saveImg = this._drawCtx.getImageData(0, 0, canvas.width, canvas.height); } - if (width > this._fb_width) { - width = this._fb_width; - } - if (height > this._fb_height) { - height = this._fb_height; - } - - var vp = this._viewportLoc; - if (vp.w !== width || vp.h !== height) { - vp.w = width; - vp.h = height; - - var canvas = this._target; + if (canvas.width !== width) { canvas.width = width; + } + if (canvas.height !== height) { canvas.height = height; - - // The position might need to be updated if we've grown - this.viewportChangePos(0, 0); - - this._damage(vp.x, vp.y, vp.w, vp.h); - this.flip(); - - // Update the visible size of the target canvas - this._rescale(this._scale); - } - }, - - absX: function (x) { - return x / this._scale + this._viewportLoc.x; - }, - - absY: function (y) { - return y / this._scale + this._viewportLoc.y; - }, - - resize: function (width, height) { - this._prevDrawStyle = ""; - - this._fb_width = width; - this._fb_height = height; - - var canvas = this._backbuffer; - if (canvas.width !== width || canvas.height !== height) { - - // We have to save the canvas data since changing the size will clear it - var saveImg = null; - if (canvas.width > 0 && canvas.height > 0) { - saveImg = this._drawCtx.getImageData(0, 0, canvas.width, canvas.height); - } - - if (canvas.width !== width) { - canvas.width = width; - } - if (canvas.height !== height) { - canvas.height = height; - } - - if (saveImg) { - this._drawCtx.putImageData(saveImg, 0, 0); - } } - // Readjust the viewport as it may be incorrectly sized - // and positioned - var vp = this._viewportLoc; - this.viewportChangeSize(vp.w, vp.h); - this.viewportChangePos(0, 0); - }, - - // Track what parts of the visible canvas that need updating - _damage: function(x, y, w, h) { - if (x < this._damageBounds.left) { - this._damageBounds.left = x; + if (saveImg) { + this._drawCtx.putImageData(saveImg, 0, 0); } - if (y < this._damageBounds.top) { - this._damageBounds.top = y; - } - if ((x + w) > this._damageBounds.right) { - this._damageBounds.right = x + w; - } - if ((y + h) > this._damageBounds.bottom) { - this._damageBounds.bottom = y + h; - } - }, + } - // Update the visible canvas with the contents of the - // rendering canvas - flip: function(from_queue) { - if (this._renderQ.length !== 0 && !from_queue) { - this._renderQ_push({ - 'type': 'flip' - }); - } else { - var x, y, vx, vy, w, h; + // Readjust the viewport as it may be incorrectly sized + // and positioned + var vp = this._viewportLoc; + this.viewportChangeSize(vp.w, vp.h); + this.viewportChangePos(0, 0); + }, - x = this._damageBounds.left; - y = this._damageBounds.top; - w = this._damageBounds.right - x; - h = this._damageBounds.bottom - y; + // Track what parts of the visible canvas that need updating + _damage: function(x, y, w, h) { + if (x < this._damageBounds.left) { + this._damageBounds.left = x; + } + if (y < this._damageBounds.top) { + this._damageBounds.top = y; + } + if ((x + w) > this._damageBounds.right) { + this._damageBounds.right = x + w; + } + if ((y + h) > this._damageBounds.bottom) { + this._damageBounds.bottom = y + h; + } + }, - vx = x - this._viewportLoc.x; - vy = y - this._viewportLoc.y; - - if (vx < 0) { - w += vx; - x -= vx; - vx = 0; - } - if (vy < 0) { - h += vy; - y -= vy; - vy = 0; - } - - if ((vx + w) > this._viewportLoc.w) { - w = this._viewportLoc.w - vx; - } - if ((vy + h) > this._viewportLoc.h) { - h = this._viewportLoc.h - vy; - } - - if ((w > 0) && (h > 0)) { - // FIXME: We may need to disable image smoothing here - // as well (see copyImage()), but we haven't - // noticed any problem yet. - this._targetCtx.drawImage(this._backbuffer, - x, y, w, h, - vx, vy, w, h); - } - - this._damageBounds.left = this._damageBounds.top = 65535; - this._damageBounds.right = this._damageBounds.bottom = 0; - } - }, - - clear: function () { - if (this._logo) { - this.resize(this._logo.width, this._logo.height); - this.imageRect(0, 0, this._logo.type, this._logo.data); - } else { - this.resize(240, 20); - this._drawCtx.clearRect(0, 0, this._fb_width, this._fb_height); - } - this.flip(); - }, - - pending: function() { - return this._renderQ.length > 0; - }, - - flush: function() { - if (this._renderQ.length === 0) { - this._onFlush(); - } else { - this._flushing = true; - } - }, - - fillRect: function (x, y, width, height, color, from_queue) { - if (this._renderQ.length !== 0 && !from_queue) { - this._renderQ_push({ - 'type': 'fill', - 'x': x, - 'y': y, - 'width': width, - 'height': height, - 'color': color - }); - } else { - this._setFillColor(color); - this._drawCtx.fillRect(x, y, width, height); - this._damage(x, y, width, height); - } - }, - - copyImage: function (old_x, old_y, new_x, new_y, w, h, from_queue) { - if (this._renderQ.length !== 0 && !from_queue) { - this._renderQ_push({ - 'type': 'copy', - 'old_x': old_x, - 'old_y': old_y, - 'x': new_x, - 'y': new_y, - 'width': w, - 'height': h, - }); - } else { - // Due to this bug among others [1] we need to disable the image-smoothing to - // avoid getting a blur effect when copying data. - // - // 1. https://bugzilla.mozilla.org/show_bug.cgi?id=1194719 - // - // We need to set these every time since all properties are reset - // when the the size is changed - this._drawCtx.mozImageSmoothingEnabled = false; - this._drawCtx.webkitImageSmoothingEnabled = false; - this._drawCtx.msImageSmoothingEnabled = false; - this._drawCtx.imageSmoothingEnabled = false; - - this._drawCtx.drawImage(this._backbuffer, - old_x, old_y, w, h, - new_x, new_y, w, h); - this._damage(new_x, new_y, w, h); - } - }, - - imageRect: function(x, y, mime, arr) { - var img = new Image(); - img.src = "data: " + mime + ";base64," + Base64.encode(arr); + // Update the visible canvas with the contents of the + // rendering canvas + flip: function(from_queue) { + if (this._renderQ.length !== 0 && !from_queue) { this._renderQ_push({ - 'type': 'img', - 'img': img, - 'x': x, - 'y': y + 'type': 'flip' }); - }, + } else { + var x, y, vx, vy, w, h; - // start updating a tile - startTile: function (x, y, width, height, color) { - this._tile_x = x; - this._tile_y = y; - if (width === 16 && height === 16) { - this._tile = this._tile16x16; - } else { - this._tile = this._drawCtx.createImageData(width, height); + x = this._damageBounds.left; + y = this._damageBounds.top; + w = this._damageBounds.right - x; + h = this._damageBounds.bottom - y; + + vx = x - this._viewportLoc.x; + vy = y - this._viewportLoc.y; + + if (vx < 0) { + w += vx; + x -= vx; + vx = 0; + } + if (vy < 0) { + h += vy; + y -= vy; + vy = 0; } - if (this._prefer_js) { - var bgr; - if (this._true_color) { - bgr = color; - } else { - bgr = this._colourMap[color[0]]; - } - var red = bgr[2]; - var green = bgr[1]; - var blue = bgr[0]; - - var data = this._tile.data; - for (var i = 0; i < width * height * 4; i += 4) { - data[i] = red; - data[i + 1] = green; - data[i + 2] = blue; - data[i + 3] = 255; - } - } else { - this.fillRect(x, y, width, height, color, true); + if ((vx + w) > this._viewportLoc.w) { + w = this._viewportLoc.w - vx; } - }, - - // update sub-rectangle of the current tile - subTile: function (x, y, w, h, color) { - if (this._prefer_js) { - var bgr; - if (this._true_color) { - bgr = color; - } else { - bgr = this._colourMap[color[0]]; - } - var red = bgr[2]; - var green = bgr[1]; - var blue = bgr[0]; - var xend = x + w; - var yend = y + h; - - var data = this._tile.data; - var width = this._tile.width; - for (var j = y; j < yend; j++) { - for (var i = x; i < xend; i++) { - var p = (i + (j * width)) * 4; - data[p] = red; - data[p + 1] = green; - data[p + 2] = blue; - data[p + 3] = 255; - } - } - } else { - this.fillRect(this._tile_x + x, this._tile_y + y, w, h, color, true); - } - }, - - // draw the current tile to the screen - finishTile: function () { - if (this._prefer_js) { - this._drawCtx.putImageData(this._tile, this._tile_x, this._tile_y); - this._damage(this._tile_x, this._tile_y, - this._tile.width, this._tile.height); - } - // else: No-op -- already done by setSubTile - }, - - blitImage: function (x, y, width, height, arr, offset, from_queue) { - if (this._renderQ.length !== 0 && !from_queue) { - // NB(directxman12): it's technically more performant here to use preallocated arrays, - // but it's a lot of extra work for not a lot of payoff -- if we're using the render queue, - // this probably isn't getting called *nearly* as much - var new_arr = new Uint8Array(width * height * 4); - new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length)); - this._renderQ_push({ - 'type': 'blit', - 'data': new_arr, - 'x': x, - 'y': y, - 'width': width, - 'height': height, - }); - } else if (this._true_color) { - this._bgrxImageData(x, y, width, height, arr, offset); - } else { - this._cmapImageData(x, y, width, height, arr, offset); - } - }, - - blitRgbImage: function (x, y , width, height, arr, offset, from_queue) { - if (this._renderQ.length !== 0 && !from_queue) { - // NB(directxman12): it's technically more performant here to use preallocated arrays, - // but it's a lot of extra work for not a lot of payoff -- if we're using the render queue, - // this probably isn't getting called *nearly* as much - var new_arr = new Uint8Array(width * height * 3); - new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length)); - this._renderQ_push({ - 'type': 'blitRgb', - 'data': new_arr, - 'x': x, - 'y': y, - 'width': width, - 'height': height, - }); - } else if (this._true_color) { - this._rgbImageData(x, y, width, height, arr, offset); - } else { - // probably wrong? - this._cmapImageData(x, y, width, height, arr, offset); - } - }, - - blitRgbxImage: function (x, y, width, height, arr, offset, from_queue) { - if (this._renderQ.length !== 0 && !from_queue) { - // NB(directxman12): it's technically more performant here to use preallocated arrays, - // but it's a lot of extra work for not a lot of payoff -- if we're using the render queue, - // this probably isn't getting called *nearly* as much - var new_arr = new Uint8Array(width * height * 4); - new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length)); - this._renderQ_push({ - 'type': 'blitRgbx', - 'data': new_arr, - 'x': x, - 'y': y, - 'width': width, - 'height': height, - }); - } else { - this._rgbxImageData(x, y, width, height, arr, offset); - } - }, - - drawImage: function (img, x, y) { - this._drawCtx.drawImage(img, x, y); - this._damage(x, y, img.width, img.height); - }, - - changeCursor: function (pixels, mask, hotx, hoty, w, h) { - if (this._cursor_uri === false) { - Util.Warn("changeCursor called but no cursor data URI support"); - return; + if ((vy + h) > this._viewportLoc.h) { + h = this._viewportLoc.h - vy; } - if (this._true_color) { - Display.changeCursor(this._target, pixels, mask, hotx, hoty, w, h); - } else { - Display.changeCursor(this._target, pixels, mask, hotx, hoty, w, h, this._colourMap); - } - }, - - defaultCursor: function () { - this._target.style.cursor = "default"; - }, - - disableLocalCursor: function () { - this._target.style.cursor = "none"; - }, - - clippingDisplay: function () { - var vp = this._viewportLoc; - return this._fb_width > vp.w || this._fb_height > vp.h; - }, - - // Overridden getters/setters - set_scale: function (scale) { - this._rescale(scale); - }, - - set_viewport: function (viewport) { - this._viewport = viewport; - // May need to readjust the viewport dimensions - var vp = this._viewportLoc; - this.viewportChangeSize(vp.w, vp.h); - this.viewportChangePos(0, 0); - }, - - get_width: function () { - return this._fb_width; - }, - get_height: function () { - return this._fb_height; - }, - - autoscale: function (containerWidth, containerHeight, downscaleOnly) { - var vp = this._viewportLoc; - var targetAspectRatio = containerWidth / containerHeight; - var fbAspectRatio = vp.w / vp.h; - - var scaleRatio; - if (fbAspectRatio >= targetAspectRatio) { - scaleRatio = containerWidth / vp.w; - } else { - scaleRatio = containerHeight / vp.h; + if ((w > 0) && (h > 0)) { + // FIXME: We may need to disable image smoothing here + // as well (see copyImage()), but we haven't + // noticed any problem yet. + this._targetCtx.drawImage(this._backbuffer, + x, y, w, h, + vx, vy, w, h); } - if (scaleRatio > 1.0 && downscaleOnly) { - scaleRatio = 1.0; - } + this._damageBounds.left = this._damageBounds.top = 65535; + this._damageBounds.right = this._damageBounds.bottom = 0; + } + }, - this._rescale(scaleRatio); - }, + clear: function () { + if (this._logo) { + this.resize(this._logo.width, this._logo.height); + this.imageRect(0, 0, this._logo.type, this._logo.data); + } else { + this.resize(240, 20); + this._drawCtx.clearRect(0, 0, this._fb_width, this._fb_height); + } + this.flip(); + }, - // Private Methods - _rescale: function (factor) { - this._scale = factor; - var vp = this._viewportLoc; + pending: function() { + return this._renderQ.length > 0; + }, - // NB(directxman12): If you set the width directly, or set the - // style width to a number, the canvas is cleared. - // However, if you set the style width to a string - // ('NNNpx'), the canvas is scaled without clearing. - var width = Math.round(factor * vp.w) + 'px'; - var height = Math.round(factor * vp.h) + 'px'; + flush: function() { + if (this._renderQ.length === 0) { + this._onFlush(); + } else { + this._flushing = true; + } + }, - if ((this._target.style.width !== width) || - (this._target.style.height !== height)) { - this._target.style.width = width; - this._target.style.height = height; - } - }, + fillRect: function (x, y, width, height, color, from_queue) { + if (this._renderQ.length !== 0 && !from_queue) { + this._renderQ_push({ + 'type': 'fill', + 'x': x, + 'y': y, + 'width': width, + 'height': height, + 'color': color + }); + } else { + this._setFillColor(color); + this._drawCtx.fillRect(x, y, width, height); + this._damage(x, y, width, height); + } + }, - _setFillColor: function (color) { + copyImage: function (old_x, old_y, new_x, new_y, w, h, from_queue) { + if (this._renderQ.length !== 0 && !from_queue) { + this._renderQ_push({ + 'type': 'copy', + 'old_x': old_x, + 'old_y': old_y, + 'x': new_x, + 'y': new_y, + 'width': w, + 'height': h, + }); + } else { + // Due to this bug among others [1] we need to disable the image-smoothing to + // avoid getting a blur effect when copying data. + // + // 1. https://bugzilla.mozilla.org/show_bug.cgi?id=1194719 + // + // We need to set these every time since all properties are reset + // when the the size is changed + this._drawCtx.mozImageSmoothingEnabled = false; + this._drawCtx.webkitImageSmoothingEnabled = false; + this._drawCtx.msImageSmoothingEnabled = false; + this._drawCtx.imageSmoothingEnabled = false; + + this._drawCtx.drawImage(this._backbuffer, + old_x, old_y, w, h, + new_x, new_y, w, h); + this._damage(new_x, new_y, w, h); + } + }, + + imageRect: function(x, y, mime, arr) { + var img = new Image(); + img.src = "data: " + mime + ";base64," + Base64.encode(arr); + this._renderQ_push({ + 'type': 'img', + 'img': img, + 'x': x, + 'y': y + }); + }, + + // start updating a tile + startTile: function (x, y, width, height, color) { + this._tile_x = x; + this._tile_y = y; + if (width === 16 && height === 16) { + this._tile = this._tile16x16; + } else { + this._tile = this._drawCtx.createImageData(width, height); + } + + if (this._prefer_js) { var bgr; if (this._true_color) { bgr = color; } else { - bgr = this._colourMap[color]; + bgr = this._colourMap[color[0]]; } + var red = bgr[2]; + var green = bgr[1]; + var blue = bgr[0]; - var newStyle = 'rgb(' + bgr[2] + ',' + bgr[1] + ',' + bgr[0] + ')'; - if (newStyle !== this._prevDrawStyle) { - this._drawCtx.fillStyle = newStyle; - this._prevDrawStyle = newStyle; + var data = this._tile.data; + for (var i = 0; i < width * height * 4; i += 4) { + data[i] = red; + data[i + 1] = green; + data[i + 2] = blue; + data[i + 3] = 255; } - }, - - _rgbImageData: function (x, y, width, height, arr, offset) { - var img = this._drawCtx.createImageData(width, height); - var data = img.data; - for (var i = 0, j = offset; i < width * height * 4; i += 4, j += 3) { - data[i] = arr[j]; - data[i + 1] = arr[j + 1]; - data[i + 2] = arr[j + 2]; - data[i + 3] = 255; // Alpha - } - this._drawCtx.putImageData(img, x, y); - this._damage(x, y, img.width, img.height); - }, - - _bgrxImageData: function (x, y, width, height, arr, offset) { - var img = this._drawCtx.createImageData(width, height); - var data = img.data; - for (var i = 0, j = offset; i < width * height * 4; i += 4, j += 4) { - data[i] = arr[j + 2]; - data[i + 1] = arr[j + 1]; - data[i + 2] = arr[j]; - data[i + 3] = 255; // Alpha - } - this._drawCtx.putImageData(img, x, y); - this._damage(x, y, img.width, img.height); - }, - - _rgbxImageData: function (x, y, width, height, arr, offset) { - // NB(directxman12): arr must be an Type Array view - var img; - if (SUPPORTS_IMAGEDATA_CONSTRUCTOR) { - img = new ImageData(new Uint8ClampedArray(arr.buffer, arr.byteOffset, width * height * 4), width, height); - } else { - img = this._drawCtx.createImageData(width, height); - img.data.set(new Uint8ClampedArray(arr.buffer, arr.byteOffset, width * height * 4)); - } - this._drawCtx.putImageData(img, x, y); - this._damage(x, y, img.width, img.height); - }, - - _cmapImageData: function (x, y, width, height, arr, offset) { - var img = this._drawCtx.createImageData(width, height); - var data = img.data; - var cmap = this._colourMap; - for (var i = 0, j = offset; i < width * height * 4; i += 4, j++) { - var bgr = cmap[arr[j]]; - data[i] = bgr[2]; - data[i + 1] = bgr[1]; - data[i + 2] = bgr[0]; - data[i + 3] = 255; // Alpha - } - this._drawCtx.putImageData(img, x, y); - this._damage(x, y, img.width, img.height); - }, - - _renderQ_push: function (action) { - this._renderQ.push(action); - if (this._renderQ.length === 1) { - // If this can be rendered immediately it will be, otherwise - // the scanner will wait for the relevant event - this._scan_renderQ(); - } - }, - - _resume_renderQ: function() { - // "this" is the object that is ready, not the - // display object - this.removeEventListener('load', this._noVNC_display._resume_renderQ); - this._noVNC_display._scan_renderQ(); - }, - - _scan_renderQ: function () { - var ready = true; - while (ready && this._renderQ.length > 0) { - var a = this._renderQ[0]; - switch (a.type) { - case 'flip': - this.flip(true); - break; - case 'copy': - this.copyImage(a.old_x, a.old_y, a.x, a.y, a.width, a.height, true); - break; - case 'fill': - this.fillRect(a.x, a.y, a.width, a.height, a.color, true); - break; - case 'blit': - this.blitImage(a.x, a.y, a.width, a.height, a.data, 0, true); - break; - case 'blitRgb': - this.blitRgbImage(a.x, a.y, a.width, a.height, a.data, 0, true); - break; - case 'blitRgbx': - this.blitRgbxImage(a.x, a.y, a.width, a.height, a.data, 0, true); - break; - case 'img': - if (a.img.complete) { - this.drawImage(a.img, a.x, a.y); - } else { - a.img._noVNC_display = this; - a.img.addEventListener('load', this._resume_renderQ); - // We need to wait for this image to 'load' - // to keep things in-order - ready = false; - } - break; - } - - if (ready) { - this._renderQ.shift(); - } - } - - if (this._renderQ.length === 0 && this._flushing) { - this._flushing = false; - this._onFlush(); - } - }, - }; - - Util.make_properties(Display, [ - ['target', 'wo', 'dom'], // Canvas element for rendering - ['context', 'ro', 'raw'], // Canvas 2D context for rendering (read-only) - ['logo', 'rw', 'raw'], // Logo to display when cleared: {"width": w, "height": h, "type": mime-type, "data": data} - ['true_color', 'rw', 'bool'], // Use true-color pixel data - ['colourMap', 'rw', 'arr'], // Colour map array (when not true-color) - ['scale', 'rw', 'float'], // Display area scale factor 0.0 - 1.0 - ['viewport', 'rw', 'bool'], // Use viewport clipping - ['width', 'ro', 'int'], // Display area width - ['height', 'ro', 'int'], // Display area height - - ['render_mode', 'ro', 'str'], // Canvas rendering mode (read-only) - - ['prefer_js', 'rw', 'str'], // Prefer Javascript over canvas methods - ['cursor_uri', 'rw', 'raw'], // Can we render cursor using data URI - - ['onFlush', 'rw', 'func'], // onFlush(): A flush request has finished - ]); - - // Class Methods - Display.changeCursor = function (target, pixels, mask, hotx, hoty, w0, h0, cmap) { - var w = w0; - var h = h0; - if (h < w) { - h = w; // increase h to make it square } else { - w = h; // increase w to make it square + this.fillRect(x, y, width, height, color, true); + } + }, + + // update sub-rectangle of the current tile + subTile: function (x, y, w, h, color) { + if (this._prefer_js) { + var bgr; + if (this._true_color) { + bgr = color; + } else { + bgr = this._colourMap[color[0]]; + } + var red = bgr[2]; + var green = bgr[1]; + var blue = bgr[0]; + var xend = x + w; + var yend = y + h; + + var data = this._tile.data; + var width = this._tile.width; + for (var j = y; j < yend; j++) { + for (var i = x; i < xend; i++) { + var p = (i + (j * width)) * 4; + data[p] = red; + data[p + 1] = green; + data[p + 2] = blue; + data[p + 3] = 255; + } + } + } else { + this.fillRect(this._tile_x + x, this._tile_y + y, w, h, color, true); + } + }, + + // draw the current tile to the screen + finishTile: function () { + if (this._prefer_js) { + this._drawCtx.putImageData(this._tile, this._tile_x, this._tile_y); + this._damage(this._tile_x, this._tile_y, + this._tile.width, this._tile.height); + } + // else: No-op -- already done by setSubTile + }, + + blitImage: function (x, y, width, height, arr, offset, from_queue) { + if (this._renderQ.length !== 0 && !from_queue) { + // NB(directxman12): it's technically more performant here to use preallocated arrays, + // but it's a lot of extra work for not a lot of payoff -- if we're using the render queue, + // this probably isn't getting called *nearly* as much + var new_arr = new Uint8Array(width * height * 4); + new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length)); + this._renderQ_push({ + 'type': 'blit', + 'data': new_arr, + 'x': x, + 'y': y, + 'width': width, + 'height': height, + }); + } else if (this._true_color) { + this._bgrxImageData(x, y, width, height, arr, offset); + } else { + this._cmapImageData(x, y, width, height, arr, offset); + } + }, + + blitRgbImage: function (x, y , width, height, arr, offset, from_queue) { + if (this._renderQ.length !== 0 && !from_queue) { + // NB(directxman12): it's technically more performant here to use preallocated arrays, + // but it's a lot of extra work for not a lot of payoff -- if we're using the render queue, + // this probably isn't getting called *nearly* as much + var new_arr = new Uint8Array(width * height * 3); + new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length)); + this._renderQ_push({ + 'type': 'blitRgb', + 'data': new_arr, + 'x': x, + 'y': y, + 'width': width, + 'height': height, + }); + } else if (this._true_color) { + this._rgbImageData(x, y, width, height, arr, offset); + } else { + // probably wrong? + this._cmapImageData(x, y, width, height, arr, offset); + } + }, + + blitRgbxImage: function (x, y, width, height, arr, offset, from_queue) { + if (this._renderQ.length !== 0 && !from_queue) { + // NB(directxman12): it's technically more performant here to use preallocated arrays, + // but it's a lot of extra work for not a lot of payoff -- if we're using the render queue, + // this probably isn't getting called *nearly* as much + var new_arr = new Uint8Array(width * height * 4); + new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length)); + this._renderQ_push({ + 'type': 'blitRgbx', + 'data': new_arr, + 'x': x, + 'y': y, + 'width': width, + 'height': height, + }); + } else { + this._rgbxImageData(x, y, width, height, arr, offset); + } + }, + + drawImage: function (img, x, y) { + this._drawCtx.drawImage(img, x, y); + this._damage(x, y, img.width, img.height); + }, + + changeCursor: function (pixels, mask, hotx, hoty, w, h) { + if (this._cursor_uri === false) { + Log.Warn("changeCursor called but no cursor data URI support"); + return; } - var cur = []; + if (this._true_color) { + Display.changeCursor(this._target, pixels, mask, hotx, hoty, w, h); + } else { + Display.changeCursor(this._target, pixels, mask, hotx, hoty, w, h, this._colourMap); + } + }, - // Push multi-byte little-endian values - cur.push16le = function (num) { - this.push(num & 0xFF, (num >> 8) & 0xFF); - }; - cur.push32le = function (num) { - this.push(num & 0xFF, - (num >> 8) & 0xFF, - (num >> 16) & 0xFF, - (num >> 24) & 0xFF); - }; + defaultCursor: function () { + this._target.style.cursor = "default"; + }, - var IHDRsz = 40; - var RGBsz = w * h * 4; - var XORsz = Math.ceil((w * h) / 8.0); - var ANDsz = Math.ceil((w * h) / 8.0); + disableLocalCursor: function () { + this._target.style.cursor = "none"; + }, - cur.push16le(0); // 0: Reserved - cur.push16le(2); // 2: .CUR type - cur.push16le(1); // 4: Number of images, 1 for non-animated ico + clippingDisplay: function () { + var vp = this._viewportLoc; + return this._fb_width > vp.w || this._fb_height > vp.h; + }, - // Cursor #1 header (ICONDIRENTRY) - cur.push(w); // 6: width - cur.push(h); // 7: height - cur.push(0); // 8: colors, 0 -> true-color - cur.push(0); // 9: reserved - cur.push16le(hotx); // 10: hotspot x coordinate - cur.push16le(hoty); // 12: hotspot y coordinate - cur.push32le(IHDRsz + RGBsz + XORsz + ANDsz); - // 14: cursor data byte size - cur.push32le(22); // 18: offset of cursor data in the file + // Overridden getters/setters + set_scale: function (scale) { + this._rescale(scale); + }, - // Cursor #1 InfoHeader (ICONIMAGE/BITMAPINFO) - cur.push32le(IHDRsz); // 22: InfoHeader size - cur.push32le(w); // 26: Cursor width - cur.push32le(h * 2); // 30: XOR+AND height - cur.push16le(1); // 34: number of planes - cur.push16le(32); // 36: bits per pixel - cur.push32le(0); // 38: Type of compression + set_viewport: function (viewport) { + this._viewport = viewport; + // May need to readjust the viewport dimensions + var vp = this._viewportLoc; + this.viewportChangeSize(vp.w, vp.h); + this.viewportChangePos(0, 0); + }, - cur.push32le(XORsz + ANDsz); - // 42: Size of Image - cur.push32le(0); // 46: reserved - cur.push32le(0); // 50: reserved - cur.push32le(0); // 54: reserved - cur.push32le(0); // 58: reserved + get_width: function () { + return this._fb_width; + }, + get_height: function () { + return this._fb_height; + }, - // 62: color data (RGBQUAD icColors[]) - var y, x; - for (y = h - 1; y >= 0; y--) { - for (x = 0; x < w; x++) { - if (x >= w0 || y >= h0) { - cur.push(0); // blue - cur.push(0); // green - cur.push(0); // red - cur.push(0); // alpha - } else { - var idx = y * Math.ceil(w0 / 8) + Math.floor(x / 8); - var alpha = (mask[idx] << (x % 8)) & 0x80 ? 255 : 0; - if (cmap) { - idx = (w0 * y) + x; - var rgb = cmap[pixels[idx]]; - cur.push(rgb[2]); // blue - cur.push(rgb[1]); // green - cur.push(rgb[0]); // red - cur.push(alpha); // alpha + autoscale: function (containerWidth, containerHeight, downscaleOnly) { + var vp = this._viewportLoc; + var targetAspectRatio = containerWidth / containerHeight; + var fbAspectRatio = vp.w / vp.h; + + var scaleRatio; + if (fbAspectRatio >= targetAspectRatio) { + scaleRatio = containerWidth / vp.w; + } else { + scaleRatio = containerHeight / vp.h; + } + + if (scaleRatio > 1.0 && downscaleOnly) { + scaleRatio = 1.0; + } + + this._rescale(scaleRatio); + }, + + // Private Methods + _rescale: function (factor) { + this._scale = factor; + var vp = this._viewportLoc; + + // NB(directxman12): If you set the width directly, or set the + // style width to a number, the canvas is cleared. + // However, if you set the style width to a string + // ('NNNpx'), the canvas is scaled without clearing. + var width = Math.round(factor * vp.w) + 'px'; + var height = Math.round(factor * vp.h) + 'px'; + + if ((this._target.style.width !== width) || + (this._target.style.height !== height)) { + this._target.style.width = width; + this._target.style.height = height; + } + }, + + _setFillColor: function (color) { + var bgr; + if (this._true_color) { + bgr = color; + } else { + bgr = this._colourMap[color]; + } + + var newStyle = 'rgb(' + bgr[2] + ',' + bgr[1] + ',' + bgr[0] + ')'; + if (newStyle !== this._prevDrawStyle) { + this._drawCtx.fillStyle = newStyle; + this._prevDrawStyle = newStyle; + } + }, + + _rgbImageData: function (x, y, width, height, arr, offset) { + var img = this._drawCtx.createImageData(width, height); + var data = img.data; + for (var i = 0, j = offset; i < width * height * 4; i += 4, j += 3) { + data[i] = arr[j]; + data[i + 1] = arr[j + 1]; + data[i + 2] = arr[j + 2]; + data[i + 3] = 255; // Alpha + } + this._drawCtx.putImageData(img, x, y); + this._damage(x, y, img.width, img.height); + }, + + _bgrxImageData: function (x, y, width, height, arr, offset) { + var img = this._drawCtx.createImageData(width, height); + var data = img.data; + for (var i = 0, j = offset; i < width * height * 4; i += 4, j += 4) { + data[i] = arr[j + 2]; + data[i + 1] = arr[j + 1]; + data[i + 2] = arr[j]; + data[i + 3] = 255; // Alpha + } + this._drawCtx.putImageData(img, x, y); + this._damage(x, y, img.width, img.height); + }, + + _rgbxImageData: function (x, y, width, height, arr, offset) { + // NB(directxman12): arr must be an Type Array view + var img; + if (SUPPORTS_IMAGEDATA_CONSTRUCTOR) { + img = new ImageData(new Uint8ClampedArray(arr.buffer, arr.byteOffset, width * height * 4), width, height); + } else { + img = this._drawCtx.createImageData(width, height); + img.data.set(new Uint8ClampedArray(arr.buffer, arr.byteOffset, width * height * 4)); + } + this._drawCtx.putImageData(img, x, y); + this._damage(x, y, img.width, img.height); + }, + + _cmapImageData: function (x, y, width, height, arr, offset) { + var img = this._drawCtx.createImageData(width, height); + var data = img.data; + var cmap = this._colourMap; + for (var i = 0, j = offset; i < width * height * 4; i += 4, j++) { + var bgr = cmap[arr[j]]; + data[i] = bgr[2]; + data[i + 1] = bgr[1]; + data[i + 2] = bgr[0]; + data[i + 3] = 255; // Alpha + } + this._drawCtx.putImageData(img, x, y); + this._damage(x, y, img.width, img.height); + }, + + _renderQ_push: function (action) { + this._renderQ.push(action); + if (this._renderQ.length === 1) { + // If this can be rendered immediately it will be, otherwise + // the scanner will wait for the relevant event + this._scan_renderQ(); + } + }, + + _resume_renderQ: function() { + // "this" is the object that is ready, not the + // display object + this.removeEventListener('load', this._noVNC_display._resume_renderQ); + this._noVNC_display._scan_renderQ(); + }, + + _scan_renderQ: function () { + var ready = true; + while (ready && this._renderQ.length > 0) { + var a = this._renderQ[0]; + switch (a.type) { + case 'flip': + this.flip(true); + break; + case 'copy': + this.copyImage(a.old_x, a.old_y, a.x, a.y, a.width, a.height, true); + break; + case 'fill': + this.fillRect(a.x, a.y, a.width, a.height, a.color, true); + break; + case 'blit': + this.blitImage(a.x, a.y, a.width, a.height, a.data, 0, true); + break; + case 'blitRgb': + this.blitRgbImage(a.x, a.y, a.width, a.height, a.data, 0, true); + break; + case 'blitRgbx': + this.blitRgbxImage(a.x, a.y, a.width, a.height, a.data, 0, true); + break; + case 'img': + if (a.img.complete) { + this.drawImage(a.img, a.x, a.y); } else { - idx = ((w0 * y) + x) * 4; - cur.push(pixels[idx]); // blue - cur.push(pixels[idx + 1]); // green - cur.push(pixels[idx + 2]); // red - cur.push(alpha); // alpha + a.img._noVNC_display = this; + a.img.addEventListener('load', this._resume_renderQ); + // We need to wait for this image to 'load' + // to keep things in-order + ready = false; } + break; + } + + if (ready) { + this._renderQ.shift(); + } + } + + if (this._renderQ.length === 0 && this._flushing) { + this._flushing = false; + this._onFlush(); + } + }, +}; + +make_properties(Display, [ + ['target', 'wo', 'dom'], // Canvas element for rendering + ['context', 'ro', 'raw'], // Canvas 2D context for rendering (read-only) + ['logo', 'rw', 'raw'], // Logo to display when cleared: {"width": w, "height": h, "type": mime-type, "data": data} + ['true_color', 'rw', 'bool'], // Use true-color pixel data + ['colourMap', 'rw', 'arr'], // Colour map array (when not true-color) + ['scale', 'rw', 'float'], // Display area scale factor 0.0 - 1.0 + ['viewport', 'rw', 'bool'], // Use viewport clipping + ['width', 'ro', 'int'], // Display area width + ['height', 'ro', 'int'], // Display area height + + ['render_mode', 'ro', 'str'], // Canvas rendering mode (read-only) + + ['prefer_js', 'rw', 'str'], // Prefer Javascript over canvas methods + ['cursor_uri', 'rw', 'raw'], // Can we render cursor using data URI + + ['onFlush', 'rw', 'func'], // onFlush(): A flush request has finished +]); + +// Class Methods +Display.changeCursor = function (target, pixels, mask, hotx, hoty, w0, h0, cmap) { + var w = w0; + var h = h0; + if (h < w) { + h = w; // increase h to make it square + } else { + w = h; // increase w to make it square + } + + var cur = []; + + // Push multi-byte little-endian values + cur.push16le = function (num) { + this.push(num & 0xFF, (num >> 8) & 0xFF); + }; + cur.push32le = function (num) { + this.push(num & 0xFF, + (num >> 8) & 0xFF, + (num >> 16) & 0xFF, + (num >> 24) & 0xFF); + }; + + var IHDRsz = 40; + var RGBsz = w * h * 4; + var XORsz = Math.ceil((w * h) / 8.0); + var ANDsz = Math.ceil((w * h) / 8.0); + + cur.push16le(0); // 0: Reserved + cur.push16le(2); // 2: .CUR type + cur.push16le(1); // 4: Number of images, 1 for non-animated ico + + // Cursor #1 header (ICONDIRENTRY) + cur.push(w); // 6: width + cur.push(h); // 7: height + cur.push(0); // 8: colors, 0 -> true-color + cur.push(0); // 9: reserved + cur.push16le(hotx); // 10: hotspot x coordinate + cur.push16le(hoty); // 12: hotspot y coordinate + cur.push32le(IHDRsz + RGBsz + XORsz + ANDsz); + // 14: cursor data byte size + cur.push32le(22); // 18: offset of cursor data in the file + + // Cursor #1 InfoHeader (ICONIMAGE/BITMAPINFO) + cur.push32le(IHDRsz); // 22: InfoHeader size + cur.push32le(w); // 26: Cursor width + cur.push32le(h * 2); // 30: XOR+AND height + cur.push16le(1); // 34: number of planes + cur.push16le(32); // 36: bits per pixel + cur.push32le(0); // 38: Type of compression + + cur.push32le(XORsz + ANDsz); + // 42: Size of Image + cur.push32le(0); // 46: reserved + cur.push32le(0); // 50: reserved + cur.push32le(0); // 54: reserved + cur.push32le(0); // 58: reserved + + // 62: color data (RGBQUAD icColors[]) + var y, x; + for (y = h - 1; y >= 0; y--) { + for (x = 0; x < w; x++) { + if (x >= w0 || y >= h0) { + cur.push(0); // blue + cur.push(0); // green + cur.push(0); // red + cur.push(0); // alpha + } else { + var idx = y * Math.ceil(w0 / 8) + Math.floor(x / 8); + var alpha = (mask[idx] << (x % 8)) & 0x80 ? 255 : 0; + if (cmap) { + idx = (w0 * y) + x; + var rgb = cmap[pixels[idx]]; + cur.push(rgb[2]); // blue + cur.push(rgb[1]); // green + cur.push(rgb[0]); // red + cur.push(alpha); // alpha + } else { + idx = ((w0 * y) + x) * 4; + cur.push(pixels[idx]); // blue + cur.push(pixels[idx + 1]); // green + cur.push(pixels[idx + 2]); // red + cur.push(alpha); // alpha } } } + } - // XOR/bitmask data (BYTE icXOR[]) - // (ignored, just needs to be the right size) - for (y = 0; y < h; y++) { - for (x = 0; x < Math.ceil(w / 8); x++) { - cur.push(0); - } + // XOR/bitmask data (BYTE icXOR[]) + // (ignored, just needs to be the right size) + for (y = 0; y < h; y++) { + for (x = 0; x < Math.ceil(w / 8); x++) { + cur.push(0); } + } - // AND/bitmask data (BYTE icAND[]) - // (ignored, just needs to be the right size) - for (y = 0; y < h; y++) { - for (x = 0; x < Math.ceil(w / 8); x++) { - cur.push(0); - } + // AND/bitmask data (BYTE icAND[]) + // (ignored, just needs to be the right size) + for (y = 0; y < h; y++) { + for (x = 0; x < Math.ceil(w / 8); x++) { + cur.push(0); } + } - var url = 'data:image/x-icon;base64,' + Base64.encode(cur); - target.style.cursor = 'url(' + url + ')' + hotx + ' ' + hoty + ', default'; - }; -})(); + var url = 'data:image/x-icon;base64,' + Base64.encode(cur); + target.style.cursor = 'url(' + url + ')' + hotx + ' ' + hoty + ', default'; +}; diff --git a/core/inflator.js b/core/inflator.js index 973836d7..a4d6ff6a 100644 --- a/core/inflator.js +++ b/core/inflator.js @@ -1,15 +1,5 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Inflator = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o>> 16) & 0xffff) |0, - n = 0; - - while (len !== 0) { - // Set limit ~ twice less than 5552, to keep - // s2 in 31-bits, because we force signed ints. - // in other case %= will fail. - n = len > 2000 ? 2000 : len; - len -= n; - - do { - s1 = (s1 + buf[pos++]) |0; - s2 = (s2 + s1) |0; - } while (--n); - - s1 %= 65521; - s2 %= 65521; - } - - return (s1 | (s2 << 16)) |0; -} - - -module.exports = adler32; - -},{}],4:[function(require,module,exports){ -'use strict'; - -// Note: we can't get significant speed boost here. -// So write code to minimize size - no pregenerated tables -// and array tools dependencies. - - -// Use ordinary array, since untyped makes no boost here -function makeTable() { - var c, table = []; - - for (var n = 0; n < 256; n++) { - c = n; - for (var k = 0; k < 8; k++) { - c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); - } - table[n] = c; - } - - return table; -} - -// Create table on load. Just 255 signed longs. Not a problem. -var crcTable = makeTable(); - - -function crc32(crc, buf, len, pos) { - var t = crcTable, - end = pos + len; - - crc ^= -1; - - for (var i = pos; i < end; i++) { - crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; - } - - return (crc ^ (-1)); // >>> 0; -} - - -module.exports = crc32; - -},{}],5:[function(require,module,exports){ -'use strict'; - -// See state defs from inflate.js -var BAD = 30; /* got a data error -- remain here until reset */ -var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state.mode === LEN - strm.avail_in >= 6 - strm.avail_out >= 258 - start >= strm.avail_out - state.bits < 8 - - On return, state.mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm.avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm.avail_out >= 258 for each loop to avoid checking for - output space. - */ -module.exports = function inflate_fast(strm, start) { - var state; - var _in; /* local strm.input */ - var last; /* have enough input while in < last */ - var _out; /* local strm.output */ - var beg; /* inflate()'s initial strm.output */ - var end; /* while out < end, enough space available */ -//#ifdef INFLATE_STRICT - var dmax; /* maximum distance from zlib header */ -//#endif - var wsize; /* window size or zero if not using window */ - var whave; /* valid bytes in the window */ - var wnext; /* window write index */ - // Use `s_window` instead `window`, avoid conflict with instrumentation tools - var s_window; /* allocated sliding window, if wsize != 0 */ - var hold; /* local strm.hold */ - var bits; /* local strm.bits */ - var lcode; /* local strm.lencode */ - var dcode; /* local strm.distcode */ - var lmask; /* mask for first level of length codes */ - var dmask; /* mask for first level of distance codes */ - var here; /* retrieved table entry */ - var op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - var len; /* match length, unused bytes */ - var dist; /* match distance */ - var from; /* where to copy match from */ - var from_source; - - - var input, output; // JS specific, because we have no pointers - - /* copy state to local variables */ - state = strm.state; - //here = state.here; - _in = strm.next_in; - input = strm.input; - last = _in + (strm.avail_in - 5); - _out = strm.next_out; - output = strm.output; - beg = _out - (start - strm.avail_out); - end = _out + (strm.avail_out - 257); -//#ifdef INFLATE_STRICT - dmax = state.dmax; -//#endif - wsize = state.wsize; - whave = state.whave; - wnext = state.wnext; - s_window = state.window; - hold = state.hold; - bits = state.bits; - lcode = state.lencode; - dcode = state.distcode; - lmask = (1 << state.lenbits) - 1; - dmask = (1 << state.distbits) - 1; - - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - top: - do { - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - - here = lcode[hold & lmask]; - - dolen: - for (;;) { // Goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = (here >>> 16) & 0xff/*here.op*/; - if (op === 0) { /* literal */ - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - output[_out++] = here & 0xffff/*here.val*/; - } - else if (op & 16) { /* length base */ - len = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - len += hold & ((1 << op) - 1); - hold >>>= op; - bits -= op; - } - //Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - here = dcode[hold & dmask]; - - dodist: - for (;;) { // goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = (here >>> 16) & 0xff/*here.op*/; - - if (op & 16) { /* distance base */ - dist = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - } - dist += hold & ((1 << op) - 1); -//#ifdef INFLATE_STRICT - if (dist > dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break top; - } -//#endif - hold >>>= op; - bits -= op; - //Tracevv((stderr, "inflate: distance %u\n", dist)); - op = _out - beg; /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break top; - } - -// (!) This block is disabled in zlib defailts, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// if (len <= op - whave) { -// do { -// output[_out++] = 0; -// } while (--len); -// continue top; -// } -// len -= op - whave; -// do { -// output[_out++] = 0; -// } while (--op > whave); -// if (op === 0) { -// from = _out - dist; -// do { -// output[_out++] = output[from++]; -// } while (--len); -// continue top; -// } -//#endif - } - from = 0; // window index - from_source = s_window; - if (wnext === 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = 0; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - } - else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - while (len > 2) { - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - len -= 3; - } - if (len) { - output[_out++] = from_source[from++]; - if (len > 1) { - output[_out++] = from_source[from++]; - } - } - } - else { - from = _out - dist; /* copy direct from output */ - do { /* minimum length is three */ - output[_out++] = output[from++]; - output[_out++] = output[from++]; - output[_out++] = output[from++]; - len -= 3; - } while (len > 2); - if (len) { - output[_out++] = output[from++]; - if (len > 1) { - output[_out++] = output[from++]; - } - } - } - } - else if ((op & 64) === 0) { /* 2nd level distance code */ - here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dodist; - } - else { - strm.msg = 'invalid distance code'; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } - else if ((op & 64) === 0) { /* 2nd level length code */ - here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dolen; - } - else if (op & 32) { /* end-of-block */ - //Tracevv((stderr, "inflate: end of block\n")); - state.mode = TYPE; - break top; - } - else { - strm.msg = 'invalid literal/length code'; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } while (_in < last && _out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - _in -= len; - bits -= len << 3; - hold &= (1 << bits) - 1; - - /* update state and return */ - strm.next_in = _in; - strm.next_out = _out; - strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); - strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); - state.hold = hold; - state.bits = bits; - return; -}; - -},{}],6:[function(require,module,exports){ -'use strict'; - - -var utils = require('../utils/common'); -var adler32 = require('./adler32'); -var crc32 = require('./crc32'); -var inflate_fast = require('./inffast'); -var inflate_table = require('./inftrees'); - -var CODES = 0; -var LENS = 1; -var DISTS = 2; - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - - -/* Allowed flush values; see deflate() and inflate() below for details */ -//var Z_NO_FLUSH = 0; -//var Z_PARTIAL_FLUSH = 1; -//var Z_SYNC_FLUSH = 2; -//var Z_FULL_FLUSH = 3; -var Z_FINISH = 4; -var Z_BLOCK = 5; -var Z_TREES = 6; - - -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ -var Z_OK = 0; -var Z_STREAM_END = 1; -var Z_NEED_DICT = 2; -//var Z_ERRNO = -1; -var Z_STREAM_ERROR = -2; -var Z_DATA_ERROR = -3; -var Z_MEM_ERROR = -4; -var Z_BUF_ERROR = -5; -//var Z_VERSION_ERROR = -6; - -/* The deflate compression method */ -var Z_DEFLATED = 8; - - -/* STATES ====================================================================*/ -/* ===========================================================================*/ - - -var HEAD = 1; /* i: waiting for magic header */ -var FLAGS = 2; /* i: waiting for method and flags (gzip) */ -var TIME = 3; /* i: waiting for modification time (gzip) */ -var OS = 4; /* i: waiting for extra flags and operating system (gzip) */ -var EXLEN = 5; /* i: waiting for extra length (gzip) */ -var EXTRA = 6; /* i: waiting for extra bytes (gzip) */ -var NAME = 7; /* i: waiting for end of file name (gzip) */ -var COMMENT = 8; /* i: waiting for end of comment (gzip) */ -var HCRC = 9; /* i: waiting for header crc (gzip) */ -var DICTID = 10; /* i: waiting for dictionary check value */ -var DICT = 11; /* waiting for inflateSetDictionary() call */ -var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ -var TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ -var STORED = 14; /* i: waiting for stored size (length and complement) */ -var COPY_ = 15; /* i/o: same as COPY below, but only first time in */ -var COPY = 16; /* i/o: waiting for input or output to copy stored block */ -var TABLE = 17; /* i: waiting for dynamic block table lengths */ -var LENLENS = 18; /* i: waiting for code length code lengths */ -var CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ -var LEN_ = 20; /* i: same as LEN below, but only first time in */ -var LEN = 21; /* i: waiting for length/lit/eob code */ -var LENEXT = 22; /* i: waiting for length extra bits */ -var DIST = 23; /* i: waiting for distance code */ -var DISTEXT = 24; /* i: waiting for distance extra bits */ -var MATCH = 25; /* o: waiting for output space to copy string */ -var LIT = 26; /* o: waiting for output space to write literal */ -var CHECK = 27; /* i: waiting for 32-bit check value */ -var LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ -var DONE = 29; /* finished check, done -- remain here until reset */ -var BAD = 30; /* got a data error -- remain here until reset */ -var MEM = 31; /* got an inflate() memory error -- remain here until reset */ -var SYNC = 32; /* looking for synchronization bytes to restart inflate() */ - -/* ===========================================================================*/ - - - -var ENOUGH_LENS = 852; -var ENOUGH_DISTS = 592; -//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - -var MAX_WBITS = 15; -/* 32K LZ77 window */ -var DEF_WBITS = MAX_WBITS; - - -function zswap32(q) { - return (((q >>> 24) & 0xff) + - ((q >>> 8) & 0xff00) + - ((q & 0xff00) << 8) + - ((q & 0xff) << 24)); -} - - -function InflateState() { - this.mode = 0; /* current inflate mode */ - this.last = false; /* true if processing last block */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.havedict = false; /* true if dictionary provided */ - this.flags = 0; /* gzip header method and flags (0 if zlib) */ - this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ - this.check = 0; /* protected copy of check value */ - this.total = 0; /* protected copy of output count */ - // TODO: may be {} - this.head = null; /* where to save gzip header information */ - - /* sliding window */ - this.wbits = 0; /* log base 2 of requested window size */ - this.wsize = 0; /* window size or zero if not using window */ - this.whave = 0; /* valid bytes in the window */ - this.wnext = 0; /* window write index */ - this.window = null; /* allocated sliding window, if needed */ - - /* bit accumulator */ - this.hold = 0; /* input bit accumulator */ - this.bits = 0; /* number of bits in "in" */ - - /* for string and stored block copying */ - this.length = 0; /* literal or length of data to copy */ - this.offset = 0; /* distance back to copy string from */ - - /* for table and code decoding */ - this.extra = 0; /* extra bits needed */ - - /* fixed and dynamic code tables */ - this.lencode = null; /* starting table for length/literal codes */ - this.distcode = null; /* starting table for distance codes */ - this.lenbits = 0; /* index bits for lencode */ - this.distbits = 0; /* index bits for distcode */ - - /* dynamic table building */ - this.ncode = 0; /* number of code length code lengths */ - this.nlen = 0; /* number of length code lengths */ - this.ndist = 0; /* number of distance code lengths */ - this.have = 0; /* number of code lengths in lens[] */ - this.next = null; /* next available space in codes[] */ - - this.lens = new utils.Buf16(320); /* temporary storage for code lengths */ - this.work = new utils.Buf16(288); /* work area for code table building */ - - /* - because we don't have pointers in js, we use lencode and distcode directly - as buffers so we don't need codes - */ - //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ - this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ - this.distdyn = null; /* dynamic table for distance codes (JS specific) */ - this.sane = 0; /* if false, allow invalid distance too far */ - this.back = 0; /* bits back of last unprocessed length/lit */ - this.was = 0; /* initial length of match */ -} - -function inflateResetKeep(strm) { - var state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - strm.total_in = strm.total_out = state.total = 0; - strm.msg = ''; /*Z_NULL*/ - if (state.wrap) { /* to support ill-conceived Java test suite */ - strm.adler = state.wrap & 1; - } - state.mode = HEAD; - state.last = 0; - state.havedict = 0; - state.dmax = 32768; - state.head = null/*Z_NULL*/; - state.hold = 0; - state.bits = 0; - //state.lencode = state.distcode = state.next = state.codes; - state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS); - state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS); - - state.sane = 1; - state.back = -1; - //Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -function inflateReset(strm) { - var state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - state.wsize = 0; - state.whave = 0; - state.wnext = 0; - return inflateResetKeep(strm); - -} - -function inflateReset2(strm, windowBits) { - var wrap; - var state; - - /* get the state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 1; - if (windowBits < 48) { - windowBits &= 15; - } - } - - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) { - return Z_STREAM_ERROR; - } - if (state.window !== null && state.wbits !== windowBits) { - state.window = null; - } - - /* update state and reset the rest of it */ - state.wrap = wrap; - state.wbits = windowBits; - return inflateReset(strm); -} - -function inflateInit2(strm, windowBits) { - var ret; - var state; - - if (!strm) { return Z_STREAM_ERROR; } - //strm.msg = Z_NULL; /* in case we return an error */ - - state = new InflateState(); - - //if (state === Z_NULL) return Z_MEM_ERROR; - //Tracev((stderr, "inflate: allocated\n")); - strm.state = state; - state.window = null/*Z_NULL*/; - ret = inflateReset2(strm, windowBits); - if (ret !== Z_OK) { - strm.state = null/*Z_NULL*/; - } - return ret; -} - -function inflateInit(strm) { - return inflateInit2(strm, DEF_WBITS); -} - - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -var virgin = true; - -var lenfix, distfix; // We have no pointers in JS, so keep tables separate - -function fixedtables(state) { - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - var sym; - - lenfix = new utils.Buf32(512); - distfix = new utils.Buf32(32); - - /* literal/length table */ - sym = 0; - while (sym < 144) { state.lens[sym++] = 8; } - while (sym < 256) { state.lens[sym++] = 9; } - while (sym < 280) { state.lens[sym++] = 7; } - while (sym < 288) { state.lens[sym++] = 8; } - - inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); - - /* distance table */ - sym = 0; - while (sym < 32) { state.lens[sym++] = 5; } - - inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); - - /* do this just once */ - virgin = false; - } - - state.lencode = lenfix; - state.lenbits = 9; - state.distcode = distfix; - state.distbits = 5; -} - - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -function updatewindow(strm, src, end, copy) { - var dist; - var state = strm.state; - - /* if it hasn't been done already, allocate space for the window */ - if (state.window === null) { - state.wsize = 1 << state.wbits; - state.wnext = 0; - state.whave = 0; - - state.window = new utils.Buf8(state.wsize); - } - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state.wsize) { - utils.arraySet(state.window, src, end - state.wsize, state.wsize, 0); - state.wnext = 0; - state.whave = state.wsize; - } - else { - dist = state.wsize - state.wnext; - if (dist > copy) { - dist = copy; - } - //zmemcpy(state->window + state->wnext, end - copy, dist); - utils.arraySet(state.window, src, end - copy, dist, state.wnext); - copy -= dist; - if (copy) { - //zmemcpy(state->window, end - copy, copy); - utils.arraySet(state.window, src, end - copy, copy, 0); - state.wnext = copy; - state.whave = state.wsize; - } - else { - state.wnext += dist; - if (state.wnext === state.wsize) { state.wnext = 0; } - if (state.whave < state.wsize) { state.whave += dist; } - } - } - return 0; -} - -function inflate(strm, flush) { - var state; - var input, output; // input/output buffers - var next; /* next input INDEX */ - var put; /* next output INDEX */ - var have, left; /* available input and output */ - var hold; /* bit buffer */ - var bits; /* bits in bit buffer */ - var _in, _out; /* save starting available input and output */ - var copy; /* number of stored or match bytes to copy */ - var from; /* where to copy match bytes from */ - var from_source; - var here = 0; /* current decoding table entry */ - var here_bits, here_op, here_val; // paked "here" denormalized (JS specific) - //var last; /* parent table entry */ - var last_bits, last_op, last_val; // paked "last" denormalized (JS specific) - var len; /* length to copy for repeats, bits to drop */ - var ret; /* return code */ - var hbuf = new utils.Buf8(4); /* buffer for gzip header crc calculation */ - var opts; - - var n; // temporary var for NEED_BITS - - var order = /* permutation of code lengths */ - [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; - - - if (!strm || !strm.state || !strm.output || - (!strm.input && strm.avail_in !== 0)) { - return Z_STREAM_ERROR; - } - - state = strm.state; - if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */ - - - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - _in = have; - _out = left; - ret = Z_OK; - - inf_leave: // goto emulation - for (;;) { - switch (state.mode) { - case HEAD: - if (state.wrap === 0) { - state.mode = TYPEDO; - break; - } - //=== NEEDBITS(16); - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ - state.check = 0/*crc32(0L, Z_NULL, 0)*/; - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = FLAGS; - break; - } - state.flags = 0; /* expect zlib header */ - if (state.head) { - state.head.done = false; - } - if (!(state.wrap & 1) || /* check if zlib header allowed */ - (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { - strm.msg = 'incorrect header check'; - state.mode = BAD; - break; - } - if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD; - break; - } - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// - len = (hold & 0x0f)/*BITS(4)*/ + 8; - if (state.wbits === 0) { - state.wbits = len; - } - else if (len > state.wbits) { - strm.msg = 'invalid window size'; - state.mode = BAD; - break; - } - state.dmax = 1 << len; - //Tracev((stderr, "inflate: zlib header ok\n")); - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = hold & 0x200 ? DICTID : TYPE; - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - break; - case FLAGS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.flags = hold; - if ((state.flags & 0xff) !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD; - break; - } - if (state.flags & 0xe000) { - strm.msg = 'unknown header flags set'; - state.mode = BAD; - break; - } - if (state.head) { - state.head.text = ((hold >> 8) & 1); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = TIME; - /* falls through */ - case TIME: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.time = hold; - } - if (state.flags & 0x0200) { - //=== CRC4(state.check, hold) - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - hbuf[2] = (hold >>> 16) & 0xff; - hbuf[3] = (hold >>> 24) & 0xff; - state.check = crc32(state.check, hbuf, 4, 0); - //=== - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = OS; - /* falls through */ - case OS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.xflags = (hold & 0xff); - state.head.os = (hold >> 8); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = EXLEN; - /* falls through */ - case EXLEN: - if (state.flags & 0x0400) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length = hold; - if (state.head) { - state.head.extra_len = hold; - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - else if (state.head) { - state.head.extra = null/*Z_NULL*/; - } - state.mode = EXTRA; - /* falls through */ - case EXTRA: - if (state.flags & 0x0400) { - copy = state.length; - if (copy > have) { copy = have; } - if (copy) { - if (state.head) { - len = state.head.extra_len - state.length; - if (!state.head.extra) { - // Use untyped array for more conveniend processing later - state.head.extra = new Array(state.head.extra_len); - } - utils.arraySet( - state.head.extra, - input, - next, - // extra field is limited to 65536 bytes - // - no need for additional size check - copy, - /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ - len - ); - //zmemcpy(state.head.extra + len, next, - // len + copy > state.head.extra_max ? - // state.head.extra_max - len : copy); - } - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - state.length -= copy; - } - if (state.length) { break inf_leave; } - } - state.length = 0; - state.mode = NAME; - /* falls through */ - case NAME: - if (state.flags & 0x0800) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - // TODO: 2 or 1 bytes? - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.name_max*/)) { - state.head.name += String.fromCharCode(len); - } - } while (len && copy < have); - - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.name = null; - } - state.length = 0; - state.mode = COMMENT; - /* falls through */ - case COMMENT: - if (state.flags & 0x1000) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.comm_max*/)) { - state.head.comment += String.fromCharCode(len); - } - } while (len && copy < have); - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.comment = null; - } - state.mode = HCRC; - /* falls through */ - case HCRC: - if (state.flags & 0x0200) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.check & 0xffff)) { - strm.msg = 'header crc mismatch'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - if (state.head) { - state.head.hcrc = ((state.flags >> 9) & 1); - state.head.done = true; - } - strm.adler = state.check = 0; - state.mode = TYPE; - break; - case DICTID: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - strm.adler = state.check = zswap32(hold); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = DICT; - /* falls through */ - case DICT: - if (state.havedict === 0) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - return Z_NEED_DICT; - } - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = TYPE; - /* falls through */ - case TYPE: - if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } - /* falls through */ - case TYPEDO: - if (state.last) { - //--- BYTEBITS() ---// - hold >>>= bits & 7; - bits -= bits & 7; - //---// - state.mode = CHECK; - break; - } - //=== NEEDBITS(3); */ - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.last = (hold & 0x01)/*BITS(1)*/; - //--- DROPBITS(1) ---// - hold >>>= 1; - bits -= 1; - //---// - - switch ((hold & 0x03)/*BITS(2)*/) { - case 0: /* stored block */ - //Tracev((stderr, "inflate: stored block%s\n", - // state.last ? " (last)" : "")); - state.mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - //Tracev((stderr, "inflate: fixed codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = LEN_; /* decode codes */ - if (flush === Z_TREES) { - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break inf_leave; - } - break; - case 2: /* dynamic block */ - //Tracev((stderr, "inflate: dynamic codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = TABLE; - break; - case 3: - strm.msg = 'invalid block type'; - state.mode = BAD; - } - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break; - case STORED: - //--- BYTEBITS() ---// /* go to byte boundary */ - hold >>>= bits & 7; - bits -= bits & 7; - //---// - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { - strm.msg = 'invalid stored block lengths'; - state.mode = BAD; - break; - } - state.length = hold & 0xffff; - //Tracev((stderr, "inflate: stored length %u\n", - // state.length)); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = COPY_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case COPY_: - state.mode = COPY; - /* falls through */ - case COPY: - copy = state.length; - if (copy) { - if (copy > have) { copy = have; } - if (copy > left) { copy = left; } - if (copy === 0) { break inf_leave; } - //--- zmemcpy(put, next, copy); --- - utils.arraySet(output, input, next, copy, put); - //---// - have -= copy; - next += copy; - left -= copy; - put += copy; - state.length -= copy; - break; - } - //Tracev((stderr, "inflate: stored end\n")); - state.mode = TYPE; - break; - case TABLE: - //=== NEEDBITS(14); */ - while (bits < 14) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// -//#ifndef PKZIP_BUG_WORKAROUND - if (state.nlen > 286 || state.ndist > 30) { - strm.msg = 'too many length or distance symbols'; - state.mode = BAD; - break; - } -//#endif - //Tracev((stderr, "inflate: table sizes ok\n")); - state.have = 0; - state.mode = LENLENS; - /* falls through */ - case LENLENS: - while (state.have < state.ncode) { - //=== NEEDBITS(3); - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - while (state.have < 19) { - state.lens[order[state.have++]] = 0; - } - // We have separate tables & no pointers. 2 commented lines below not needed. - //state.next = state.codes; - //state.lencode = state.next; - // Switch to use dynamic table - state.lencode = state.lendyn; - state.lenbits = 7; - - opts = { bits: state.lenbits }; - ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); - state.lenbits = opts.bits; - - if (ret) { - strm.msg = 'invalid code lengths set'; - state.mode = BAD; - break; - } - //Tracev((stderr, "inflate: code lengths ok\n")); - state.have = 0; - state.mode = CODELENS; - /* falls through */ - case CODELENS: - while (state.have < state.nlen + state.ndist) { - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_val < 16) { - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.lens[state.have++] = here_val; - } - else { - if (here_val === 16) { - //=== NEEDBITS(here.bits + 2); - n = here_bits + 2; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - if (state.have === 0) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD; - break; - } - len = state.lens[state.have - 1]; - copy = 3 + (hold & 0x03);//BITS(2); - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - } - else if (here_val === 17) { - //=== NEEDBITS(here.bits + 3); - n = here_bits + 3; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 3 + (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - else { - //=== NEEDBITS(here.bits + 7); - n = here_bits + 7; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 11 + (hold & 0x7f);//BITS(7); - //--- DROPBITS(7) ---// - hold >>>= 7; - bits -= 7; - //---// - } - if (state.have + copy > state.nlen + state.ndist) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD; - break; - } - while (copy--) { - state.lens[state.have++] = len; - } - } - } - - /* handle error breaks in while */ - if (state.mode === BAD) { break; } - - /* check for end-of-block code (better have one) */ - if (state.lens[256] === 0) { - strm.msg = 'invalid code -- missing end-of-block'; - state.mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state.lenbits = 9; - - opts = { bits: state.lenbits }; - ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.lenbits = opts.bits; - // state.lencode = state.next; - - if (ret) { - strm.msg = 'invalid literal/lengths set'; - state.mode = BAD; - break; - } - - state.distbits = 6; - //state.distcode.copy(state.codes); - // Switch to use dynamic table - state.distcode = state.distdyn; - opts = { bits: state.distbits }; - ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.distbits = opts.bits; - // state.distcode = state.next; - - if (ret) { - strm.msg = 'invalid distances set'; - state.mode = BAD; - break; - } - //Tracev((stderr, 'inflate: codes ok\n')); - state.mode = LEN_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case LEN_: - state.mode = LEN; - /* falls through */ - case LEN: - if (have >= 6 && left >= 258) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - inflate_fast(strm, _out); - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - if (state.mode === TYPE) { - state.back = -1; - } - break; - } - state.back = 0; - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if (here_bits <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_op && (here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.lencode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - state.length = here_val; - if (here_op === 0) { - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - state.mode = LIT; - break; - } - if (here_op & 32) { - //Tracevv((stderr, "inflate: end of block\n")); - state.back = -1; - state.mode = TYPE; - break; - } - if (here_op & 64) { - strm.msg = 'invalid literal/length code'; - state.mode = BAD; - break; - } - state.extra = here_op & 15; - state.mode = LENEXT; - /* falls through */ - case LENEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } - //Tracevv((stderr, "inflate: length %u\n", state.length)); - state.was = state.length; - state.mode = DIST; - /* falls through */ - case DIST: - for (;;) { - here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if ((here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.distcode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - if (here_op & 64) { - strm.msg = 'invalid distance code'; - state.mode = BAD; - break; - } - state.offset = here_val; - state.extra = (here_op) & 15; - state.mode = DISTEXT; - /* falls through */ - case DISTEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } -//#ifdef INFLATE_STRICT - if (state.offset > state.dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break; - } -//#endif - //Tracevv((stderr, "inflate: distance %u\n", state.offset)); - state.mode = MATCH; - /* falls through */ - case MATCH: - if (left === 0) { break inf_leave; } - copy = _out - left; - if (state.offset > copy) { /* copy from window */ - copy = state.offset - copy; - if (copy > state.whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break; - } -// (!) This block is disabled in zlib defailts, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// Trace((stderr, "inflate.c too far\n")); -// copy -= state.whave; -// if (copy > state.length) { copy = state.length; } -// if (copy > left) { copy = left; } -// left -= copy; -// state.length -= copy; -// do { -// output[put++] = 0; -// } while (--copy); -// if (state.length === 0) { state.mode = LEN; } -// break; -//#endif - } - if (copy > state.wnext) { - copy -= state.wnext; - from = state.wsize - copy; - } - else { - from = state.wnext - copy; - } - if (copy > state.length) { copy = state.length; } - from_source = state.window; - } - else { /* copy from output */ - from_source = output; - from = put - state.offset; - copy = state.length; - } - if (copy > left) { copy = left; } - left -= copy; - state.length -= copy; - do { - output[put++] = from_source[from++]; - } while (--copy); - if (state.length === 0) { state.mode = LEN; } - break; - case LIT: - if (left === 0) { break inf_leave; } - output[put++] = state.length; - left--; - state.mode = LEN; - break; - case CHECK: - if (state.wrap) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - // Use '|' insdead of '+' to make sure that result is signed - hold |= input[next++] << bits; - bits += 8; - } - //===// - _out -= left; - strm.total_out += _out; - state.total += _out; - if (_out) { - strm.adler = state.check = - /*UPDATE(state.check, put - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); - - } - _out = left; - // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too - if ((state.flags ? hold : zswap32(hold)) !== state.check) { - strm.msg = 'incorrect data check'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: check matches trailer\n")); - } - state.mode = LENGTH; - /* falls through */ - case LENGTH: - if (state.wrap && state.flags) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.total & 0xffffffff)) { - strm.msg = 'incorrect length check'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: length matches trailer\n")); - } - state.mode = DONE; - /* falls through */ - case DONE: - ret = Z_STREAM_END; - break inf_leave; - case BAD: - ret = Z_DATA_ERROR; - break inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - /* falls through */ - default: - return Z_STREAM_ERROR; - } - } - - // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - - if (state.wsize || (_out !== strm.avail_out && state.mode < BAD && - (state.mode < CHECK || flush !== Z_FINISH))) { - if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) { - state.mode = MEM; - return Z_MEM_ERROR; - } - } - _in -= strm.avail_in; - _out -= strm.avail_out; - strm.total_in += _in; - strm.total_out += _out; - state.total += _out; - if (state.wrap && _out) { - strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); - } - strm.data_type = state.bits + (state.last ? 64 : 0) + - (state.mode === TYPE ? 128 : 0) + - (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); - if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { - ret = Z_BUF_ERROR; - } - return ret; -} - -function inflateEnd(strm) { - - if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { - return Z_STREAM_ERROR; - } - - var state = strm.state; - if (state.window) { - state.window = null; - } - strm.state = null; - return Z_OK; -} - -function inflateGetHeader(strm, head) { - var state; - - /* check state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } - - /* save header structure */ - state.head = head; - head.done = false; - return Z_OK; -} - -function inflateSetDictionary(strm, dictionary) { - var dictLength = dictionary.length; - - var state; - var dictid; - var ret; - - /* check state */ - if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } - state = strm.state; - - if (state.wrap !== 0 && state.mode !== DICT) { - return Z_STREAM_ERROR; - } - - /* check for correct dictionary identifier */ - if (state.mode === DICT) { - dictid = 1; /* adler32(0, null, 0)*/ - /* dictid = adler32(dictid, dictionary, dictLength); */ - dictid = adler32(dictid, dictionary, dictLength, 0); - if (dictid !== state.check) { - return Z_DATA_ERROR; - } - } - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - ret = updatewindow(strm, dictionary, dictLength, dictLength); - if (ret) { - state.mode = MEM; - return Z_MEM_ERROR; - } - state.havedict = 1; - // Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} - -exports.inflateReset = inflateReset; -exports.inflateReset2 = inflateReset2; -exports.inflateResetKeep = inflateResetKeep; -exports.inflateInit = inflateInit; -exports.inflateInit2 = inflateInit2; -exports.inflate = inflate; -exports.inflateEnd = inflateEnd; -exports.inflateGetHeader = inflateGetHeader; -exports.inflateSetDictionary = inflateSetDictionary; -exports.inflateInfo = 'pako inflate (from Nodeca project)'; - -/* Not implemented -exports.inflateCopy = inflateCopy; -exports.inflateGetDictionary = inflateGetDictionary; -exports.inflateMark = inflateMark; -exports.inflatePrime = inflatePrime; -exports.inflateSync = inflateSync; -exports.inflateSyncPoint = inflateSyncPoint; -exports.inflateUndermine = inflateUndermine; -*/ - -},{"../utils/common":2,"./adler32":3,"./crc32":4,"./inffast":5,"./inftrees":7}],7:[function(require,module,exports){ -'use strict'; - - -var utils = require('../utils/common'); - -var MAXBITS = 15; -var ENOUGH_LENS = 852; -var ENOUGH_DISTS = 592; -//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - -var CODES = 0; -var LENS = 1; -var DISTS = 2; - -var lbase = [ /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 -]; - -var lext = [ /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 -]; - -var dbase = [ /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0 -]; - -var dext = [ /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64 -]; - -module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) -{ - var bits = opts.bits; - //here = opts.here; /* table entry for duplication */ - - var len = 0; /* a code's length in bits */ - var sym = 0; /* index of code symbols */ - var min = 0, max = 0; /* minimum and maximum code lengths */ - var root = 0; /* number of index bits for root table */ - var curr = 0; /* number of index bits for current table */ - var drop = 0; /* code bits to drop for sub-table */ - var left = 0; /* number of prefix codes available */ - var used = 0; /* code entries in table used */ - var huff = 0; /* Huffman code */ - var incr; /* for incrementing code, index */ - var fill; /* index for replicating entries */ - var low; /* low bits for current root entry */ - var mask; /* mask for low root bits */ - var next; /* next available space in table */ - var base = null; /* base value table to use */ - var base_index = 0; -// var shoextra; /* extra bits table to use */ - var end; /* use base and extra for symbol > end */ - var count = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ - var offs = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ - var extra = null; - var extra_index = 0; - - var here_bits, here_op, here_val; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) { - count[len] = 0; - } - for (sym = 0; sym < codes; sym++) { - count[lens[lens_index + sym]]++; - } - - /* bound code lengths, force root to be within code lengths */ - root = bits; - for (max = MAXBITS; max >= 1; max--) { - if (count[max] !== 0) { break; } - } - if (root > max) { - root = max; - } - if (max === 0) { /* no symbols to code at all */ - //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ - //table.bits[opts.table_index] = 1; //here.bits = (var char)1; - //table.val[opts.table_index++] = 0; //here.val = (var short)0; - table[table_index++] = (1 << 24) | (64 << 16) | 0; - - - //table.op[opts.table_index] = 64; - //table.bits[opts.table_index] = 1; - //table.val[opts.table_index++] = 0; - table[table_index++] = (1 << 24) | (64 << 16) | 0; - - opts.bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) { - if (count[min] !== 0) { break; } - } - if (root < min) { - root = min; - } - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) { - return -1; - } /* over-subscribed */ - } - if (left > 0 && (type === CODES || max !== 1)) { - return -1; /* incomplete set */ - } - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) { - offs[len + 1] = offs[len] + count[len]; - } - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) { - if (lens[lens_index + sym] !== 0) { - work[offs[lens[lens_index + sym]]++] = sym; - } - } - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - // poor man optimization - use if-else instead of switch, - // to avoid deopts in old v8 - if (type === CODES) { - base = extra = work; /* dummy value--not used */ - end = 19; - - } else if (type === LENS) { - base = lbase; - base_index -= 257; - extra = lext; - extra_index -= 257; - end = 256; - - } else { /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize opts for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = table_index; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = -1; /* trigger new sub-table when len > root */ - used = 1 << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if ((type === LENS && used > ENOUGH_LENS) || - (type === DISTS && used > ENOUGH_DISTS)) { - return 1; - } - - var i = 0; - /* process all codes and make table entries */ - for (;;) { - i++; - /* create table entry */ - here_bits = len - drop; - if (work[sym] < end) { - here_op = 0; - here_val = work[sym]; - } - else if (work[sym] > end) { - here_op = extra[extra_index + work[sym]]; - here_val = base[base_index + work[sym]]; - } - else { - here_op = 32 + 64; /* end of block */ - here_val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1 << (len - drop); - fill = 1 << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; - } while (fill !== 0); - - /* backwards increment the len-bit code huff */ - incr = 1 << (len - 1); - while (huff & incr) { - incr >>= 1; - } - if (incr !== 0) { - huff &= incr - 1; - huff += incr; - } else { - huff = 0; - } - - /* go to next symbol, update count, len */ - sym++; - if (--count[len] === 0) { - if (len === max) { break; } - len = lens[lens_index + work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) !== low) { - /* if first time, transition to sub-tables */ - if (drop === 0) { - drop = root; - } - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = 1 << curr; - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) { break; } - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1 << curr; - if ((type === LENS && used > ENOUGH_LENS) || - (type === DISTS && used > ENOUGH_DISTS)) { - return 1; - } - - /* point entry in root table to sub-table */ - low = huff & mask; - /*table.op[low] = curr; - table.bits[low] = root; - table.val[low] = next - opts.table_index;*/ - table[low] = (root << 24) | (curr << 16) | (next - table_index) |0; - } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff !== 0) { - //table.op[next + huff] = 64; /* invalid code marker */ - //table.bits[next + huff] = len - drop; - //table.val[next + huff] = 0; - table[next + huff] = ((len - drop) << 24) | (64 << 16) |0; - } - - /* set return parameters */ - //opts.table_index += used; - opts.bits = root; - return 0; -}; - -},{"../utils/common":2}],8:[function(require,module,exports){ -'use strict'; - - -function ZStream() { - /* next input byte */ - this.input = null; // JS specific, because we have no pointers - this.next_in = 0; - /* number of bytes available at input */ - this.avail_in = 0; - /* total number of input bytes read so far */ - this.total_in = 0; - /* next output byte should be put there */ - this.output = null; // JS specific, because we have no pointers - this.next_out = 0; - /* remaining free space at output */ - this.avail_out = 0; - /* total number of bytes output so far */ - this.total_out = 0; - /* last error message, NULL if no error */ - this.msg = ''/*Z_NULL*/; - /* not visible by applications */ - this.state = null; - /* best guess about the data type: binary or text */ - this.data_type = 2/*Z_UNKNOWN*/; - /* adler32 value of the uncompressed data */ - this.adler = 0; -} - -module.exports = ZStream; - -},{}]},{},[1])(1) -}); \ No newline at end of file diff --git a/core/inflator.mod.js b/core/inflator.mod.js deleted file mode 100644 index 26e6441b..00000000 --- a/core/inflator.mod.js +++ /dev/null @@ -1,40 +0,0 @@ -var zlib = require('pako/lib/zlib/inflate.js'); -var ZStream = require('pako/lib/zlib/zstream.js'); - -function Inflate() { - this.strm = new ZStream(); - this.chunkSize = 1024 * 10 * 10; - this.strm.output = new Uint8Array(this.chunkSize); - this.windowBits = 5; - - zlib.inflateInit(this.strm, this.windowBits); -}; - -Inflate.prototype = { - inflate: function (data, flush, expected) { - this.strm.input = data; - this.strm.avail_in = this.strm.input.length; - this.strm.next_in = 0; - this.strm.next_out = 0; - - // resize our output buffer if it's too small - // (we could just use multiple chunks, but that would cause an extra - // allocation each time to flatten the chunks) - if (expected > this.chunkSize) { - this.chunkSize = expected; - this.strm.output = new Uint8Array(this.chunkSize); - } - - this.strm.avail_out = this.chunkSize; - - zlib.inflate(this.strm, flush); - - return new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out); - }, - - reset: function () { - zlib.inflateReset(this.strm); - } -}; - -module.exports = { Inflate: Inflate }; diff --git a/core/input/devices.js b/core/input/devices.js index 2e41122e..22653e38 100644 --- a/core/input/devices.js +++ b/core/input/devices.js @@ -8,396 +8,387 @@ /*jslint browser: true, white: false */ /*global window, Util */ -/* [module] - * import Util from "../util"; - * import KeyboardUtil from "./util"; - */ +import * as Log from '../util/logging.js'; +import { isTouchDevice } from '../util/browsers.js' +import { setCapture, releaseCapture, stopEvent, getPointerEvent } from '../util/events.js'; +import { set_defaults, make_properties } from '../util/properties.js'; +import * as KeyboardUtil from "./util.js"; -/* [module] export */ var Keyboard; +// +// Keyboard event handler +// -(function () { - "use strict"; +const Keyboard = function (defaults) { + this._keyDownList = []; // List of depressed keys + // (even if they are happy) - // - // Keyboard event handler - // + set_defaults(this, defaults, { + 'target': document, + 'focused': true + }); - Keyboard = function (defaults) { - this._keyDownList = []; // List of depressed keys - // (even if they are happy) - - Util.set_defaults(this, defaults, { - 'target': document, - 'focused': true - }); - - // create the keyboard handler - this._handler = new KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), - KeyboardUtil.VerifyCharModifier( /* jshint newcap: false */ - KeyboardUtil.TrackKeyState( - KeyboardUtil.EscapeModifiers(this._handleRfbEvent.bind(this)) - ) + // create the keyboard handler + this._handler = new KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), + KeyboardUtil.VerifyCharModifier( /* jshint newcap: false */ + KeyboardUtil.TrackKeyState( + KeyboardUtil.EscapeModifiers(this._handleRfbEvent.bind(this)) ) - ); /* jshint newcap: true */ + ) + ); /* jshint newcap: true */ - // keep these here so we can refer to them later - this._eventHandlers = { - 'keyup': this._handleKeyUp.bind(this), - 'keydown': this._handleKeyDown.bind(this), - 'keypress': this._handleKeyPress.bind(this), - 'blur': this._allKeysUp.bind(this) - }; + // keep these here so we can refer to them later + this._eventHandlers = { + 'keyup': this._handleKeyUp.bind(this), + 'keydown': this._handleKeyDown.bind(this), + 'keypress': this._handleKeyPress.bind(this), + 'blur': this._allKeysUp.bind(this) }; +}; - Keyboard.prototype = { - // private methods +Keyboard.prototype = { + // private methods - _handleRfbEvent: function (e) { - if (this._onKeyPress) { - Util.Debug("onKeyPress " + (e.type == 'keydown' ? "down" : "up") + - ", keysym: " + e.keysym.keysym + "(" + e.keysym.keyname + ")"); - this._onKeyPress(e); - } - }, - - setQEMUVNCKeyboardHandler: function () { - this._handler = new KeyboardUtil.QEMUKeyEventDecoder(KeyboardUtil.ModifierSync(), - KeyboardUtil.TrackQEMUKeyState( - this._handleRfbEvent.bind(this) - ) - ); - }, - - _handleKeyDown: function (e) { - if (!this._focused) { return; } - - if (this._handler.keydown(e)) { - // Suppress bubbling/default actions - Util.stopEvent(e); - } else { - // Allow the event to bubble and become a keyPress event which - // will have the character code translated - } - }, - - _handleKeyPress: function (e) { - if (!this._focused) { return; } - - if (this._handler.keypress(e)) { - // Suppress bubbling/default actions - Util.stopEvent(e); - } - }, - - _handleKeyUp: function (e) { - if (!this._focused) { return; } - - if (this._handler.keyup(e)) { - // Suppress bubbling/default actions - Util.stopEvent(e); - } - }, - - _allKeysUp: function () { - Util.Debug(">> Keyboard.allKeysUp"); - this._handler.releaseAll(); - Util.Debug("<< Keyboard.allKeysUp"); - }, - - // Public methods - - grab: function () { - //Util.Debug(">> Keyboard.grab"); - var c = this._target; - - c.addEventListener('keydown', this._eventHandlers.keydown); - c.addEventListener('keyup', this._eventHandlers.keyup); - c.addEventListener('keypress', this._eventHandlers.keypress); - - // Release (key up) if window loses focus - window.addEventListener('blur', this._eventHandlers.blur); - - //Util.Debug("<< Keyboard.grab"); - }, - - ungrab: function () { - //Util.Debug(">> Keyboard.ungrab"); - var c = this._target; - - c.removeEventListener('keydown', this._eventHandlers.keydown); - c.removeEventListener('keyup', this._eventHandlers.keyup); - c.removeEventListener('keypress', this._eventHandlers.keypress); - window.removeEventListener('blur', this._eventHandlers.blur); - - // Release (key up) all keys that are in a down state - this._allKeysUp(); - - //Util.Debug(">> Keyboard.ungrab"); - }, - - sync: function (e) { - this._handler.syncModifiers(e); + _handleRfbEvent: function (e) { + if (this._onKeyPress) { + Log.Debug("onKeyPress " + (e.type == 'keydown' ? "down" : "up") + + ", keysym: " + e.keysym.keysym + "(" + e.keysym.keyname + ")"); + this._onKeyPress(e); } + }, + + setQEMUVNCKeyboardHandler: function () { + this._handler = new KeyboardUtil.QEMUKeyEventDecoder(KeyboardUtil.ModifierSync(), + KeyboardUtil.TrackQEMUKeyState( + this._handleRfbEvent.bind(this) + ) + ); + }, + + _handleKeyDown: function (e) { + if (!this._focused) { return; } + + if (this._handler.keydown(e)) { + // Suppress bubbling/default actions + stopEvent(e); + } else { + // Allow the event to bubble and become a keyPress event which + // will have the character code translated + } + }, + + _handleKeyPress: function (e) { + if (!this._focused) { return; } + + if (this._handler.keypress(e)) { + // Suppress bubbling/default actions + stopEvent(e); + } + }, + + _handleKeyUp: function (e) { + if (!this._focused) { return; } + + if (this._handler.keyup(e)) { + // Suppress bubbling/default actions + stopEvent(e); + } + }, + + _allKeysUp: function () { + Log.Debug(">> Keyboard.allKeysUp"); + this._handler.releaseAll(); + Log.Debug("<< Keyboard.allKeysUp"); + }, + + // Public methods + + grab: function () { + //Log.Debug(">> Keyboard.grab"); + var c = this._target; + + c.addEventListener('keydown', this._eventHandlers.keydown); + c.addEventListener('keyup', this._eventHandlers.keyup); + c.addEventListener('keypress', this._eventHandlers.keypress); + + // Release (key up) if window loses focus + window.addEventListener('blur', this._eventHandlers.blur); + + //Log.Debug("<< Keyboard.grab"); + }, + + ungrab: function () { + //Log.Debug(">> Keyboard.ungrab"); + var c = this._target; + + c.removeEventListener('keydown', this._eventHandlers.keydown); + c.removeEventListener('keyup', this._eventHandlers.keyup); + c.removeEventListener('keypress', this._eventHandlers.keypress); + window.removeEventListener('blur', this._eventHandlers.blur); + + // Release (key up) all keys that are in a down state + this._allKeysUp(); + + //Log.Debug(">> Keyboard.ungrab"); + }, + + sync: function (e) { + this._handler.syncModifiers(e); + } +}; + +make_properties(Keyboard, [ + ['target', 'wo', 'dom'], // DOM element that captures keyboard input + ['focused', 'rw', 'bool'], // Capture and send key events + + ['onKeyPress', 'rw', 'func'] // Handler for key press/release +]); + +const Mouse = function (defaults) { + this._mouseCaptured = false; + + this._doubleClickTimer = null; + this._lastTouchPos = null; + + // Configuration attributes + set_defaults(this, defaults, { + 'target': document, + 'focused': true, + 'touchButton': 1 + }); + + this._eventHandlers = { + 'mousedown': this._handleMouseDown.bind(this), + 'mouseup': this._handleMouseUp.bind(this), + 'mousemove': this._handleMouseMove.bind(this), + 'mousewheel': this._handleMouseWheel.bind(this), + 'mousedisable': this._handleMouseDisable.bind(this) }; +}; - Util.make_properties(Keyboard, [ - ['target', 'wo', 'dom'], // DOM element that captures keyboard input - ['focused', 'rw', 'bool'], // Capture and send key events +Mouse.prototype = { + // private methods + _captureMouse: function () { + // capturing the mouse ensures we get the mouseup event + setCapture(this._target); - ['onKeyPress', 'rw', 'func'] // Handler for key press/release - ]); -})(); + // some browsers give us mouseup events regardless, + // so if we never captured the mouse, we can disregard the event + this._mouseCaptured = true; + }, -/* [module] export */ var Mouse; - -(function () { - Mouse = function (defaults) { - this._mouseCaptured = false; + _releaseMouse: function () { + releaseCapture(); + this._mouseCaptured = false; + }, + _resetDoubleClickTimer: function () { this._doubleClickTimer = null; - this._lastTouchPos = null; + }, - // Configuration attributes - Util.set_defaults(this, defaults, { - 'target': document, - 'focused': true, - 'touchButton': 1 - }); + _handleMouseButton: function (e, down) { + if (!this._focused) { return; } - this._eventHandlers = { - 'mousedown': this._handleMouseDown.bind(this), - 'mouseup': this._handleMouseUp.bind(this), - 'mousemove': this._handleMouseMove.bind(this), - 'mousewheel': this._handleMouseWheel.bind(this), - 'mousedisable': this._handleMouseDisable.bind(this) - }; - }; - - Mouse.prototype = { - // private methods - _captureMouse: function () { - // capturing the mouse ensures we get the mouseup event - Util.setCapture(this._target); - - // some browsers give us mouseup events regardless, - // so if we never captured the mouse, we can disregard the event - this._mouseCaptured = true; - }, - - _releaseMouse: function () { - Util.releaseCapture(); - this._mouseCaptured = false; - }, - - _resetDoubleClickTimer: function () { - this._doubleClickTimer = null; - }, - - _handleMouseButton: function (e, down) { - if (!this._focused) { return; } - - if (this._notify) { - this._notify(e); - } - - var pos = this._getMousePosition(e); - - var bmask; - if (e.touches || e.changedTouches) { - // Touch device - - // When two touches occur within 500 ms of each other and are - // close enough together a double click is triggered. - if (down == 1) { - if (this._doubleClickTimer === null) { - this._lastTouchPos = pos; - } else { - clearTimeout(this._doubleClickTimer); - - // When the distance between the two touches is small enough - // force the position of the latter touch to the position of - // the first. - - var xs = this._lastTouchPos.x - pos.x; - var ys = this._lastTouchPos.y - pos.y; - var d = Math.sqrt((xs * xs) + (ys * ys)); - - // The goal is to trigger on a certain physical width, the - // devicePixelRatio brings us a bit closer but is not optimal. - var threshold = 20 * (window.devicePixelRatio || 1); - if (d < threshold) { - pos = this._lastTouchPos; - } - } - this._doubleClickTimer = setTimeout(this._resetDoubleClickTimer.bind(this), 500); - } - bmask = this._touchButton; - // If bmask is set - } else if (e.which) { - /* everything except IE */ - bmask = 1 << e.button; - } else { - /* IE including 9 */ - bmask = (e.button & 0x1) + // Left - (e.button & 0x2) * 2 + // Right - (e.button & 0x4) / 2; // Middle - } - - if (this._onMouseButton) { - Util.Debug("onMouseButton " + (down ? "down" : "up") + - ", x: " + pos.x + ", y: " + pos.y + ", bmask: " + bmask); - this._onMouseButton(pos.x, pos.y, down, bmask); - } - Util.stopEvent(e); - }, - - _handleMouseDown: function (e) { - this._captureMouse(); - this._handleMouseButton(e, 1); - }, - - _handleMouseUp: function (e) { - if (!this._mouseCaptured) { return; } - - this._handleMouseButton(e, 0); - this._releaseMouse(); - }, - - _handleMouseWheel: function (e) { - if (!this._focused) { return; } - - if (this._notify) { - this._notify(e); - } - - var pos = this._getMousePosition(e); - - if (this._onMouseButton) { - if (e.deltaX < 0) { - this._onMouseButton(pos.x, pos.y, 1, 1 << 5); - this._onMouseButton(pos.x, pos.y, 0, 1 << 5); - } else if (e.deltaX > 0) { - this._onMouseButton(pos.x, pos.y, 1, 1 << 6); - this._onMouseButton(pos.x, pos.y, 0, 1 << 6); - } - - if (e.deltaY < 0) { - this._onMouseButton(pos.x, pos.y, 1, 1 << 3); - this._onMouseButton(pos.x, pos.y, 0, 1 << 3); - } else if (e.deltaY > 0) { - this._onMouseButton(pos.x, pos.y, 1, 1 << 4); - this._onMouseButton(pos.x, pos.y, 0, 1 << 4); - } - } - - Util.stopEvent(e); - }, - - _handleMouseMove: function (e) { - if (! this._focused) { return; } - - if (this._notify) { - this._notify(e); - } - - var pos = this._getMousePosition(e); - if (this._onMouseMove) { - this._onMouseMove(pos.x, pos.y); - } - Util.stopEvent(e); - }, - - _handleMouseDisable: function (e) { - if (!this._focused) { return; } - - /* - * Stop propagation if inside canvas area - * Note: This is only needed for the 'click' event as it fails - * to fire properly for the target element so we have - * to listen on the document element instead. - */ - if (e.target == this._target) { - //Util.Debug("mouse event disabled"); - Util.stopEvent(e); - } - }, - - // Return coordinates relative to target - _getMousePosition: function(e) { - e = Util.getPointerEvent(e); - var bounds = this._target.getBoundingClientRect(); - var x, y; - // Clip to target bounds - if (e.clientX < bounds.left) { - x = 0; - } else if (e.clientX >= bounds.right) { - x = bounds.width - 1; - } else { - x = e.clientX - bounds.left; - } - if (e.clientY < bounds.top) { - y = 0; - } else if (e.clientY >= bounds.bottom) { - y = bounds.height - 1; - } else { - y = e.clientY - bounds.top; - } - return {x:x, y:y}; - }, - - - // Public methods - grab: function () { - var c = this._target; - - if (Util.isTouchDevice) { - c.addEventListener('touchstart', this._eventHandlers.mousedown); - window.addEventListener('touchend', this._eventHandlers.mouseup); - c.addEventListener('touchend', this._eventHandlers.mouseup); - c.addEventListener('touchmove', this._eventHandlers.mousemove); - } - c.addEventListener('mousedown', this._eventHandlers.mousedown); - window.addEventListener('mouseup', this._eventHandlers.mouseup); - c.addEventListener('mouseup', this._eventHandlers.mouseup); - c.addEventListener('mousemove', this._eventHandlers.mousemove); - c.addEventListener('wheel', this._eventHandlers.mousewheel); - - /* Prevent middle-click pasting (see above for why we bind to document) */ - document.addEventListener('click', this._eventHandlers.mousedisable); - - /* preventDefault() on mousedown doesn't stop this event for some - reason so we have to explicitly block it */ - c.addEventListener('contextmenu', this._eventHandlers.mousedisable); - }, - - ungrab: function () { - var c = this._target; - - if (Util.isTouchDevice) { - c.removeEventListener('touchstart', this._eventHandlers.mousedown); - window.removeEventListener('touchend', this._eventHandlers.mouseup); - c.removeEventListener('touchend', this._eventHandlers.mouseup); - c.removeEventListener('touchmove', this._eventHandlers.mousemove); - } - c.removeEventListener('mousedown', this._eventHandlers.mousedown); - window.removeEventListener('mouseup', this._eventHandlers.mouseup); - c.removeEventListener('mouseup', this._eventHandlers.mouseup); - c.removeEventListener('mousemove', this._eventHandlers.mousemove); - c.removeEventListener('wheel', this._eventHandlers.mousewheel); - - document.removeEventListener('click', this._eventHandlers.mousedisable); - - c.removeEventListener('contextmenu', this._eventHandlers.mousedisable); + if (this._notify) { + this._notify(e); } - }; - Util.make_properties(Mouse, [ - ['target', 'ro', 'dom'], // DOM element that captures mouse input - ['notify', 'ro', 'func'], // Function to call to notify whenever a mouse event is received - ['focused', 'rw', 'bool'], // Capture and send mouse clicks/movement + var pos = this._getMousePosition(e); - ['onMouseButton', 'rw', 'func'], // Handler for mouse button click/release - ['onMouseMove', 'rw', 'func'], // Handler for mouse movement - ['touchButton', 'rw', 'int'] // Button mask (1, 2, 4) for touch devices (0 means ignore clicks) - ]); -})(); + var bmask; + if (e.touches || e.changedTouches) { + // Touch device + + // When two touches occur within 500 ms of each other and are + // close enough together a double click is triggered. + if (down == 1) { + if (this._doubleClickTimer === null) { + this._lastTouchPos = pos; + } else { + clearTimeout(this._doubleClickTimer); + + // When the distance between the two touches is small enough + // force the position of the latter touch to the position of + // the first. + + var xs = this._lastTouchPos.x - pos.x; + var ys = this._lastTouchPos.y - pos.y; + var d = Math.sqrt((xs * xs) + (ys * ys)); + + // The goal is to trigger on a certain physical width, the + // devicePixelRatio brings us a bit closer but is not optimal. + var threshold = 20 * (window.devicePixelRatio || 1); + if (d < threshold) { + pos = this._lastTouchPos; + } + } + this._doubleClickTimer = setTimeout(this._resetDoubleClickTimer.bind(this), 500); + } + bmask = this._touchButton; + // If bmask is set + } else if (e.which) { + /* everything except IE */ + bmask = 1 << e.button; + } else { + /* IE including 9 */ + bmask = (e.button & 0x1) + // Left + (e.button & 0x2) * 2 + // Right + (e.button & 0x4) / 2; // Middle + } + + if (this._onMouseButton) { + Log.Debug("onMouseButton " + (down ? "down" : "up") + + ", x: " + pos.x + ", y: " + pos.y + ", bmask: " + bmask); + this._onMouseButton(pos.x, pos.y, down, bmask); + } + stopEvent(e); + }, + + _handleMouseDown: function (e) { + this._captureMouse(); + this._handleMouseButton(e, 1); + }, + + _handleMouseUp: function (e) { + if (!this._mouseCaptured) { return; } + + this._handleMouseButton(e, 0); + this._releaseMouse(); + }, + + _handleMouseWheel: function (e) { + if (!this._focused) { return; } + + if (this._notify) { + this._notify(e); + } + + var pos = this._getMousePosition(e); + + if (this._onMouseButton) { + if (e.deltaX < 0) { + this._onMouseButton(pos.x, pos.y, 1, 1 << 5); + this._onMouseButton(pos.x, pos.y, 0, 1 << 5); + } else if (e.deltaX > 0) { + this._onMouseButton(pos.x, pos.y, 1, 1 << 6); + this._onMouseButton(pos.x, pos.y, 0, 1 << 6); + } + + if (e.deltaY < 0) { + this._onMouseButton(pos.x, pos.y, 1, 1 << 3); + this._onMouseButton(pos.x, pos.y, 0, 1 << 3); + } else if (e.deltaY > 0) { + this._onMouseButton(pos.x, pos.y, 1, 1 << 4); + this._onMouseButton(pos.x, pos.y, 0, 1 << 4); + } + } + + stopEvent(e); + }, + + _handleMouseMove: function (e) { + if (! this._focused) { return; } + + if (this._notify) { + this._notify(e); + } + + var pos = this._getMousePosition(e); + if (this._onMouseMove) { + this._onMouseMove(pos.x, pos.y); + } + stopEvent(e); + }, + + _handleMouseDisable: function (e) { + if (!this._focused) { return; } + + /* + * Stop propagation if inside canvas area + * Note: This is only needed for the 'click' event as it fails + * to fire properly for the target element so we have + * to listen on the document element instead. + */ + if (e.target == this._target) { + stopEvent(e); + } + }, + + // Return coordinates relative to target + _getMousePosition: function(e) { + e = getPointerEvent(e); + var bounds = this._target.getBoundingClientRect(); + var x, y; + // Clip to target bounds + if (e.clientX < bounds.left) { + x = 0; + } else if (e.clientX >= bounds.right) { + x = bounds.width - 1; + } else { + x = e.clientX - bounds.left; + } + if (e.clientY < bounds.top) { + y = 0; + } else if (e.clientY >= bounds.bottom) { + y = bounds.height - 1; + } else { + y = e.clientY - bounds.top; + } + return {x:x, y:y}; + }, + + // Public methods + grab: function () { + var c = this._target; + + if (isTouchDevice) { + c.addEventListener('touchstart', this._eventHandlers.mousedown); + window.addEventListener('touchend', this._eventHandlers.mouseup); + c.addEventListener('touchend', this._eventHandlers.mouseup); + c.addEventListener('touchmove', this._eventHandlers.mousemove); + } + c.addEventListener('mousedown', this._eventHandlers.mousedown); + window.addEventListener('mouseup', this._eventHandlers.mouseup); + c.addEventListener('mouseup', this._eventHandlers.mouseup); + c.addEventListener('mousemove', this._eventHandlers.mousemove); + c.addEventListener('wheel', this._eventHandlers.mousewheel); + + /* Prevent middle-click pasting (see above for why we bind to document) */ + document.addEventListener('click', this._eventHandlers.mousedisable); + + /* preventDefault() on mousedown doesn't stop this event for some + reason so we have to explicitly block it */ + c.addEventListener('contextmenu', this._eventHandlers.mousedisable); + }, + + ungrab: function () { + var c = this._target; + + if (isTouchDevice) { + c.removeEventListener('touchstart', this._eventHandlers.mousedown); + window.removeEventListener('touchend', this._eventHandlers.mouseup); + c.removeEventListener('touchend', this._eventHandlers.mouseup); + c.removeEventListener('touchmove', this._eventHandlers.mousemove); + } + c.removeEventListener('mousedown', this._eventHandlers.mousedown); + window.removeEventListener('mouseup', this._eventHandlers.mouseup); + c.removeEventListener('mouseup', this._eventHandlers.mouseup); + c.removeEventListener('mousemove', this._eventHandlers.mousemove); + c.removeEventListener('wheel', this._eventHandlers.mousewheel); + + document.removeEventListener('click', this._eventHandlers.mousedisable); + + c.removeEventListener('contextmenu', this._eventHandlers.mousedisable); + } +}; + +make_properties(Mouse, [ + ['target', 'ro', 'dom'], // DOM element that captures mouse input + ['notify', 'ro', 'func'], // Function to call to notify whenever a mouse event is received + ['focused', 'rw', 'bool'], // Capture and send mouse clicks/movement + + ['onMouseButton', 'rw', 'func'], // Handler for mouse button click/release + ['onMouseMove', 'rw', 'func'], // Handler for mouse movement + ['touchButton', 'rw', 'int'] // Button mask (1, 2, 4) for touch devices (0 means ignore clicks) +]); + +export { Keyboard, Mouse }; diff --git a/core/input/keysym.js b/core/input/keysym.js index 5983c38a..f3a247fd 100644 --- a/core/input/keysym.js +++ b/core/input/keysym.js @@ -1,4 +1,4 @@ -var KeyTable = { +export default { XK_VoidSymbol: 0xffffff, /* Void symbol */ XK_BackSpace: 0xff08, /* Back space, back char */ @@ -378,5 +378,3 @@ var KeyTable = { XK_thorn: 0x00fe, /* U+00FE LATIN SMALL LETTER THORN */ XK_ydiaeresis: 0x00ff, /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */ }; - -/* [module] export default KeyTable; */ diff --git a/core/input/keysymdef.js b/core/input/keysymdef.js index c4d0ace9..3d9cee39 100644 --- a/core/input/keysymdef.js +++ b/core/input/keysymdef.js @@ -3,22 +3,17 @@ // How this file was generated: // node /Users/jalf/dev/mi/novnc/utils/parse.js /opt/X11/include/X11/keysymdef.h -var keysyms = (function(){ - "use strict"; - var keynames = null; - var codepoints = {"32":32,"33":33,"34":34,"35":35,"36":36,"37":37,"38":38,"39":39,"40":40,"41":41,"42":42,"43":43,"44":44,"45":45,"46":46,"47":47,"48":48,"49":49,"50":50,"51":51,"52":52,"53":53,"54":54,"55":55,"56":56,"57":57,"58":58,"59":59,"60":60,"61":61,"62":62,"63":63,"64":64,"65":65,"66":66,"67":67,"68":68,"69":69,"70":70,"71":71,"72":72,"73":73,"74":74,"75":75,"76":76,"77":77,"78":78,"79":79,"80":80,"81":81,"82":82,"83":83,"84":84,"85":85,"86":86,"87":87,"88":88,"89":89,"90":90,"91":91,"92":92,"93":93,"94":94,"95":95,"96":96,"97":97,"98":98,"99":99,"100":100,"101":101,"102":102,"103":103,"104":104,"105":105,"106":106,"107":107,"108":108,"109":109,"110":110,"111":111,"112":112,"113":113,"114":114,"115":115,"116":116,"117":117,"118":118,"119":119,"120":120,"121":121,"122":122,"123":123,"124":124,"125":125,"126":126,"160":160,"161":161,"162":162,"163":163,"164":164,"165":165,"166":166,"167":167,"168":168,"169":169,"170":170,"171":171,"172":172,"173":173,"174":174,"175":175,"176":176,"177":177,"178":178,"179":179,"180":180,"181":181,"182":182,"183":183,"184":184,"185":185,"186":186,"187":187,"188":188,"189":189,"190":190,"191":191,"192":192,"193":193,"194":194,"195":195,"196":196,"197":197,"198":198,"199":199,"200":200,"201":201,"202":202,"203":203,"204":204,"205":205,"206":206,"207":207,"208":208,"209":209,"210":210,"211":211,"212":212,"213":213,"214":214,"215":215,"216":216,"217":217,"218":218,"219":219,"220":220,"221":221,"222":222,"223":223,"224":224,"225":225,"226":226,"227":227,"228":228,"229":229,"230":230,"231":231,"232":232,"233":233,"234":234,"235":235,"236":236,"237":237,"238":238,"239":239,"240":240,"241":241,"242":242,"243":243,"244":244,"245":245,"246":246,"247":247,"248":248,"249":249,"250":250,"251":251,"252":252,"253":253,"254":254,"255":255,"256":960,"257":992,"258":451,"259":483,"260":417,"261":433,"262":454,"263":486,"264":710,"265":742,"266":709,"267":741,"268":456,"269":488,"270":463,"271":495,"272":464,"273":496,"274":938,"275":954,"278":972,"279":1004,"280":458,"281":490,"282":460,"283":492,"284":728,"285":760,"286":683,"287":699,"288":725,"289":757,"290":939,"291":955,"292":678,"293":694,"294":673,"295":689,"296":933,"297":949,"298":975,"299":1007,"300":16777516,"301":16777517,"302":967,"303":999,"304":681,"305":697,"308":684,"309":700,"310":979,"311":1011,"312":930,"313":453,"314":485,"315":934,"316":950,"317":421,"318":437,"321":419,"322":435,"323":465,"324":497,"325":977,"326":1009,"327":466,"328":498,"330":957,"331":959,"332":978,"333":1010,"336":469,"337":501,"338":5052,"339":5053,"340":448,"341":480,"342":931,"343":947,"344":472,"345":504,"346":422,"347":438,"348":734,"349":766,"350":426,"351":442,"352":425,"353":441,"354":478,"355":510,"356":427,"357":443,"358":940,"359":956,"360":989,"361":1021,"362":990,"363":1022,"364":733,"365":765,"366":473,"367":505,"368":475,"369":507,"370":985,"371":1017,"372":16777588,"373":16777589,"374":16777590,"375":16777591,"376":5054,"377":428,"378":444,"379":431,"380":447,"381":430,"382":446,"399":16777615,"402":2294,"415":16777631,"416":16777632,"417":16777633,"431":16777647,"432":16777648,"437":16777653,"438":16777654,"439":16777655,"466":16777681,"486":16777702,"487":16777703,"601":16777817,"629":16777845,"658":16777874,"711":439,"728":418,"729":511,"731":434,"733":445,"901":1966,"902":1953,"904":1954,"905":1955,"906":1956,"908":1959,"910":1960,"911":1963,"912":1974,"913":1985,"914":1986,"915":1987,"916":1988,"917":1989,"918":1990,"919":1991,"920":1992,"921":1993,"922":1994,"923":1995,"924":1996,"925":1997,"926":1998,"927":1999,"928":2000,"929":2001,"931":2002,"932":2004,"933":2005,"934":2006,"935":2007,"936":2008,"937":2009,"938":1957,"939":1961,"940":1969,"941":1970,"942":1971,"943":1972,"944":1978,"945":2017,"946":2018,"947":2019,"948":2020,"949":2021,"950":2022,"951":2023,"952":2024,"953":2025,"954":2026,"955":2027,"956":2028,"957":2029,"958":2030,"959":2031,"960":2032,"961":2033,"962":2035,"963":2034,"964":2036,"965":2037,"966":2038,"967":2039,"968":2040,"969":2041,"970":1973,"971":1977,"972":1975,"973":1976,"974":1979,"1025":1715,"1026":1713,"1027":1714,"1028":1716,"1029":1717,"1030":1718,"1031":1719,"1032":1720,"1033":1721,"1034":1722,"1035":1723,"1036":1724,"1038":1726,"1039":1727,"1040":1761,"1041":1762,"1042":1783,"1043":1767,"1044":1764,"1045":1765,"1046":1782,"1047":1786,"1048":1769,"1049":1770,"1050":1771,"1051":1772,"1052":1773,"1053":1774,"1054":1775,"1055":1776,"1056":1778,"1057":1779,"1058":1780,"1059":1781,"1060":1766,"1061":1768,"1062":1763,"1063":1790,"1064":1787,"1065":1789,"1066":1791,"1067":1785,"1068":1784,"1069":1788,"1070":1760,"1071":1777,"1072":1729,"1073":1730,"1074":1751,"1075":1735,"1076":1732,"1077":1733,"1078":1750,"1079":1754,"1080":1737,"1081":1738,"1082":1739,"1083":1740,"1084":1741,"1085":1742,"1086":1743,"1087":1744,"1088":1746,"1089":1747,"1090":1748,"1091":1749,"1092":1734,"1093":1736,"1094":1731,"1095":1758,"1096":1755,"1097":1757,"1098":1759,"1099":1753,"1100":1752,"1101":1756,"1102":1728,"1103":1745,"1105":1699,"1106":1697,"1107":1698,"1108":1700,"1109":1701,"1110":1702,"1111":1703,"1112":1704,"1113":1705,"1114":1706,"1115":1707,"1116":1708,"1118":1710,"1119":1711,"1168":1725,"1169":1709,"1170":16778386,"1171":16778387,"1174":16778390,"1175":16778391,"1178":16778394,"1179":16778395,"1180":16778396,"1181":16778397,"1186":16778402,"1187":16778403,"1198":16778414,"1199":16778415,"1200":16778416,"1201":16778417,"1202":16778418,"1203":16778419,"1206":16778422,"1207":16778423,"1208":16778424,"1209":16778425,"1210":16778426,"1211":16778427,"1240":16778456,"1241":16778457,"1250":16778466,"1251":16778467,"1256":16778472,"1257":16778473,"1262":16778478,"1263":16778479,"1329":16778545,"1330":16778546,"1331":16778547,"1332":16778548,"1333":16778549,"1334":16778550,"1335":16778551,"1336":16778552,"1337":16778553,"1338":16778554,"1339":16778555,"1340":16778556,"1341":16778557,"1342":16778558,"1343":16778559,"1344":16778560,"1345":16778561,"1346":16778562,"1347":16778563,"1348":16778564,"1349":16778565,"1350":16778566,"1351":16778567,"1352":16778568,"1353":16778569,"1354":16778570,"1355":16778571,"1356":16778572,"1357":16778573,"1358":16778574,"1359":16778575,"1360":16778576,"1361":16778577,"1362":16778578,"1363":16778579,"1364":16778580,"1365":16778581,"1366":16778582,"1370":16778586,"1371":16778587,"1372":16778588,"1373":16778589,"1374":16778590,"1377":16778593,"1378":16778594,"1379":16778595,"1380":16778596,"1381":16778597,"1382":16778598,"1383":16778599,"1384":16778600,"1385":16778601,"1386":16778602,"1387":16778603,"1388":16778604,"1389":16778605,"1390":16778606,"1391":16778607,"1392":16778608,"1393":16778609,"1394":16778610,"1395":16778611,"1396":16778612,"1397":16778613,"1398":16778614,"1399":16778615,"1400":16778616,"1401":16778617,"1402":16778618,"1403":16778619,"1404":16778620,"1405":16778621,"1406":16778622,"1407":16778623,"1408":16778624,"1409":16778625,"1410":16778626,"1411":16778627,"1412":16778628,"1413":16778629,"1414":16778630,"1415":16778631,"1417":16778633,"1418":16778634,"1488":3296,"1489":3297,"1490":3298,"1491":3299,"1492":3300,"1493":3301,"1494":3302,"1495":3303,"1496":3304,"1497":3305,"1498":3306,"1499":3307,"1500":3308,"1501":3309,"1502":3310,"1503":3311,"1504":3312,"1505":3313,"1506":3314,"1507":3315,"1508":3316,"1509":3317,"1510":3318,"1511":3319,"1512":3320,"1513":3321,"1514":3322,"1548":1452,"1563":1467,"1567":1471,"1569":1473,"1570":1474,"1571":1475,"1572":1476,"1573":1477,"1574":1478,"1575":1479,"1576":1480,"1577":1481,"1578":1482,"1579":1483,"1580":1484,"1581":1485,"1582":1486,"1583":1487,"1584":1488,"1585":1489,"1586":1490,"1587":1491,"1588":1492,"1589":1493,"1590":1494,"1591":1495,"1592":1496,"1593":1497,"1594":1498,"1600":1504,"1601":1505,"1602":1506,"1603":1507,"1604":1508,"1605":1509,"1606":1510,"1607":1511,"1608":1512,"1609":1513,"1610":1514,"1611":1515,"1612":1516,"1613":1517,"1614":1518,"1615":1519,"1616":1520,"1617":1521,"1618":1522,"1619":16778835,"1620":16778836,"1621":16778837,"1632":16778848,"1633":16778849,"1634":16778850,"1635":16778851,"1636":16778852,"1637":16778853,"1638":16778854,"1639":16778855,"1640":16778856,"1641":16778857,"1642":16778858,"1648":16778864,"1657":16778873,"1662":16778878,"1670":16778886,"1672":16778888,"1681":16778897,"1688":16778904,"1700":16778916,"1705":16778921,"1711":16778927,"1722":16778938,"1726":16778942,"1729":16778945,"1740":16778956,"1746":16778962,"1748":16778964,"1776":16778992,"1777":16778993,"1778":16778994,"1779":16778995,"1780":16778996,"1781":16778997,"1782":16778998,"1783":16778999,"1784":16779000,"1785":16779001,"3458":16780674,"3459":16780675,"3461":16780677,"3462":16780678,"3463":16780679,"3464":16780680,"3465":16780681,"3466":16780682,"3467":16780683,"3468":16780684,"3469":16780685,"3470":16780686,"3471":16780687,"3472":16780688,"3473":16780689,"3474":16780690,"3475":16780691,"3476":16780692,"3477":16780693,"3478":16780694,"3482":16780698,"3483":16780699,"3484":16780700,"3485":16780701,"3486":16780702,"3487":16780703,"3488":16780704,"3489":16780705,"3490":16780706,"3491":16780707,"3492":16780708,"3493":16780709,"3494":16780710,"3495":16780711,"3496":16780712,"3497":16780713,"3498":16780714,"3499":16780715,"3500":16780716,"3501":16780717,"3502":16780718,"3503":16780719,"3504":16780720,"3505":16780721,"3507":16780723,"3508":16780724,"3509":16780725,"3510":16780726,"3511":16780727,"3512":16780728,"3513":16780729,"3514":16780730,"3515":16780731,"3517":16780733,"3520":16780736,"3521":16780737,"3522":16780738,"3523":16780739,"3524":16780740,"3525":16780741,"3526":16780742,"3530":16780746,"3535":16780751,"3536":16780752,"3537":16780753,"3538":16780754,"3539":16780755,"3540":16780756,"3542":16780758,"3544":16780760,"3545":16780761,"3546":16780762,"3547":16780763,"3548":16780764,"3549":16780765,"3550":16780766,"3551":16780767,"3570":16780786,"3571":16780787,"3572":16780788,"3585":3489,"3586":3490,"3587":3491,"3588":3492,"3589":3493,"3590":3494,"3591":3495,"3592":3496,"3593":3497,"3594":3498,"3595":3499,"3596":3500,"3597":3501,"3598":3502,"3599":3503,"3600":3504,"3601":3505,"3602":3506,"3603":3507,"3604":3508,"3605":3509,"3606":3510,"3607":3511,"3608":3512,"3609":3513,"3610":3514,"3611":3515,"3612":3516,"3613":3517,"3614":3518,"3615":3519,"3616":3520,"3617":3521,"3618":3522,"3619":3523,"3620":3524,"3621":3525,"3622":3526,"3623":3527,"3624":3528,"3625":3529,"3626":3530,"3627":3531,"3628":3532,"3629":3533,"3630":3534,"3631":3535,"3632":3536,"3633":3537,"3634":3538,"3635":3539,"3636":3540,"3637":3541,"3638":3542,"3639":3543,"3640":3544,"3641":3545,"3642":3546,"3647":3551,"3648":3552,"3649":3553,"3650":3554,"3651":3555,"3652":3556,"3653":3557,"3654":3558,"3655":3559,"3656":3560,"3657":3561,"3658":3562,"3659":3563,"3660":3564,"3661":3565,"3664":3568,"3665":3569,"3666":3570,"3667":3571,"3668":3572,"3669":3573,"3670":3574,"3671":3575,"3672":3576,"3673":3577,"4304":16781520,"4305":16781521,"4306":16781522,"4307":16781523,"4308":16781524,"4309":16781525,"4310":16781526,"4311":16781527,"4312":16781528,"4313":16781529,"4314":16781530,"4315":16781531,"4316":16781532,"4317":16781533,"4318":16781534,"4319":16781535,"4320":16781536,"4321":16781537,"4322":16781538,"4323":16781539,"4324":16781540,"4325":16781541,"4326":16781542,"4327":16781543,"4328":16781544,"4329":16781545,"4330":16781546,"4331":16781547,"4332":16781548,"4333":16781549,"4334":16781550,"4335":16781551,"4336":16781552,"4337":16781553,"4338":16781554,"4339":16781555,"4340":16781556,"4341":16781557,"4342":16781558,"7682":16784898,"7683":16784899,"7690":16784906,"7691":16784907,"7710":16784926,"7711":16784927,"7734":16784950,"7735":16784951,"7744":16784960,"7745":16784961,"7766":16784982,"7767":16784983,"7776":16784992,"7777":16784993,"7786":16785002,"7787":16785003,"7808":16785024,"7809":16785025,"7810":16785026,"7811":16785027,"7812":16785028,"7813":16785029,"7818":16785034,"7819":16785035,"7840":16785056,"7841":16785057,"7842":16785058,"7843":16785059,"7844":16785060,"7845":16785061,"7846":16785062,"7847":16785063,"7848":16785064,"7849":16785065,"7850":16785066,"7851":16785067,"7852":16785068,"7853":16785069,"7854":16785070,"7855":16785071,"7856":16785072,"7857":16785073,"7858":16785074,"7859":16785075,"7860":16785076,"7861":16785077,"7862":16785078,"7863":16785079,"7864":16785080,"7865":16785081,"7866":16785082,"7867":16785083,"7868":16785084,"7869":16785085,"7870":16785086,"7871":16785087,"7872":16785088,"7873":16785089,"7874":16785090,"7875":16785091,"7876":16785092,"7877":16785093,"7878":16785094,"7879":16785095,"7880":16785096,"7881":16785097,"7882":16785098,"7883":16785099,"7884":16785100,"7885":16785101,"7886":16785102,"7887":16785103,"7888":16785104,"7889":16785105,"7890":16785106,"7891":16785107,"7892":16785108,"7893":16785109,"7894":16785110,"7895":16785111,"7896":16785112,"7897":16785113,"7898":16785114,"7899":16785115,"7900":16785116,"7901":16785117,"7902":16785118,"7903":16785119,"7904":16785120,"7905":16785121,"7906":16785122,"7907":16785123,"7908":16785124,"7909":16785125,"7910":16785126,"7911":16785127,"7912":16785128,"7913":16785129,"7914":16785130,"7915":16785131,"7916":16785132,"7917":16785133,"7918":16785134,"7919":16785135,"7920":16785136,"7921":16785137,"7922":16785138,"7923":16785139,"7924":16785140,"7925":16785141,"7926":16785142,"7927":16785143,"7928":16785144,"7929":16785145,"8194":2722,"8195":2721,"8196":2723,"8197":2724,"8199":2725,"8200":2726,"8201":2727,"8202":2728,"8210":2747,"8211":2730,"8212":2729,"8213":1967,"8215":3295,"8216":2768,"8217":2769,"8218":2813,"8220":2770,"8221":2771,"8222":2814,"8224":2801,"8225":2802,"8226":2790,"8229":2735,"8230":2734,"8240":2773,"8242":2774,"8243":2775,"8248":2812,"8254":1150,"8304":16785520,"8308":16785524,"8309":16785525,"8310":16785526,"8311":16785527,"8312":16785528,"8313":16785529,"8320":16785536,"8321":16785537,"8322":16785538,"8323":16785539,"8324":16785540,"8325":16785541,"8326":16785542,"8327":16785543,"8328":16785544,"8329":16785545,"8352":16785568,"8353":16785569,"8354":16785570,"8355":16785571,"8356":16785572,"8357":16785573,"8358":16785574,"8359":16785575,"8360":16785576,"8361":3839,"8362":16785578,"8363":16785579,"8364":8364,"8453":2744,"8470":1712,"8471":2811,"8478":2772,"8482":2761,"8531":2736,"8532":2737,"8533":2738,"8534":2739,"8535":2740,"8536":2741,"8537":2742,"8538":2743,"8539":2755,"8540":2756,"8541":2757,"8542":2758,"8592":2299,"8593":2300,"8594":2301,"8595":2302,"8658":2254,"8660":2253,"8706":2287,"8709":16785925,"8711":2245,"8712":16785928,"8713":16785929,"8715":16785931,"8728":3018,"8730":2262,"8731":16785947,"8732":16785948,"8733":2241,"8734":2242,"8743":2270,"8744":2271,"8745":2268,"8746":2269,"8747":2239,"8748":16785964,"8749":16785965,"8756":2240,"8757":16785973,"8764":2248,"8771":2249,"8773":16785992,"8775":16785991,"8800":2237,"8801":2255,"8802":16786018,"8803":16786019,"8804":2236,"8805":2238,"8834":2266,"8835":2267,"8866":3068,"8867":3036,"8868":3010,"8869":3022,"8968":3027,"8970":3012,"8981":2810,"8992":2212,"8993":2213,"9109":3020,"9115":2219,"9117":2220,"9118":2221,"9120":2222,"9121":2215,"9123":2216,"9124":2217,"9126":2218,"9128":2223,"9132":2224,"9143":2209,"9146":2543,"9147":2544,"9148":2546,"9149":2547,"9225":2530,"9226":2533,"9227":2537,"9228":2531,"9229":2532,"9251":2732,"9252":2536,"9472":2211,"9474":2214,"9484":2210,"9488":2539,"9492":2541,"9496":2538,"9500":2548,"9508":2549,"9516":2551,"9524":2550,"9532":2542,"9618":2529,"9642":2791,"9643":2785,"9644":2779,"9645":2786,"9646":2783,"9647":2767,"9650":2792,"9651":2787,"9654":2781,"9655":2765,"9660":2793,"9661":2788,"9664":2780,"9665":2764,"9670":2528,"9675":2766,"9679":2782,"9702":2784,"9734":2789,"9742":2809,"9747":2762,"9756":2794,"9758":2795,"9792":2808,"9794":2807,"9827":2796,"9829":2798,"9830":2797,"9837":2806,"9839":2805,"10003":2803,"10007":2804,"10013":2777,"10016":2800,"10216":2748,"10217":2750,"10240":16787456,"10241":16787457,"10242":16787458,"10243":16787459,"10244":16787460,"10245":16787461,"10246":16787462,"10247":16787463,"10248":16787464,"10249":16787465,"10250":16787466,"10251":16787467,"10252":16787468,"10253":16787469,"10254":16787470,"10255":16787471,"10256":16787472,"10257":16787473,"10258":16787474,"10259":16787475,"10260":16787476,"10261":16787477,"10262":16787478,"10263":16787479,"10264":16787480,"10265":16787481,"10266":16787482,"10267":16787483,"10268":16787484,"10269":16787485,"10270":16787486,"10271":16787487,"10272":16787488,"10273":16787489,"10274":16787490,"10275":16787491,"10276":16787492,"10277":16787493,"10278":16787494,"10279":16787495,"10280":16787496,"10281":16787497,"10282":16787498,"10283":16787499,"10284":16787500,"10285":16787501,"10286":16787502,"10287":16787503,"10288":16787504,"10289":16787505,"10290":16787506,"10291":16787507,"10292":16787508,"10293":16787509,"10294":16787510,"10295":16787511,"10296":16787512,"10297":16787513,"10298":16787514,"10299":16787515,"10300":16787516,"10301":16787517,"10302":16787518,"10303":16787519,"10304":16787520,"10305":16787521,"10306":16787522,"10307":16787523,"10308":16787524,"10309":16787525,"10310":16787526,"10311":16787527,"10312":16787528,"10313":16787529,"10314":16787530,"10315":16787531,"10316":16787532,"10317":16787533,"10318":16787534,"10319":16787535,"10320":16787536,"10321":16787537,"10322":16787538,"10323":16787539,"10324":16787540,"10325":16787541,"10326":16787542,"10327":16787543,"10328":16787544,"10329":16787545,"10330":16787546,"10331":16787547,"10332":16787548,"10333":16787549,"10334":16787550,"10335":16787551,"10336":16787552,"10337":16787553,"10338":16787554,"10339":16787555,"10340":16787556,"10341":16787557,"10342":16787558,"10343":16787559,"10344":16787560,"10345":16787561,"10346":16787562,"10347":16787563,"10348":16787564,"10349":16787565,"10350":16787566,"10351":16787567,"10352":16787568,"10353":16787569,"10354":16787570,"10355":16787571,"10356":16787572,"10357":16787573,"10358":16787574,"10359":16787575,"10360":16787576,"10361":16787577,"10362":16787578,"10363":16787579,"10364":16787580,"10365":16787581,"10366":16787582,"10367":16787583,"10368":16787584,"10369":16787585,"10370":16787586,"10371":16787587,"10372":16787588,"10373":16787589,"10374":16787590,"10375":16787591,"10376":16787592,"10377":16787593,"10378":16787594,"10379":16787595,"10380":16787596,"10381":16787597,"10382":16787598,"10383":16787599,"10384":16787600,"10385":16787601,"10386":16787602,"10387":16787603,"10388":16787604,"10389":16787605,"10390":16787606,"10391":16787607,"10392":16787608,"10393":16787609,"10394":16787610,"10395":16787611,"10396":16787612,"10397":16787613,"10398":16787614,"10399":16787615,"10400":16787616,"10401":16787617,"10402":16787618,"10403":16787619,"10404":16787620,"10405":16787621,"10406":16787622,"10407":16787623,"10408":16787624,"10409":16787625,"10410":16787626,"10411":16787627,"10412":16787628,"10413":16787629,"10414":16787630,"10415":16787631,"10416":16787632,"10417":16787633,"10418":16787634,"10419":16787635,"10420":16787636,"10421":16787637,"10422":16787638,"10423":16787639,"10424":16787640,"10425":16787641,"10426":16787642,"10427":16787643,"10428":16787644,"10429":16787645,"10430":16787646,"10431":16787647,"10432":16787648,"10433":16787649,"10434":16787650,"10435":16787651,"10436":16787652,"10437":16787653,"10438":16787654,"10439":16787655,"10440":16787656,"10441":16787657,"10442":16787658,"10443":16787659,"10444":16787660,"10445":16787661,"10446":16787662,"10447":16787663,"10448":16787664,"10449":16787665,"10450":16787666,"10451":16787667,"10452":16787668,"10453":16787669,"10454":16787670,"10455":16787671,"10456":16787672,"10457":16787673,"10458":16787674,"10459":16787675,"10460":16787676,"10461":16787677,"10462":16787678,"10463":16787679,"10464":16787680,"10465":16787681,"10466":16787682,"10467":16787683,"10468":16787684,"10469":16787685,"10470":16787686,"10471":16787687,"10472":16787688,"10473":16787689,"10474":16787690,"10475":16787691,"10476":16787692,"10477":16787693,"10478":16787694,"10479":16787695,"10480":16787696,"10481":16787697,"10482":16787698,"10483":16787699,"10484":16787700,"10485":16787701,"10486":16787702,"10487":16787703,"10488":16787704,"10489":16787705,"10490":16787706,"10491":16787707,"10492":16787708,"10493":16787709,"10494":16787710,"10495":16787711,"12289":1188,"12290":1185,"12300":1186,"12301":1187,"12443":1246,"12444":1247,"12449":1191,"12450":1201,"12451":1192,"12452":1202,"12453":1193,"12454":1203,"12455":1194,"12456":1204,"12457":1195,"12458":1205,"12459":1206,"12461":1207,"12463":1208,"12465":1209,"12467":1210,"12469":1211,"12471":1212,"12473":1213,"12475":1214,"12477":1215,"12479":1216,"12481":1217,"12483":1199,"12484":1218,"12486":1219,"12488":1220,"12490":1221,"12491":1222,"12492":1223,"12493":1224,"12494":1225,"12495":1226,"12498":1227,"12501":1228,"12504":1229,"12507":1230,"12510":1231,"12511":1232,"12512":1233,"12513":1234,"12514":1235,"12515":1196,"12516":1236,"12517":1197,"12518":1237,"12519":1198,"12520":1238,"12521":1239,"12522":1240,"12523":1241,"12524":1242,"12525":1243,"12527":1244,"12530":1190,"12531":1245,"12539":1189,"12540":1200}; +var keynames = null; +var codepoints = {"32":32,"33":33,"34":34,"35":35,"36":36,"37":37,"38":38,"39":39,"40":40,"41":41,"42":42,"43":43,"44":44,"45":45,"46":46,"47":47,"48":48,"49":49,"50":50,"51":51,"52":52,"53":53,"54":54,"55":55,"56":56,"57":57,"58":58,"59":59,"60":60,"61":61,"62":62,"63":63,"64":64,"65":65,"66":66,"67":67,"68":68,"69":69,"70":70,"71":71,"72":72,"73":73,"74":74,"75":75,"76":76,"77":77,"78":78,"79":79,"80":80,"81":81,"82":82,"83":83,"84":84,"85":85,"86":86,"87":87,"88":88,"89":89,"90":90,"91":91,"92":92,"93":93,"94":94,"95":95,"96":96,"97":97,"98":98,"99":99,"100":100,"101":101,"102":102,"103":103,"104":104,"105":105,"106":106,"107":107,"108":108,"109":109,"110":110,"111":111,"112":112,"113":113,"114":114,"115":115,"116":116,"117":117,"118":118,"119":119,"120":120,"121":121,"122":122,"123":123,"124":124,"125":125,"126":126,"160":160,"161":161,"162":162,"163":163,"164":164,"165":165,"166":166,"167":167,"168":168,"169":169,"170":170,"171":171,"172":172,"173":173,"174":174,"175":175,"176":176,"177":177,"178":178,"179":179,"180":180,"181":181,"182":182,"183":183,"184":184,"185":185,"186":186,"187":187,"188":188,"189":189,"190":190,"191":191,"192":192,"193":193,"194":194,"195":195,"196":196,"197":197,"198":198,"199":199,"200":200,"201":201,"202":202,"203":203,"204":204,"205":205,"206":206,"207":207,"208":208,"209":209,"210":210,"211":211,"212":212,"213":213,"214":214,"215":215,"216":216,"217":217,"218":218,"219":219,"220":220,"221":221,"222":222,"223":223,"224":224,"225":225,"226":226,"227":227,"228":228,"229":229,"230":230,"231":231,"232":232,"233":233,"234":234,"235":235,"236":236,"237":237,"238":238,"239":239,"240":240,"241":241,"242":242,"243":243,"244":244,"245":245,"246":246,"247":247,"248":248,"249":249,"250":250,"251":251,"252":252,"253":253,"254":254,"255":255,"256":960,"257":992,"258":451,"259":483,"260":417,"261":433,"262":454,"263":486,"264":710,"265":742,"266":709,"267":741,"268":456,"269":488,"270":463,"271":495,"272":464,"273":496,"274":938,"275":954,"278":972,"279":1004,"280":458,"281":490,"282":460,"283":492,"284":728,"285":760,"286":683,"287":699,"288":725,"289":757,"290":939,"291":955,"292":678,"293":694,"294":673,"295":689,"296":933,"297":949,"298":975,"299":1007,"300":16777516,"301":16777517,"302":967,"303":999,"304":681,"305":697,"308":684,"309":700,"310":979,"311":1011,"312":930,"313":453,"314":485,"315":934,"316":950,"317":421,"318":437,"321":419,"322":435,"323":465,"324":497,"325":977,"326":1009,"327":466,"328":498,"330":957,"331":959,"332":978,"333":1010,"336":469,"337":501,"338":5052,"339":5053,"340":448,"341":480,"342":931,"343":947,"344":472,"345":504,"346":422,"347":438,"348":734,"349":766,"350":426,"351":442,"352":425,"353":441,"354":478,"355":510,"356":427,"357":443,"358":940,"359":956,"360":989,"361":1021,"362":990,"363":1022,"364":733,"365":765,"366":473,"367":505,"368":475,"369":507,"370":985,"371":1017,"372":16777588,"373":16777589,"374":16777590,"375":16777591,"376":5054,"377":428,"378":444,"379":431,"380":447,"381":430,"382":446,"399":16777615,"402":2294,"415":16777631,"416":16777632,"417":16777633,"431":16777647,"432":16777648,"437":16777653,"438":16777654,"439":16777655,"466":16777681,"486":16777702,"487":16777703,"601":16777817,"629":16777845,"658":16777874,"711":439,"728":418,"729":511,"731":434,"733":445,"901":1966,"902":1953,"904":1954,"905":1955,"906":1956,"908":1959,"910":1960,"911":1963,"912":1974,"913":1985,"914":1986,"915":1987,"916":1988,"917":1989,"918":1990,"919":1991,"920":1992,"921":1993,"922":1994,"923":1995,"924":1996,"925":1997,"926":1998,"927":1999,"928":2000,"929":2001,"931":2002,"932":2004,"933":2005,"934":2006,"935":2007,"936":2008,"937":2009,"938":1957,"939":1961,"940":1969,"941":1970,"942":1971,"943":1972,"944":1978,"945":2017,"946":2018,"947":2019,"948":2020,"949":2021,"950":2022,"951":2023,"952":2024,"953":2025,"954":2026,"955":2027,"956":2028,"957":2029,"958":2030,"959":2031,"960":2032,"961":2033,"962":2035,"963":2034,"964":2036,"965":2037,"966":2038,"967":2039,"968":2040,"969":2041,"970":1973,"971":1977,"972":1975,"973":1976,"974":1979,"1025":1715,"1026":1713,"1027":1714,"1028":1716,"1029":1717,"1030":1718,"1031":1719,"1032":1720,"1033":1721,"1034":1722,"1035":1723,"1036":1724,"1038":1726,"1039":1727,"1040":1761,"1041":1762,"1042":1783,"1043":1767,"1044":1764,"1045":1765,"1046":1782,"1047":1786,"1048":1769,"1049":1770,"1050":1771,"1051":1772,"1052":1773,"1053":1774,"1054":1775,"1055":1776,"1056":1778,"1057":1779,"1058":1780,"1059":1781,"1060":1766,"1061":1768,"1062":1763,"1063":1790,"1064":1787,"1065":1789,"1066":1791,"1067":1785,"1068":1784,"1069":1788,"1070":1760,"1071":1777,"1072":1729,"1073":1730,"1074":1751,"1075":1735,"1076":1732,"1077":1733,"1078":1750,"1079":1754,"1080":1737,"1081":1738,"1082":1739,"1083":1740,"1084":1741,"1085":1742,"1086":1743,"1087":1744,"1088":1746,"1089":1747,"1090":1748,"1091":1749,"1092":1734,"1093":1736,"1094":1731,"1095":1758,"1096":1755,"1097":1757,"1098":1759,"1099":1753,"1100":1752,"1101":1756,"1102":1728,"1103":1745,"1105":1699,"1106":1697,"1107":1698,"1108":1700,"1109":1701,"1110":1702,"1111":1703,"1112":1704,"1113":1705,"1114":1706,"1115":1707,"1116":1708,"1118":1710,"1119":1711,"1168":1725,"1169":1709,"1170":16778386,"1171":16778387,"1174":16778390,"1175":16778391,"1178":16778394,"1179":16778395,"1180":16778396,"1181":16778397,"1186":16778402,"1187":16778403,"1198":16778414,"1199":16778415,"1200":16778416,"1201":16778417,"1202":16778418,"1203":16778419,"1206":16778422,"1207":16778423,"1208":16778424,"1209":16778425,"1210":16778426,"1211":16778427,"1240":16778456,"1241":16778457,"1250":16778466,"1251":16778467,"1256":16778472,"1257":16778473,"1262":16778478,"1263":16778479,"1329":16778545,"1330":16778546,"1331":16778547,"1332":16778548,"1333":16778549,"1334":16778550,"1335":16778551,"1336":16778552,"1337":16778553,"1338":16778554,"1339":16778555,"1340":16778556,"1341":16778557,"1342":16778558,"1343":16778559,"1344":16778560,"1345":16778561,"1346":16778562,"1347":16778563,"1348":16778564,"1349":16778565,"1350":16778566,"1351":16778567,"1352":16778568,"1353":16778569,"1354":16778570,"1355":16778571,"1356":16778572,"1357":16778573,"1358":16778574,"1359":16778575,"1360":16778576,"1361":16778577,"1362":16778578,"1363":16778579,"1364":16778580,"1365":16778581,"1366":16778582,"1370":16778586,"1371":16778587,"1372":16778588,"1373":16778589,"1374":16778590,"1377":16778593,"1378":16778594,"1379":16778595,"1380":16778596,"1381":16778597,"1382":16778598,"1383":16778599,"1384":16778600,"1385":16778601,"1386":16778602,"1387":16778603,"1388":16778604,"1389":16778605,"1390":16778606,"1391":16778607,"1392":16778608,"1393":16778609,"1394":16778610,"1395":16778611,"1396":16778612,"1397":16778613,"1398":16778614,"1399":16778615,"1400":16778616,"1401":16778617,"1402":16778618,"1403":16778619,"1404":16778620,"1405":16778621,"1406":16778622,"1407":16778623,"1408":16778624,"1409":16778625,"1410":16778626,"1411":16778627,"1412":16778628,"1413":16778629,"1414":16778630,"1415":16778631,"1417":16778633,"1418":16778634,"1488":3296,"1489":3297,"1490":3298,"1491":3299,"1492":3300,"1493":3301,"1494":3302,"1495":3303,"1496":3304,"1497":3305,"1498":3306,"1499":3307,"1500":3308,"1501":3309,"1502":3310,"1503":3311,"1504":3312,"1505":3313,"1506":3314,"1507":3315,"1508":3316,"1509":3317,"1510":3318,"1511":3319,"1512":3320,"1513":3321,"1514":3322,"1548":1452,"1563":1467,"1567":1471,"1569":1473,"1570":1474,"1571":1475,"1572":1476,"1573":1477,"1574":1478,"1575":1479,"1576":1480,"1577":1481,"1578":1482,"1579":1483,"1580":1484,"1581":1485,"1582":1486,"1583":1487,"1584":1488,"1585":1489,"1586":1490,"1587":1491,"1588":1492,"1589":1493,"1590":1494,"1591":1495,"1592":1496,"1593":1497,"1594":1498,"1600":1504,"1601":1505,"1602":1506,"1603":1507,"1604":1508,"1605":1509,"1606":1510,"1607":1511,"1608":1512,"1609":1513,"1610":1514,"1611":1515,"1612":1516,"1613":1517,"1614":1518,"1615":1519,"1616":1520,"1617":1521,"1618":1522,"1619":16778835,"1620":16778836,"1621":16778837,"1632":16778848,"1633":16778849,"1634":16778850,"1635":16778851,"1636":16778852,"1637":16778853,"1638":16778854,"1639":16778855,"1640":16778856,"1641":16778857,"1642":16778858,"1648":16778864,"1657":16778873,"1662":16778878,"1670":16778886,"1672":16778888,"1681":16778897,"1688":16778904,"1700":16778916,"1705":16778921,"1711":16778927,"1722":16778938,"1726":16778942,"1729":16778945,"1740":16778956,"1746":16778962,"1748":16778964,"1776":16778992,"1777":16778993,"1778":16778994,"1779":16778995,"1780":16778996,"1781":16778997,"1782":16778998,"1783":16778999,"1784":16779000,"1785":16779001,"3458":16780674,"3459":16780675,"3461":16780677,"3462":16780678,"3463":16780679,"3464":16780680,"3465":16780681,"3466":16780682,"3467":16780683,"3468":16780684,"3469":16780685,"3470":16780686,"3471":16780687,"3472":16780688,"3473":16780689,"3474":16780690,"3475":16780691,"3476":16780692,"3477":16780693,"3478":16780694,"3482":16780698,"3483":16780699,"3484":16780700,"3485":16780701,"3486":16780702,"3487":16780703,"3488":16780704,"3489":16780705,"3490":16780706,"3491":16780707,"3492":16780708,"3493":16780709,"3494":16780710,"3495":16780711,"3496":16780712,"3497":16780713,"3498":16780714,"3499":16780715,"3500":16780716,"3501":16780717,"3502":16780718,"3503":16780719,"3504":16780720,"3505":16780721,"3507":16780723,"3508":16780724,"3509":16780725,"3510":16780726,"3511":16780727,"3512":16780728,"3513":16780729,"3514":16780730,"3515":16780731,"3517":16780733,"3520":16780736,"3521":16780737,"3522":16780738,"3523":16780739,"3524":16780740,"3525":16780741,"3526":16780742,"3530":16780746,"3535":16780751,"3536":16780752,"3537":16780753,"3538":16780754,"3539":16780755,"3540":16780756,"3542":16780758,"3544":16780760,"3545":16780761,"3546":16780762,"3547":16780763,"3548":16780764,"3549":16780765,"3550":16780766,"3551":16780767,"3570":16780786,"3571":16780787,"3572":16780788,"3585":3489,"3586":3490,"3587":3491,"3588":3492,"3589":3493,"3590":3494,"3591":3495,"3592":3496,"3593":3497,"3594":3498,"3595":3499,"3596":3500,"3597":3501,"3598":3502,"3599":3503,"3600":3504,"3601":3505,"3602":3506,"3603":3507,"3604":3508,"3605":3509,"3606":3510,"3607":3511,"3608":3512,"3609":3513,"3610":3514,"3611":3515,"3612":3516,"3613":3517,"3614":3518,"3615":3519,"3616":3520,"3617":3521,"3618":3522,"3619":3523,"3620":3524,"3621":3525,"3622":3526,"3623":3527,"3624":3528,"3625":3529,"3626":3530,"3627":3531,"3628":3532,"3629":3533,"3630":3534,"3631":3535,"3632":3536,"3633":3537,"3634":3538,"3635":3539,"3636":3540,"3637":3541,"3638":3542,"3639":3543,"3640":3544,"3641":3545,"3642":3546,"3647":3551,"3648":3552,"3649":3553,"3650":3554,"3651":3555,"3652":3556,"3653":3557,"3654":3558,"3655":3559,"3656":3560,"3657":3561,"3658":3562,"3659":3563,"3660":3564,"3661":3565,"3664":3568,"3665":3569,"3666":3570,"3667":3571,"3668":3572,"3669":3573,"3670":3574,"3671":3575,"3672":3576,"3673":3577,"4304":16781520,"4305":16781521,"4306":16781522,"4307":16781523,"4308":16781524,"4309":16781525,"4310":16781526,"4311":16781527,"4312":16781528,"4313":16781529,"4314":16781530,"4315":16781531,"4316":16781532,"4317":16781533,"4318":16781534,"4319":16781535,"4320":16781536,"4321":16781537,"4322":16781538,"4323":16781539,"4324":16781540,"4325":16781541,"4326":16781542,"4327":16781543,"4328":16781544,"4329":16781545,"4330":16781546,"4331":16781547,"4332":16781548,"4333":16781549,"4334":16781550,"4335":16781551,"4336":16781552,"4337":16781553,"4338":16781554,"4339":16781555,"4340":16781556,"4341":16781557,"4342":16781558,"7682":16784898,"7683":16784899,"7690":16784906,"7691":16784907,"7710":16784926,"7711":16784927,"7734":16784950,"7735":16784951,"7744":16784960,"7745":16784961,"7766":16784982,"7767":16784983,"7776":16784992,"7777":16784993,"7786":16785002,"7787":16785003,"7808":16785024,"7809":16785025,"7810":16785026,"7811":16785027,"7812":16785028,"7813":16785029,"7818":16785034,"7819":16785035,"7840":16785056,"7841":16785057,"7842":16785058,"7843":16785059,"7844":16785060,"7845":16785061,"7846":16785062,"7847":16785063,"7848":16785064,"7849":16785065,"7850":16785066,"7851":16785067,"7852":16785068,"7853":16785069,"7854":16785070,"7855":16785071,"7856":16785072,"7857":16785073,"7858":16785074,"7859":16785075,"7860":16785076,"7861":16785077,"7862":16785078,"7863":16785079,"7864":16785080,"7865":16785081,"7866":16785082,"7867":16785083,"7868":16785084,"7869":16785085,"7870":16785086,"7871":16785087,"7872":16785088,"7873":16785089,"7874":16785090,"7875":16785091,"7876":16785092,"7877":16785093,"7878":16785094,"7879":16785095,"7880":16785096,"7881":16785097,"7882":16785098,"7883":16785099,"7884":16785100,"7885":16785101,"7886":16785102,"7887":16785103,"7888":16785104,"7889":16785105,"7890":16785106,"7891":16785107,"7892":16785108,"7893":16785109,"7894":16785110,"7895":16785111,"7896":16785112,"7897":16785113,"7898":16785114,"7899":16785115,"7900":16785116,"7901":16785117,"7902":16785118,"7903":16785119,"7904":16785120,"7905":16785121,"7906":16785122,"7907":16785123,"7908":16785124,"7909":16785125,"7910":16785126,"7911":16785127,"7912":16785128,"7913":16785129,"7914":16785130,"7915":16785131,"7916":16785132,"7917":16785133,"7918":16785134,"7919":16785135,"7920":16785136,"7921":16785137,"7922":16785138,"7923":16785139,"7924":16785140,"7925":16785141,"7926":16785142,"7927":16785143,"7928":16785144,"7929":16785145,"8194":2722,"8195":2721,"8196":2723,"8197":2724,"8199":2725,"8200":2726,"8201":2727,"8202":2728,"8210":2747,"8211":2730,"8212":2729,"8213":1967,"8215":3295,"8216":2768,"8217":2769,"8218":2813,"8220":2770,"8221":2771,"8222":2814,"8224":2801,"8225":2802,"8226":2790,"8229":2735,"8230":2734,"8240":2773,"8242":2774,"8243":2775,"8248":2812,"8254":1150,"8304":16785520,"8308":16785524,"8309":16785525,"8310":16785526,"8311":16785527,"8312":16785528,"8313":16785529,"8320":16785536,"8321":16785537,"8322":16785538,"8323":16785539,"8324":16785540,"8325":16785541,"8326":16785542,"8327":16785543,"8328":16785544,"8329":16785545,"8352":16785568,"8353":16785569,"8354":16785570,"8355":16785571,"8356":16785572,"8357":16785573,"8358":16785574,"8359":16785575,"8360":16785576,"8361":3839,"8362":16785578,"8363":16785579,"8364":8364,"8453":2744,"8470":1712,"8471":2811,"8478":2772,"8482":2761,"8531":2736,"8532":2737,"8533":2738,"8534":2739,"8535":2740,"8536":2741,"8537":2742,"8538":2743,"8539":2755,"8540":2756,"8541":2757,"8542":2758,"8592":2299,"8593":2300,"8594":2301,"8595":2302,"8658":2254,"8660":2253,"8706":2287,"8709":16785925,"8711":2245,"8712":16785928,"8713":16785929,"8715":16785931,"8728":3018,"8730":2262,"8731":16785947,"8732":16785948,"8733":2241,"8734":2242,"8743":2270,"8744":2271,"8745":2268,"8746":2269,"8747":2239,"8748":16785964,"8749":16785965,"8756":2240,"8757":16785973,"8764":2248,"8771":2249,"8773":16785992,"8775":16785991,"8800":2237,"8801":2255,"8802":16786018,"8803":16786019,"8804":2236,"8805":2238,"8834":2266,"8835":2267,"8866":3068,"8867":3036,"8868":3010,"8869":3022,"8968":3027,"8970":3012,"8981":2810,"8992":2212,"8993":2213,"9109":3020,"9115":2219,"9117":2220,"9118":2221,"9120":2222,"9121":2215,"9123":2216,"9124":2217,"9126":2218,"9128":2223,"9132":2224,"9143":2209,"9146":2543,"9147":2544,"9148":2546,"9149":2547,"9225":2530,"9226":2533,"9227":2537,"9228":2531,"9229":2532,"9251":2732,"9252":2536,"9472":2211,"9474":2214,"9484":2210,"9488":2539,"9492":2541,"9496":2538,"9500":2548,"9508":2549,"9516":2551,"9524":2550,"9532":2542,"9618":2529,"9642":2791,"9643":2785,"9644":2779,"9645":2786,"9646":2783,"9647":2767,"9650":2792,"9651":2787,"9654":2781,"9655":2765,"9660":2793,"9661":2788,"9664":2780,"9665":2764,"9670":2528,"9675":2766,"9679":2782,"9702":2784,"9734":2789,"9742":2809,"9747":2762,"9756":2794,"9758":2795,"9792":2808,"9794":2807,"9827":2796,"9829":2798,"9830":2797,"9837":2806,"9839":2805,"10003":2803,"10007":2804,"10013":2777,"10016":2800,"10216":2748,"10217":2750,"10240":16787456,"10241":16787457,"10242":16787458,"10243":16787459,"10244":16787460,"10245":16787461,"10246":16787462,"10247":16787463,"10248":16787464,"10249":16787465,"10250":16787466,"10251":16787467,"10252":16787468,"10253":16787469,"10254":16787470,"10255":16787471,"10256":16787472,"10257":16787473,"10258":16787474,"10259":16787475,"10260":16787476,"10261":16787477,"10262":16787478,"10263":16787479,"10264":16787480,"10265":16787481,"10266":16787482,"10267":16787483,"10268":16787484,"10269":16787485,"10270":16787486,"10271":16787487,"10272":16787488,"10273":16787489,"10274":16787490,"10275":16787491,"10276":16787492,"10277":16787493,"10278":16787494,"10279":16787495,"10280":16787496,"10281":16787497,"10282":16787498,"10283":16787499,"10284":16787500,"10285":16787501,"10286":16787502,"10287":16787503,"10288":16787504,"10289":16787505,"10290":16787506,"10291":16787507,"10292":16787508,"10293":16787509,"10294":16787510,"10295":16787511,"10296":16787512,"10297":16787513,"10298":16787514,"10299":16787515,"10300":16787516,"10301":16787517,"10302":16787518,"10303":16787519,"10304":16787520,"10305":16787521,"10306":16787522,"10307":16787523,"10308":16787524,"10309":16787525,"10310":16787526,"10311":16787527,"10312":16787528,"10313":16787529,"10314":16787530,"10315":16787531,"10316":16787532,"10317":16787533,"10318":16787534,"10319":16787535,"10320":16787536,"10321":16787537,"10322":16787538,"10323":16787539,"10324":16787540,"10325":16787541,"10326":16787542,"10327":16787543,"10328":16787544,"10329":16787545,"10330":16787546,"10331":16787547,"10332":16787548,"10333":16787549,"10334":16787550,"10335":16787551,"10336":16787552,"10337":16787553,"10338":16787554,"10339":16787555,"10340":16787556,"10341":16787557,"10342":16787558,"10343":16787559,"10344":16787560,"10345":16787561,"10346":16787562,"10347":16787563,"10348":16787564,"10349":16787565,"10350":16787566,"10351":16787567,"10352":16787568,"10353":16787569,"10354":16787570,"10355":16787571,"10356":16787572,"10357":16787573,"10358":16787574,"10359":16787575,"10360":16787576,"10361":16787577,"10362":16787578,"10363":16787579,"10364":16787580,"10365":16787581,"10366":16787582,"10367":16787583,"10368":16787584,"10369":16787585,"10370":16787586,"10371":16787587,"10372":16787588,"10373":16787589,"10374":16787590,"10375":16787591,"10376":16787592,"10377":16787593,"10378":16787594,"10379":16787595,"10380":16787596,"10381":16787597,"10382":16787598,"10383":16787599,"10384":16787600,"10385":16787601,"10386":16787602,"10387":16787603,"10388":16787604,"10389":16787605,"10390":16787606,"10391":16787607,"10392":16787608,"10393":16787609,"10394":16787610,"10395":16787611,"10396":16787612,"10397":16787613,"10398":16787614,"10399":16787615,"10400":16787616,"10401":16787617,"10402":16787618,"10403":16787619,"10404":16787620,"10405":16787621,"10406":16787622,"10407":16787623,"10408":16787624,"10409":16787625,"10410":16787626,"10411":16787627,"10412":16787628,"10413":16787629,"10414":16787630,"10415":16787631,"10416":16787632,"10417":16787633,"10418":16787634,"10419":16787635,"10420":16787636,"10421":16787637,"10422":16787638,"10423":16787639,"10424":16787640,"10425":16787641,"10426":16787642,"10427":16787643,"10428":16787644,"10429":16787645,"10430":16787646,"10431":16787647,"10432":16787648,"10433":16787649,"10434":16787650,"10435":16787651,"10436":16787652,"10437":16787653,"10438":16787654,"10439":16787655,"10440":16787656,"10441":16787657,"10442":16787658,"10443":16787659,"10444":16787660,"10445":16787661,"10446":16787662,"10447":16787663,"10448":16787664,"10449":16787665,"10450":16787666,"10451":16787667,"10452":16787668,"10453":16787669,"10454":16787670,"10455":16787671,"10456":16787672,"10457":16787673,"10458":16787674,"10459":16787675,"10460":16787676,"10461":16787677,"10462":16787678,"10463":16787679,"10464":16787680,"10465":16787681,"10466":16787682,"10467":16787683,"10468":16787684,"10469":16787685,"10470":16787686,"10471":16787687,"10472":16787688,"10473":16787689,"10474":16787690,"10475":16787691,"10476":16787692,"10477":16787693,"10478":16787694,"10479":16787695,"10480":16787696,"10481":16787697,"10482":16787698,"10483":16787699,"10484":16787700,"10485":16787701,"10486":16787702,"10487":16787703,"10488":16787704,"10489":16787705,"10490":16787706,"10491":16787707,"10492":16787708,"10493":16787709,"10494":16787710,"10495":16787711,"12289":1188,"12290":1185,"12300":1186,"12301":1187,"12443":1246,"12444":1247,"12449":1191,"12450":1201,"12451":1192,"12452":1202,"12453":1193,"12454":1203,"12455":1194,"12456":1204,"12457":1195,"12458":1205,"12459":1206,"12461":1207,"12463":1208,"12465":1209,"12467":1210,"12469":1211,"12471":1212,"12473":1213,"12475":1214,"12477":1215,"12479":1216,"12481":1217,"12483":1199,"12484":1218,"12486":1219,"12488":1220,"12490":1221,"12491":1222,"12492":1223,"12493":1224,"12494":1225,"12495":1226,"12498":1227,"12501":1228,"12504":1229,"12507":1230,"12510":1231,"12511":1232,"12512":1233,"12513":1234,"12514":1235,"12515":1196,"12516":1236,"12517":1197,"12518":1237,"12519":1198,"12520":1238,"12521":1239,"12522":1240,"12523":1241,"12524":1242,"12525":1243,"12527":1244,"12530":1190,"12531":1245,"12539":1189,"12540":1200}; - function lookup(k) { return k ? {keysym: k, keyname: keynames ? keynames[k] : k} : undefined; } - return { - fromUnicode : function(u) { - var keysym = codepoints[u]; - if (keysym === undefined) { - keysym = 0x01000000 | u; - } - return lookup(keysym); - }, - lookup : lookup - }; -})(); - -/* [module] export default keysyms */ +function lookup(k) { return k ? {keysym: k, keyname: keynames ? keynames[k] : k} : undefined; } +export default { + fromUnicode : function(u) { + var keysym = codepoints[u]; + if (keysym === undefined) { + keysym = 0x01000000 | u; + } + return lookup(keysym); + }, + lookup : lookup +}; diff --git a/core/input/util.js b/core/input/util.js index 52b31283..b1e63711 100644 --- a/core/input/util.js +++ b/core/input/util.js @@ -1,294 +1,277 @@ -/* [module] - * import KeyTable from "./keysym"; - * import keysyms from "./keysymdef"; - */ +import KeyTable from "./keysym.js"; +import keysyms from "./keysymdef.js"; -var KeyboardUtil = {}; +export function substituteCodepoint(cp) { + // Any Unicode code points which do not have corresponding keysym entries + // can be swapped out for another code point by adding them to this table + var substitutions = { + // {S,s} with comma below -> {S,s} with cedilla + 0x218 : 0x15e, + 0x219 : 0x15f, + // {T,t} with comma below -> {T,t} with cedilla + 0x21a : 0x162, + 0x21b : 0x163 + }; -(function() { - "use strict"; + var sub = substitutions[cp]; + return sub ? sub : cp; +} - function substituteCodepoint(cp) { - // Any Unicode code points which do not have corresponding keysym entries - // can be swapped out for another code point by adding them to this table - var substitutions = { - // {S,s} with comma below -> {S,s} with cedilla - 0x218 : 0x15e, - 0x219 : 0x15f, - // {T,t} with comma below -> {T,t} with cedilla - 0x21a : 0x162, - 0x21b : 0x163 - }; +function isMac() { + return navigator && !!(/mac/i).exec(navigator.platform); +} +function isWindows() { + return navigator && !!(/win/i).exec(navigator.platform); +} +function isLinux() { + return navigator && !!(/linux/i).exec(navigator.platform); +} - var sub = substitutions[cp]; - return sub ? sub : cp; - } - - function isMac() { - return navigator && !!(/mac/i).exec(navigator.platform); - } - function isWindows() { - return navigator && !!(/win/i).exec(navigator.platform); - } - function isLinux() { - return navigator && !!(/linux/i).exec(navigator.platform); - } - - // Return true if a modifier which is not the specified char modifier (and is not shift) is down - function hasShortcutModifier(charModifier, currentModifiers) { - var mods = {}; - for (var key in currentModifiers) { - if (parseInt(key) !== KeyTable.XK_Shift_L) { - mods[key] = currentModifiers[key]; - } +// Return true if a modifier which is not the specified char modifier (and is not shift) is down +export function hasShortcutModifier(charModifier, currentModifiers) { + var mods = {}; + for (var key in currentModifiers) { + if (parseInt(key) !== KeyTable.XK_Shift_L) { + mods[key] = currentModifiers[key]; } + } - var sum = 0; - for (var k in currentModifiers) { - if (mods[k]) { - ++sum; - } + var sum = 0; + for (var k in currentModifiers) { + if (mods[k]) { + ++sum; } - if (hasCharModifier(charModifier, mods)) { - return sum > charModifier.length; + } + if (hasCharModifier(charModifier, mods)) { + return sum > charModifier.length; + } + else { + return sum > 0; + } +} + +// Return true if the specified char modifier is currently down +export function hasCharModifier(charModifier, currentModifiers) { + if (charModifier.length === 0) { return false; } + + for (var i = 0; i < charModifier.length; ++i) { + if (!currentModifiers[charModifier[i]]) { + return false; + } + } + return true; +} + +// Helper object tracking modifier key state +// and generates fake key events to compensate if it gets out of sync +export function ModifierSync(charModifier) { + if (!charModifier) { + if (isMac()) { + // on Mac, Option (AKA Alt) is used as a char modifier + charModifier = [KeyTable.XK_Alt_L]; + } + else if (isWindows()) { + // on Windows, Ctrl+Alt is used as a char modifier + charModifier = [KeyTable.XK_Alt_L, KeyTable.XK_Control_L]; + } + else if (isLinux()) { + // on Linux, ISO Level 3 Shift (AltGr) is used as a char modifier + charModifier = [KeyTable.XK_ISO_Level3_Shift]; } else { - return sum > 0; + charModifier = []; } } - // Return true if the specified char modifier is currently down - function hasCharModifier(charModifier, currentModifiers) { - if (charModifier.length === 0) { return false; } + var state = {}; + state[KeyTable.XK_Control_L] = false; + state[KeyTable.XK_Alt_L] = false; + state[KeyTable.XK_ISO_Level3_Shift] = false; + state[KeyTable.XK_Shift_L] = false; + state[KeyTable.XK_Meta_L] = false; - for (var i = 0; i < charModifier.length; ++i) { - if (!currentModifiers[charModifier[i]]) { - return false; - } + function sync(evt, keysym) { + var result = []; + function syncKey(keysym) { + return {keysym: keysyms.lookup(keysym), type: state[keysym] ? 'keydown' : 'keyup'}; } - return true; + + if (evt.ctrlKey !== undefined && + evt.ctrlKey !== state[KeyTable.XK_Control_L] && keysym !== KeyTable.XK_Control_L) { + state[KeyTable.XK_Control_L] = evt.ctrlKey; + result.push(syncKey(KeyTable.XK_Control_L)); + } + if (evt.altKey !== undefined && + evt.altKey !== state[KeyTable.XK_Alt_L] && keysym !== KeyTable.XK_Alt_L) { + state[KeyTable.XK_Alt_L] = evt.altKey; + result.push(syncKey(KeyTable.XK_Alt_L)); + } + if (evt.altGraphKey !== undefined && + evt.altGraphKey !== state[KeyTable.XK_ISO_Level3_Shift] && keysym !== KeyTable.XK_ISO_Level3_Shift) { + state[KeyTable.XK_ISO_Level3_Shift] = evt.altGraphKey; + result.push(syncKey(KeyTable.XK_ISO_Level3_Shift)); + } + if (evt.shiftKey !== undefined && + evt.shiftKey !== state[KeyTable.XK_Shift_L] && keysym !== KeyTable.XK_Shift_L) { + state[KeyTable.XK_Shift_L] = evt.shiftKey; + result.push(syncKey(KeyTable.XK_Shift_L)); + } + if (evt.metaKey !== undefined && + evt.metaKey !== state[KeyTable.XK_Meta_L] && keysym !== KeyTable.XK_Meta_L) { + state[KeyTable.XK_Meta_L] = evt.metaKey; + result.push(syncKey(KeyTable.XK_Meta_L)); + } + return result; + } + function syncKeyEvent(evt, down) { + var obj = getKeysym(evt); + var keysym = obj ? obj.keysym : null; + + // first, apply the event itself, if relevant + if (keysym !== null && state[keysym] !== undefined) { + state[keysym] = down; + } + return sync(evt, keysym); } - // Helper object tracking modifier key state - // and generates fake key events to compensate if it gets out of sync - function ModifierSync(charModifier) { - if (!charModifier) { - if (isMac()) { - // on Mac, Option (AKA Alt) is used as a char modifier - charModifier = [KeyTable.XK_Alt_L]; - } - else if (isWindows()) { - // on Windows, Ctrl+Alt is used as a char modifier - charModifier = [KeyTable.XK_Alt_L, KeyTable.XK_Control_L]; - } - else if (isLinux()) { - // on Linux, ISO Level 3 Shift (AltGr) is used as a char modifier - charModifier = [KeyTable.XK_ISO_Level3_Shift]; - } - else { - charModifier = []; - } - } + return { + // sync on the appropriate keyboard event + keydown: function(evt) { return syncKeyEvent(evt, true);}, + keyup: function(evt) { return syncKeyEvent(evt, false);}, + // Call this with a non-keyboard event (such as mouse events) to use its modifier state to synchronize anyway + syncAny: function(evt) { return sync(evt);}, - var state = {}; - state[KeyTable.XK_Control_L] = false; - state[KeyTable.XK_Alt_L] = false; - state[KeyTable.XK_ISO_Level3_Shift] = false; - state[KeyTable.XK_Shift_L] = false; - state[KeyTable.XK_Meta_L] = false; + // is a shortcut modifier down? + hasShortcutModifier: function() { return hasShortcutModifier(charModifier, state); }, + // if a char modifier is down, return the keys it consists of, otherwise return null + activeCharModifier: function() { return hasCharModifier(charModifier, state) ? charModifier : null; } + }; +} - function sync(evt, keysym) { - var result = []; - function syncKey(keysym) { - return {keysym: keysyms.lookup(keysym), type: state[keysym] ? 'keydown' : 'keyup'}; - } - - if (evt.ctrlKey !== undefined && - evt.ctrlKey !== state[KeyTable.XK_Control_L] && keysym !== KeyTable.XK_Control_L) { - state[KeyTable.XK_Control_L] = evt.ctrlKey; - result.push(syncKey(KeyTable.XK_Control_L)); - } - if (evt.altKey !== undefined && - evt.altKey !== state[KeyTable.XK_Alt_L] && keysym !== KeyTable.XK_Alt_L) { - state[KeyTable.XK_Alt_L] = evt.altKey; - result.push(syncKey(KeyTable.XK_Alt_L)); - } - if (evt.altGraphKey !== undefined && - evt.altGraphKey !== state[KeyTable.XK_ISO_Level3_Shift] && keysym !== KeyTable.XK_ISO_Level3_Shift) { - state[KeyTable.XK_ISO_Level3_Shift] = evt.altGraphKey; - result.push(syncKey(KeyTable.XK_ISO_Level3_Shift)); - } - if (evt.shiftKey !== undefined && - evt.shiftKey !== state[KeyTable.XK_Shift_L] && keysym !== KeyTable.XK_Shift_L) { - state[KeyTable.XK_Shift_L] = evt.shiftKey; - result.push(syncKey(KeyTable.XK_Shift_L)); - } - if (evt.metaKey !== undefined && - evt.metaKey !== state[KeyTable.XK_Meta_L] && keysym !== KeyTable.XK_Meta_L) { - state[KeyTable.XK_Meta_L] = evt.metaKey; - result.push(syncKey(KeyTable.XK_Meta_L)); - } - return result; - } - function syncKeyEvent(evt, down) { - var obj = getKeysym(evt); - var keysym = obj ? obj.keysym : null; - - // first, apply the event itself, if relevant - if (keysym !== null && state[keysym] !== undefined) { - state[keysym] = down; - } - return sync(evt, keysym); - } - - return { - // sync on the appropriate keyboard event - keydown: function(evt) { return syncKeyEvent(evt, true);}, - keyup: function(evt) { return syncKeyEvent(evt, false);}, - // Call this with a non-keyboard event (such as mouse events) to use its modifier state to synchronize anyway - syncAny: function(evt) { return sync(evt);}, - - // is a shortcut modifier down? - hasShortcutModifier: function() { return hasShortcutModifier(charModifier, state); }, - // if a char modifier is down, return the keys it consists of, otherwise return null - activeCharModifier: function() { return hasCharModifier(charModifier, state) ? charModifier : null; } - }; +// Get a key ID from a keyboard event +// May be a string or an integer depending on the available properties +export function getKey(evt){ + if ('keyCode' in evt && 'key' in evt) { + return evt.key + ':' + evt.keyCode; } - - // Get a key ID from a keyboard event - // May be a string or an integer depending on the available properties - function getKey(evt){ - if ('keyCode' in evt && 'key' in evt) { - return evt.key + ':' + evt.keyCode; - } - else if ('keyCode' in evt) { - return evt.keyCode; - } - else { - return evt.key; - } + else if ('keyCode' in evt) { + return evt.keyCode; } + else { + return evt.key; + } +} - // Get the most reliable keysym value we can get from a key event - // if char/charCode is available, prefer those, otherwise fall back to key/keyCode/which - function getKeysym(evt){ - var codepoint; - if (evt.char && evt.char.length === 1) { - codepoint = evt.char.charCodeAt(); - } - else if (evt.charCode) { - codepoint = evt.charCode; - } - else if (evt.keyCode && evt.type === 'keypress') { - // IE10 stores the char code as keyCode, and has no other useful properties - codepoint = evt.keyCode; - } - if (codepoint) { - return keysyms.fromUnicode(substituteCodepoint(codepoint)); - } - // we could check evt.key here. - // Legal values are defined in http://www.w3.org/TR/DOM-Level-3-Events/#key-values-list, - // so we "just" need to map them to keysym, but AFAIK this is only available in IE10, which also provides evt.key - // so we don't *need* it yet - if (evt.keyCode) { - return keysyms.lookup(keysymFromKeyCode(evt.keyCode, evt.shiftKey)); - } - if (evt.which) { - return keysyms.lookup(keysymFromKeyCode(evt.which, evt.shiftKey)); - } +// Get the most reliable keysym value we can get from a key event +// if char/charCode is available, prefer those, otherwise fall back to key/keyCode/which +export function getKeysym(evt){ + var codepoint; + if (evt.char && evt.char.length === 1) { + codepoint = evt.char.charCodeAt(); + } + else if (evt.charCode) { + codepoint = evt.charCode; + } + else if (evt.keyCode && evt.type === 'keypress') { + // IE10 stores the char code as keyCode, and has no other useful properties + codepoint = evt.keyCode; + } + if (codepoint) { + return keysyms.fromUnicode(substituteCodepoint(codepoint)); + } + // we could check evt.key here. + // Legal values are defined in http://www.w3.org/TR/DOM-Level-3-Events/#key-values-list, + // so we "just" need to map them to keysym, but AFAIK this is only available in IE10, which also provides evt.key + // so we don't *need* it yet + if (evt.keyCode) { + return keysyms.lookup(keysymFromKeyCode(evt.keyCode, evt.shiftKey)); + } + if (evt.which) { + return keysyms.lookup(keysymFromKeyCode(evt.which, evt.shiftKey)); + } + return null; +} + +// Given a keycode, try to predict which keysym it might be. +// If the keycode is unknown, null is returned. +export function keysymFromKeyCode(keycode, shiftPressed) { + if (typeof(keycode) !== 'number') { return null; } - - // Given a keycode, try to predict which keysym it might be. - // If the keycode is unknown, null is returned. - function keysymFromKeyCode(keycode, shiftPressed) { - if (typeof(keycode) !== 'number') { - return null; - } - // won't be accurate for azerty - if (keycode >= 0x30 && keycode <= 0x39) { - return keycode; // digit - } - if (keycode >= 0x41 && keycode <= 0x5a) { - // remap to lowercase unless shift is down - return shiftPressed ? keycode : keycode + 32; // A-Z - } - if (keycode >= 0x60 && keycode <= 0x69) { - return KeyTable.XK_KP_0 + (keycode - 0x60); // numpad 0-9 - } - - switch(keycode) { - case 0x20: return KeyTable.XK_space; - case 0x6a: return KeyTable.XK_KP_Multiply; - case 0x6b: return KeyTable.XK_KP_Add; - case 0x6c: return KeyTable.XK_KP_Separator; - case 0x6d: return KeyTable.XK_KP_Subtract; - case 0x6e: return KeyTable.XK_KP_Decimal; - case 0x6f: return KeyTable.XK_KP_Divide; - case 0xbb: return KeyTable.XK_plus; - case 0xbc: return KeyTable.XK_comma; - case 0xbd: return KeyTable.XK_minus; - case 0xbe: return KeyTable.XK_period; - } - - return nonCharacterKey({keyCode: keycode}); + // won't be accurate for azerty + if (keycode >= 0x30 && keycode <= 0x39) { + return keycode; // digit + } + if (keycode >= 0x41 && keycode <= 0x5a) { + // remap to lowercase unless shift is down + return shiftPressed ? keycode : keycode + 32; // A-Z + } + if (keycode >= 0x60 && keycode <= 0x69) { + return KeyTable.XK_KP_0 + (keycode - 0x60); // numpad 0-9 } - // if the key is a known non-character key (any key which doesn't generate character data) - // return its keysym value. Otherwise return null - function nonCharacterKey(evt) { - // evt.key not implemented yet - if (!evt.keyCode) { return null; } - var keycode = evt.keyCode; - - if (keycode >= 0x70 && keycode <= 0x87) { - return KeyTable.XK_F1 + keycode - 0x70; // F1-F24 - } - switch (keycode) { - - case 8 : return KeyTable.XK_BackSpace; - case 13 : return KeyTable.XK_Return; - - case 9 : return KeyTable.XK_Tab; - - case 27 : return KeyTable.XK_Escape; - case 46 : return KeyTable.XK_Delete; - - case 36 : return KeyTable.XK_Home; - case 35 : return KeyTable.XK_End; - case 33 : return KeyTable.XK_Page_Up; - case 34 : return KeyTable.XK_Page_Down; - case 45 : return KeyTable.XK_Insert; - - case 37 : return KeyTable.XK_Left; - case 38 : return KeyTable.XK_Up; - case 39 : return KeyTable.XK_Right; - case 40 : return KeyTable.XK_Down; - - case 16 : return KeyTable.XK_Shift_L; - case 17 : return KeyTable.XK_Control_L; - case 18 : return KeyTable.XK_Alt_L; // also: Option-key on Mac - - case 224 : return KeyTable.XK_Meta_L; - case 225 : return KeyTable.XK_ISO_Level3_Shift; // AltGr - case 91 : return KeyTable.XK_Super_L; // also: Windows-key - case 92 : return KeyTable.XK_Super_R; // also: Windows-key - case 93 : return KeyTable.XK_Menu; // also: Windows-Menu, Command on Mac - default: return null; - } + switch(keycode) { + case 0x20: return KeyTable.XK_space; + case 0x6a: return KeyTable.XK_KP_Multiply; + case 0x6b: return KeyTable.XK_KP_Add; + case 0x6c: return KeyTable.XK_KP_Separator; + case 0x6d: return KeyTable.XK_KP_Subtract; + case 0x6e: return KeyTable.XK_KP_Decimal; + case 0x6f: return KeyTable.XK_KP_Divide; + case 0xbb: return KeyTable.XK_plus; + case 0xbc: return KeyTable.XK_comma; + case 0xbd: return KeyTable.XK_minus; + case 0xbe: return KeyTable.XK_period; } - KeyboardUtil.hasShortcutModifier = hasShortcutModifier; - KeyboardUtil.hasCharModifier = hasCharModifier; - KeyboardUtil.ModifierSync = ModifierSync; - KeyboardUtil.getKey = getKey; - KeyboardUtil.getKeysym = getKeysym; - KeyboardUtil.keysymFromKeyCode = keysymFromKeyCode; - KeyboardUtil.nonCharacterKey = nonCharacterKey; - KeyboardUtil.substituteCodepoint = substituteCodepoint; -})(); + return nonCharacterKey({keyCode: keycode}); +} -KeyboardUtil.QEMUKeyEventDecoder = function(modifierState, next) { +// if the key is a known non-character key (any key which doesn't generate character data) +// return its keysym value. Otherwise return null +export function nonCharacterKey(evt) { + // evt.key not implemented yet + if (!evt.keyCode) { return null; } + var keycode = evt.keyCode; + + if (keycode >= 0x70 && keycode <= 0x87) { + return KeyTable.XK_F1 + keycode - 0x70; // F1-F24 + } + switch (keycode) { + + case 8 : return KeyTable.XK_BackSpace; + case 13 : return KeyTable.XK_Return; + + case 9 : return KeyTable.XK_Tab; + + case 27 : return KeyTable.XK_Escape; + case 46 : return KeyTable.XK_Delete; + + case 36 : return KeyTable.XK_Home; + case 35 : return KeyTable.XK_End; + case 33 : return KeyTable.XK_Page_Up; + case 34 : return KeyTable.XK_Page_Down; + case 45 : return KeyTable.XK_Insert; + + case 37 : return KeyTable.XK_Left; + case 38 : return KeyTable.XK_Up; + case 39 : return KeyTable.XK_Right; + case 40 : return KeyTable.XK_Down; + + case 16 : return KeyTable.XK_Shift_L; + case 17 : return KeyTable.XK_Control_L; + case 18 : return KeyTable.XK_Alt_L; // also: Option-key on Mac + + case 224 : return KeyTable.XK_Meta_L; + case 225 : return KeyTable.XK_ISO_Level3_Shift; // AltGr + case 91 : return KeyTable.XK_Super_L; // also: Windows-key + case 92 : return KeyTable.XK_Super_R; // also: Windows-key + case 93 : return KeyTable.XK_Menu; // also: Windows-Menu, Command on Mac + default: return null; + } +} + +export function QEMUKeyEventDecoder (modifierState, next) { "use strict"; function sendAll(evts) { @@ -334,7 +317,7 @@ KeyboardUtil.QEMUKeyEventDecoder = function(modifierState, next) { var hasModifier = modifierState.hasShortcutModifier() || !!modifierState.activeCharModifier(); var isShift = evt.keyCode === 0x10 || evt.key === 'Shift'; - var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!KeyboardUtil.nonCharacterKey(evt)); + var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!nonCharacterKey(evt)); next(result); return suppress; @@ -358,7 +341,7 @@ KeyboardUtil.QEMUKeyEventDecoder = function(modifierState, next) { }; }; -KeyboardUtil.TrackQEMUKeyState = function(next) { +export function TrackQEMUKeyState (next) { "use strict"; var state = []; @@ -426,7 +409,7 @@ KeyboardUtil.TrackQEMUKeyState = function(next) { // - marks each event with an 'escape' property if a modifier was down which should be "escaped" // - generates a "stall" event in cases where it might be necessary to wait and see if a keypress event follows a keydown // This information is collected into an object which is passed to the next() function. (one call per event) -KeyboardUtil.KeyEventDecoder = function(modifierState, next) { +export function KeyEventDecoder (modifierState, next) { "use strict"; function sendAll(evts) { for (var i = 0; i < evts.length; ++i) { @@ -435,18 +418,18 @@ KeyboardUtil.KeyEventDecoder = function(modifierState, next) { } function process(evt, type) { var result = {type: type}; - var keyId = KeyboardUtil.getKey(evt); + var keyId = getKey(evt); if (keyId) { result.keyId = keyId; } - var keysym = KeyboardUtil.getKeysym(evt); + var keysym = getKeysym(evt); var hasModifier = modifierState.hasShortcutModifier() || !!modifierState.activeCharModifier(); // Is this a case where we have to decide on the keysym right away, rather than waiting for the keypress? // "special" keys like enter, tab or backspace don't send keypress events, // and some browsers don't send keypresses at all if a modifier is down - if (keysym && (type !== 'keydown' || KeyboardUtil.nonCharacterKey(evt) || hasModifier)) { + if (keysym && (type !== 'keydown' || nonCharacterKey(evt) || hasModifier)) { result.keysym = keysym; } @@ -455,11 +438,11 @@ KeyboardUtil.KeyEventDecoder = function(modifierState, next) { // Should we prevent the browser from handling the event? // Doing so on a keydown (in most browsers) prevents keypress from being generated // so only do that if we have to. - var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!KeyboardUtil.nonCharacterKey(evt)); + var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!nonCharacterKey(evt)); // If a char modifier is down on a keydown, we need to insert a stall, // so VerifyCharModifier knows to wait and see if a keypress is comnig - var stall = type === 'keydown' && modifierState.activeCharModifier() && !KeyboardUtil.nonCharacterKey(evt); + var stall = type === 'keydown' && modifierState.activeCharModifier() && !nonCharacterKey(evt); // if a char modifier is pressed, get the keys it consists of (on Windows, AltGr is equivalent to Ctrl+Alt) var active = modifierState.activeCharModifier(); @@ -513,7 +496,7 @@ KeyboardUtil.KeyEventDecoder = function(modifierState, next) { // so when used with the '2' key, Ctrl-Alt counts as a char modifier (and should be escaped), but when used with 'D', it does not. // The only way we can distinguish these cases is to wait and see if a keypress event arrives // When we receive a "stall" event, wait a few ms before processing the next keydown. If a keypress has also arrived, merge the two -KeyboardUtil.VerifyCharModifier = function(next) { +export function VerifyCharModifier (next) { "use strict"; var queue = []; var timer = null; @@ -570,7 +553,7 @@ KeyboardUtil.VerifyCharModifier = function(next) { // in some cases, a single key may produce multiple keysyms, so the corresponding keyup event must release all of these chars // key repeat events should be merged into a single entry. // Because we can't always identify which entry a keydown or keyup event corresponds to, we sometimes have to guess -KeyboardUtil.TrackKeyState = function(next) { +export function TrackKeyState (next) { "use strict"; var state = []; @@ -654,7 +637,7 @@ KeyboardUtil.TrackKeyState = function(next) { // Handles "escaping" of modifiers: if a char modifier is used to produce a keysym (such as AltGr-2 to generate an @), // then the modifier must be "undone" before sending the @, and "redone" afterwards. -KeyboardUtil.EscapeModifiers = function(next) { +export function EscapeModifiers (next) { "use strict"; return function(evt) { if (evt.type !== 'keydown' || evt.escape === undefined) { @@ -675,5 +658,3 @@ KeyboardUtil.EscapeModifiers = function(next) { /* jshint shadow: false */ }; }; - -/* [module] export default KeyboardUtil; */ diff --git a/core/input/xtscancodes.js b/core/input/xtscancodes.js index 542bcf73..43ea51b7 100644 --- a/core/input/xtscancodes.js +++ b/core/input/xtscancodes.js @@ -1,4 +1,4 @@ -var XtScancode = { +export default { "Escape": 0x0001, "Digit1": 0x0002, "Digit2": 0x0003, @@ -147,5 +147,3 @@ var XtScancode = { "LaunchMail": 0xE06C, "MediaSelect": 0xE06D, }; - -/* [module] export default XtScancode */ diff --git a/core/rfb.js b/core/rfb.js index baf5f3ce..669c817e 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -10,21 +10,23 @@ * (c) 2012 Michael Tinglof, Joe Balaz, Les Piech (Mercuri.ca) */ -/* [module] - * import Util from "./util"; - * import Display from "./display"; - * import { Keyboard, Mouse } from "./input/devices" - * import Websock from "./websock" - * import Base64 from "./base64"; - * import DES from "./des"; - * import KeyTable from "./input/keysym"; - * import XtScancode from "./input/xtscancodes"; - * import Inflator from "./inflator.mod"; - */ +import * as Log from './util/logging.js'; +import _ from './util/localization.js'; +import { decodeUTF8 } from './util/strings.js'; +import { set_defaults, make_properties } from './util/properties.js'; +import Display from "./display.js"; +import { Keyboard, Mouse } from "./input/devices.js"; +import Websock from "./websock.js"; +import Base64 from "./base64.js"; +import DES from "./des.js"; +import KeyTable from "./input/keysym.js"; +import XtScancode from "./input/xtscancodes.js"; +import Inflator from "./inflator.js"; + /*jslint white: false, browser: true */ /*global window, Util, Display, Keyboard, Mouse, Websock, Websock_native, Base64, DES, KeyTable, Inflator, XtScancode */ -/* [module] export default */ function RFB(defaults) { +export default function RFB(defaults) { "use strict"; if (!defaults) { defaults = {}; @@ -144,7 +146,7 @@ this._qemuExtKeyEventSupported = false; // set the default value on user-facing properties - Util.set_defaults(this, defaults, { + set_defaults(this, defaults, { 'target': 'null', // VNC display rendering Canvas object 'focusContainer': document, // DOM element that captures keyboard input 'encrypt': false, // Use TLS/SSL/wss encryption @@ -173,7 +175,7 @@ }); // main setup - Util.Debug(">> RFB.constructor"); + Log.Debug(">> RFB.constructor"); // populate encHandlers with bound versions Object.keys(RFB.encodingHandlers).forEach(function (encName) { @@ -193,7 +195,7 @@ this._display = new Display({target: this._target, onFlush: this._onFlush.bind(this)}); } catch (exc) { - Util.Error("Display exception: " + exc); + Log.Error("Display exception: " + exc); throw exc; } @@ -211,13 +213,13 @@ if ((this._rfb_connection_state === 'connecting') && (this._rfb_init_state === '')) { this._rfb_init_state = 'ProtocolVersion'; - Util.Debug("Starting VNC handshake"); + Log.Debug("Starting VNC handshake"); } else { this._fail("Unexpected server connection"); } }.bind(this)); this._sock.on('close', function (e) { - Util.Warn("WebSocket on-close event"); + Log.Warn("WebSocket on-close event"); var msg = ""; if (e.code) { msg = " (code: " + e.code; @@ -250,1868 +252,1855 @@ this._sock.off('close'); }.bind(this)); this._sock.on('error', function (e) { - Util.Warn("WebSocket on-error event"); + Log.Warn("WebSocket on-error event"); }); this._init_vars(); this._cleanup(); var rmode = this._display.get_render_mode(); - Util.Info("Using native WebSockets, render mode: " + rmode); + Log.Info("Using native WebSockets, render mode: " + rmode); - Util.Debug("<< RFB.constructor"); + Log.Debug("<< RFB.constructor"); }; -(function() { - var _ = Util.Localisation.get; +RFB.prototype = { + // Public methods + connect: function (host, port, password, path) { + this._rfb_host = host; + this._rfb_port = port; + this._rfb_password = (password !== undefined) ? password : ""; + this._rfb_path = (path !== undefined) ? path : ""; - RFB.prototype = { - // Public methods - connect: function (host, port, password, path) { - this._rfb_host = host; - this._rfb_port = port; - this._rfb_password = (password !== undefined) ? password : ""; - this._rfb_path = (path !== undefined) ? path : ""; + if (!this._rfb_host || !this._rfb_port) { + return this._fail( + _("Must set host and port")); + } - if (!this._rfb_host || !this._rfb_port) { - return this._fail( - _("Must set host and port")); - } + this._rfb_init_state = ''; + this._updateConnectionState('connecting'); + return true; + }, - this._rfb_init_state = ''; - this._updateConnectionState('connecting'); - return true; - }, + disconnect: function () { + this._updateConnectionState('disconnecting'); + this._sock.off('error'); + this._sock.off('message'); + this._sock.off('open'); + }, - disconnect: function () { - this._updateConnectionState('disconnecting'); - this._sock.off('error'); - this._sock.off('message'); - this._sock.off('open'); - }, + sendPassword: function (passwd) { + this._rfb_password = passwd; + setTimeout(this._init_msg.bind(this), 0); + }, - sendPassword: function (passwd) { - this._rfb_password = passwd; - setTimeout(this._init_msg.bind(this), 0); - }, + sendCtrlAltDel: function () { + if (this._rfb_connection_state !== 'connected' || this._view_only) { return false; } + Log.Info("Sending Ctrl-Alt-Del"); - sendCtrlAltDel: function () { - if (this._rfb_connection_state !== 'connected' || this._view_only) { return false; } - Util.Info("Sending Ctrl-Alt-Del"); + RFB.messages.keyEvent(this._sock, KeyTable.XK_Control_L, 1); + RFB.messages.keyEvent(this._sock, KeyTable.XK_Alt_L, 1); + RFB.messages.keyEvent(this._sock, KeyTable.XK_Delete, 1); + RFB.messages.keyEvent(this._sock, KeyTable.XK_Delete, 0); + RFB.messages.keyEvent(this._sock, KeyTable.XK_Alt_L, 0); + RFB.messages.keyEvent(this._sock, KeyTable.XK_Control_L, 0); + return true; + }, - RFB.messages.keyEvent(this._sock, KeyTable.XK_Control_L, 1); - RFB.messages.keyEvent(this._sock, KeyTable.XK_Alt_L, 1); - RFB.messages.keyEvent(this._sock, KeyTable.XK_Delete, 1); - RFB.messages.keyEvent(this._sock, KeyTable.XK_Delete, 0); - RFB.messages.keyEvent(this._sock, KeyTable.XK_Alt_L, 0); - RFB.messages.keyEvent(this._sock, KeyTable.XK_Control_L, 0); - return true; - }, + xvpOp: function (ver, op) { + if (this._rfb_xvp_ver < ver) { return false; } + Log.Info("Sending XVP operation " + op + " (version " + ver + ")"); + this._sock.send_string("\xFA\x00" + String.fromCharCode(ver) + String.fromCharCode(op)); + return true; + }, - xvpOp: function (ver, op) { - if (this._rfb_xvp_ver < ver) { return false; } - Util.Info("Sending XVP operation " + op + " (version " + ver + ")"); - this._sock.send_string("\xFA\x00" + String.fromCharCode(ver) + String.fromCharCode(op)); - return true; - }, + xvpShutdown: function () { + return this.xvpOp(1, 2); + }, - xvpShutdown: function () { - return this.xvpOp(1, 2); - }, + xvpReboot: function () { + return this.xvpOp(1, 3); + }, - xvpReboot: function () { - return this.xvpOp(1, 3); - }, + xvpReset: function () { + return this.xvpOp(1, 4); + }, - xvpReset: function () { - return this.xvpOp(1, 4); - }, + // Send a key press. If 'down' is not specified then send a down key + // followed by an up key. + sendKey: function (keysym, down) { + if (this._rfb_connection_state !== 'connected' || this._view_only) { return false; } + if (typeof down !== 'undefined') { + Log.Info("Sending keysym (" + (down ? "down" : "up") + "): " + keysym); + RFB.messages.keyEvent(this._sock, keysym, down ? 1 : 0); + } else { + Log.Info("Sending keysym (down + up): " + keysym); + RFB.messages.keyEvent(this._sock, keysym, 1); + RFB.messages.keyEvent(this._sock, keysym, 0); + } + return true; + }, - // Send a key press. If 'down' is not specified then send a down key - // followed by an up key. - sendKey: function (keysym, down) { - if (this._rfb_connection_state !== 'connected' || this._view_only) { return false; } - if (typeof down !== 'undefined') { - Util.Info("Sending keysym (" + (down ? "down" : "up") + "): " + keysym); - RFB.messages.keyEvent(this._sock, keysym, down ? 1 : 0); - } else { - Util.Info("Sending keysym (down + up): " + keysym); - RFB.messages.keyEvent(this._sock, keysym, 1); - RFB.messages.keyEvent(this._sock, keysym, 0); - } - return true; - }, - - clipboardPasteFrom: function (text) { - if (this._rfb_connection_state !== 'connected' || this._view_only) { - return; - } - RFB.messages.clientCutText(this._sock, text); - }, - - // Requests a change of remote desktop size. This message is an extension - // and may only be sent if we have received an ExtendedDesktopSize message - requestDesktopSize: function (width, height) { - if (this._rfb_connection_state !== 'connected' || - this._view_only) { - return false; - } - - if (this._supportsSetDesktopSize) { - RFB.messages.setDesktopSize(this._sock, width, height, - this._screen_id, this._screen_flags); - this._sock.flush(); - return true; - } else { - return false; - } - }, - - - // Private methods - - _connect: function () { - Util.Debug(">> RFB.connect"); - this._init_vars(); - - var uri; - if (typeof UsingSocketIO !== 'undefined') { - uri = 'http'; - } else { - uri = this._encrypt ? 'wss' : 'ws'; - } - - uri += '://' + this._rfb_host + ':' + this._rfb_port + '/' + this._rfb_path; - Util.Info("connecting to " + uri); - - try { - // WebSocket.onopen transitions to the RFB init states - this._sock.open(uri, this._wsProtocols); - } catch (e) { - if (e.name === 'SyntaxError') { - this._fail("Invalid host or port value given", e); - } else { - this._fail("Error while connecting", e); - } - } - - Util.Debug("<< RFB.connect"); - }, - - _disconnect: function () { - Util.Debug(">> RFB.disconnect"); - this._cleanup(); - this._sock.close(); - this._print_stats(); - Util.Debug("<< RFB.disconnect"); - }, - - _init_vars: function () { - // reset state - this._FBU.rects = 0; - this._FBU.subrects = 0; // RRE and HEXTILE - this._FBU.lines = 0; // RAW - this._FBU.tiles = 0; // HEXTILE - this._FBU.zlibs = []; // TIGHT zlib encoders - this._mouse_buttonMask = 0; - this._mouse_arr = []; - this._rfb_tightvnc = false; - - // Clear the per connection encoding stats - var i; - for (i = 0; i < this._encodings.length; i++) { - this._encStats[this._encodings[i][1]][0] = 0; - } - - for (i = 0; i < 4; i++) { - this._FBU.zlibs[i] = new Inflator.Inflate(); - } - }, - - _print_stats: function () { - Util.Info("Encoding stats for this connection:"); - var i, s; - for (i = 0; i < this._encodings.length; i++) { - s = this._encStats[this._encodings[i][1]]; - if (s[0] + s[1] > 0) { - Util.Info(" " + this._encodings[i][0] + ": " + s[0] + " rects"); - } - } - - Util.Info("Encoding stats since page load:"); - for (i = 0; i < this._encodings.length; i++) { - s = this._encStats[this._encodings[i][1]]; - Util.Info(" " + this._encodings[i][0] + ": " + s[1] + " rects"); - } - }, - - _cleanup: function () { - if (!this._view_only) { this._keyboard.ungrab(); } - if (!this._view_only) { this._mouse.ungrab(); } - this._display.defaultCursor(); - if (Util.get_logging() !== 'debug') { - // Show noVNC logo on load and when disconnected, unless in - // debug mode - this._display.clear(); - } - }, - - /* - * Connection states: - * connecting - * connected - * disconnecting - * disconnected - permanent state - */ - _updateConnectionState: function (state) { - var oldstate = this._rfb_connection_state; - - if (state === oldstate) { - Util.Debug("Already in state '" + state + "', ignoring"); - return; - } - - // The 'disconnected' state is permanent for each RFB object - if (oldstate === 'disconnected') { - Util.Error("Tried changing state of a disconnected RFB object"); - return; - } - - // Ensure proper transitions before doing anything - switch (state) { - case 'connected': - if (oldstate !== 'connecting') { - Util.Error("Bad transition to connected state, " + - "previous connection state: " + oldstate); - return; - } - break; - - case 'disconnected': - if (oldstate !== 'disconnecting') { - Util.Error("Bad transition to disconnected state, " + - "previous connection state: " + oldstate); - return; - } - break; - - case 'connecting': - if (oldstate !== '') { - Util.Error("Bad transition to connecting state, " + - "previous connection state: " + oldstate); - return; - } - break; - - case 'disconnecting': - if (oldstate !== 'connected' && oldstate !== 'connecting') { - Util.Error("Bad transition to disconnecting state, " + - "previous connection state: " + oldstate); - return; - } - break; - - default: - Util.Error("Unknown connection state: " + state); - return; - } - - // State change actions - - this._rfb_connection_state = state; - this._onUpdateState(this, state, oldstate); - - var smsg = "New state '" + state + "', was '" + oldstate + "'."; - Util.Debug(smsg); - - if (this._disconnTimer && state !== 'disconnecting') { - Util.Debug("Clearing disconnect timer"); - clearTimeout(this._disconnTimer); - this._disconnTimer = null; - - // make sure we don't get a double event - this._sock.off('close'); - } - - switch (state) { - case 'disconnected': - // Call onDisconnected callback after onUpdateState since - // we don't know if the UI only displays the latest message - if (this._rfb_disconnect_reason !== "") { - this._onDisconnected(this, this._rfb_disconnect_reason); - } else { - // No reason means clean disconnect - this._onDisconnected(this); - } - break; - - case 'connecting': - this._connect(); - break; - - case 'disconnecting': - this._disconnect(); - - this._disconnTimer = setTimeout(function () { - this._rfb_disconnect_reason = _("Disconnect timeout"); - this._updateConnectionState('disconnected'); - }.bind(this), this._disconnectTimeout * 1000); - break; - } - }, - - /* Print errors and disconnect - * - * The optional parameter 'details' is used for information that - * should be logged but not sent to the user interface. - */ - _fail: function (msg, details) { - var fullmsg = msg; - if (typeof details !== 'undefined') { - fullmsg = msg + " (" + details + ")"; - } - switch (this._rfb_connection_state) { - case 'disconnecting': - Util.Error("Failed when disconnecting: " + fullmsg); - break; - case 'connected': - Util.Error("Failed while connected: " + fullmsg); - break; - case 'connecting': - Util.Error("Failed when connecting: " + fullmsg); - break; - default: - Util.Error("RFB failure: " + fullmsg); - break; - } - this._rfb_disconnect_reason = msg; //This is sent to the UI - - // Transition to disconnected without waiting for socket to close - this._updateConnectionState('disconnecting'); - this._updateConnectionState('disconnected'); + clipboardPasteFrom: function (text) { + if (this._rfb_connection_state !== 'connected' || this._view_only) { return; } + RFB.messages.clientCutText(this._sock, text); + }, + // Requests a change of remote desktop size. This message is an extension + // and may only be sent if we have received an ExtendedDesktopSize message + requestDesktopSize: function (width, height) { + if (this._rfb_connection_state !== 'connected' || + this._view_only) { return false; - }, + } - /* - * Send a notification to the UI. Valid levels are: - * 'normal'|'warn'|'error' - * - * NOTE: Options could be added in the future. - * NOTE: If this function is called multiple times, remember that the - * interface could be only showing the latest notification. - */ - _notification: function(msg, level, options) { - switch (level) { - case 'normal': - case 'warn': - case 'error': - Util.Debug("Notification[" + level + "]:" + msg); - break; - default: - Util.Error("Invalid notification level: " + level); - return; - } + if (this._supportsSetDesktopSize) { + RFB.messages.setDesktopSize(this._sock, width, height, + this._screen_id, this._screen_flags); + this._sock.flush(); + return true; + } else { + return false; + } + }, - if (options) { - this._onNotification(this, msg, level, options); + + // Private methods + + _connect: function () { + Log.Debug(">> RFB.connect"); + this._init_vars(); + + var uri; + if (typeof UsingSocketIO !== 'undefined') { + uri = 'http'; + } else { + uri = this._encrypt ? 'wss' : 'ws'; + } + + uri += '://' + this._rfb_host + ':' + this._rfb_port + '/' + this._rfb_path; + Log.Info("connecting to " + uri); + + try { + // WebSocket.onopen transitions to the RFB init states + this._sock.open(uri, this._wsProtocols); + } catch (e) { + if (e.name === 'SyntaxError') { + this._fail("Invalid host or port value given", e); } else { - this._onNotification(this, msg, level); + this._fail("Error while connecting", e); } - }, + } - _handle_message: function () { - if (this._sock.rQlen() === 0) { - Util.Warn("handle_message called on an empty receive queue"); + Log.Debug("<< RFB.connect"); + }, + + _disconnect: function () { + Log.Debug(">> RFB.disconnect"); + this._cleanup(); + this._sock.close(); + this._print_stats(); + Log.Debug("<< RFB.disconnect"); + }, + + _init_vars: function () { + // reset state + this._FBU.rects = 0; + this._FBU.subrects = 0; // RRE and HEXTILE + this._FBU.lines = 0; // RAW + this._FBU.tiles = 0; // HEXTILE + this._FBU.zlibs = []; // TIGHT zlib encoders + this._mouse_buttonMask = 0; + this._mouse_arr = []; + this._rfb_tightvnc = false; + + // Clear the per connection encoding stats + var i; + for (i = 0; i < this._encodings.length; i++) { + this._encStats[this._encodings[i][1]][0] = 0; + } + + for (i = 0; i < 4; i++) { + this._FBU.zlibs[i] = new Inflator(); + } + }, + + _print_stats: function () { + Log.Info("Encoding stats for this connection:"); + var i, s; + for (i = 0; i < this._encodings.length; i++) { + s = this._encStats[this._encodings[i][1]]; + if (s[0] + s[1] > 0) { + Log.Info(" " + this._encodings[i][0] + ": " + s[0] + " rects"); + } + } + + Log.Info("Encoding stats since page load:"); + for (i = 0; i < this._encodings.length; i++) { + s = this._encStats[this._encodings[i][1]]; + Log.Info(" " + this._encodings[i][0] + ": " + s[1] + " rects"); + } + }, + + _cleanup: function () { + if (!this._view_only) { this._keyboard.ungrab(); } + if (!this._view_only) { this._mouse.ungrab(); } + this._display.defaultCursor(); + if (Log.get_logging() !== 'debug') { + // Show noVNC logo on load and when disconnected, unless in + // debug mode + this._display.clear(); + } + }, + + /* + * Connection states: + * connecting + * connected + * disconnecting + * disconnected - permanent state + */ + _updateConnectionState: function (state) { + var oldstate = this._rfb_connection_state; + + if (state === oldstate) { + Log.Debug("Already in state '" + state + "', ignoring"); + return; + } + + // The 'disconnected' state is permanent for each RFB object + if (oldstate === 'disconnected') { + Log.Error("Tried changing state of a disconnected RFB object"); + return; + } + + // Ensure proper transitions before doing anything + switch (state) { + case 'connected': + if (oldstate !== 'connecting') { + Log.Error("Bad transition to connected state, " + + "previous connection state: " + oldstate); + return; + } + break; + + case 'disconnected': + if (oldstate !== 'disconnecting') { + Log.Error("Bad transition to disconnected state, " + + "previous connection state: " + oldstate); + return; + } + break; + + case 'connecting': + if (oldstate !== '') { + Log.Error("Bad transition to connecting state, " + + "previous connection state: " + oldstate); + return; + } + break; + + case 'disconnecting': + if (oldstate !== 'connected' && oldstate !== 'connecting') { + Log.Error("Bad transition to disconnecting state, " + + "previous connection state: " + oldstate); + return; + } + break; + + default: + Log.Error("Unknown connection state: " + state); return; - } + } - switch (this._rfb_connection_state) { - case 'disconnected': - Util.Error("Got data while disconnected"); - break; - case 'connected': - while (true) { - if (this._flushing) { - break; - } - if (!this._normal_msg()) { - break; - } - if (this._sock.rQlen() === 0) { - break; - } - } - break; - default: - this._init_msg(); - break; - } - }, + // State change actions - _handleKeyPress: function (keyevent) { - if (this._view_only) { return; } // View only, skip keyboard, events + this._rfb_connection_state = state; + this._onUpdateState(this, state, oldstate); - var down = (keyevent.type == 'keydown'); - if (this._qemuExtKeyEventSupported) { - var scancode = XtScancode[keyevent.code]; - if (scancode) { - var keysym = keyevent.keysym; - RFB.messages.QEMUExtendedKeyEvent(this._sock, keysym, down, scancode); + var smsg = "New state '" + state + "', was '" + oldstate + "'."; + Log.Debug(smsg); + + if (this._disconnTimer && state !== 'disconnecting') { + Log.Debug("Clearing disconnect timer"); + clearTimeout(this._disconnTimer); + this._disconnTimer = null; + + // make sure we don't get a double event + this._sock.off('close'); + } + + switch (state) { + case 'disconnected': + // Call onDisconnected callback after onUpdateState since + // we don't know if the UI only displays the latest message + if (this._rfb_disconnect_reason !== "") { + this._onDisconnected(this, this._rfb_disconnect_reason); } else { - Util.Error('Unable to find a xt scancode for code = ' + keyevent.code); + // No reason means clean disconnect + this._onDisconnected(this); } - } else { - keysym = keyevent.keysym.keysym; - RFB.messages.keyEvent(this._sock, keysym, down); - } - }, + break; - _handleMouseButton: function (x, y, down, bmask) { - if (down) { - this._mouse_buttonMask |= bmask; - } else { - this._mouse_buttonMask ^= bmask; - } + case 'connecting': + this._connect(); + break; - if (this._viewportDrag) { - if (down && !this._viewportDragging) { - this._viewportDragging = true; - this._viewportDragPos = {'x': x, 'y': y}; + case 'disconnecting': + this._disconnect(); - // Skip sending mouse events - return; - } else { - this._viewportDragging = false; + this._disconnTimer = setTimeout(function () { + this._rfb_disconnect_reason = _("Disconnect timeout"); + this._updateConnectionState('disconnected'); + }.bind(this), this._disconnectTimeout * 1000); + break; + } + }, - // If the viewport didn't actually move, then treat as a mouse click event - // Send the button down event here, as the button up event is sent at the end of this function - if (!this._viewportHasMoved && !this._view_only) { - RFB.messages.pointerEvent(this._sock, this._display.absX(x), this._display.absY(y), bmask); + /* Print errors and disconnect + * + * The optional parameter 'details' is used for information that + * should be logged but not sent to the user interface. + */ + _fail: function (msg, details) { + var fullmsg = msg; + if (typeof details !== 'undefined') { + fullmsg = msg + " (" + details + ")"; + } + switch (this._rfb_connection_state) { + case 'disconnecting': + Log.Error("Failed when disconnecting: " + fullmsg); + break; + case 'connected': + Log.Error("Failed while connected: " + fullmsg); + break; + case 'connecting': + Log.Error("Failed when connecting: " + fullmsg); + break; + default: + Log.Error("RFB failure: " + fullmsg); + break; + } + this._rfb_disconnect_reason = msg; //This is sent to the UI + + // Transition to disconnected without waiting for socket to close + this._updateConnectionState('disconnecting'); + this._updateConnectionState('disconnected'); + + return false; + }, + + /* + * Send a notification to the UI. Valid levels are: + * 'normal'|'warn'|'error' + * + * NOTE: Options could be added in the future. + * NOTE: If this function is called multiple times, remember that the + * interface could be only showing the latest notification. + */ + _notification: function(msg, level, options) { + switch (level) { + case 'normal': + case 'warn': + case 'error': + Log.Debug("Notification[" + level + "]:" + msg); + break; + default: + Log.Error("Invalid notification level: " + level); + return; + } + + if (options) { + this._onNotification(this, msg, level, options); + } else { + this._onNotification(this, msg, level); + } + }, + + _handle_message: function () { + if (this._sock.rQlen() === 0) { + Log.Warn("handle_message called on an empty receive queue"); + return; + } + + switch (this._rfb_connection_state) { + case 'disconnected': + Log.Error("Got data while disconnected"); + break; + case 'connected': + while (true) { + if (this._flushing) { + break; + } + if (!this._normal_msg()) { + break; + } + if (this._sock.rQlen() === 0) { + break; } - this._viewportHasMoved = false; } + break; + default: + this._init_msg(); + break; + } + }, + + _handleKeyPress: function (keyevent) { + if (this._view_only) { return; } // View only, skip keyboard, events + + var down = (keyevent.type == 'keydown'); + if (this._qemuExtKeyEventSupported) { + var scancode = XtScancode[keyevent.code]; + if (scancode) { + var keysym = keyevent.keysym; + RFB.messages.QEMUExtendedKeyEvent(this._sock, keysym, down, scancode); + } else { + Log.Error('Unable to find a xt scancode for code = ' + keyevent.code); } + } else { + keysym = keyevent.keysym.keysym; + RFB.messages.keyEvent(this._sock, keysym, down); + } + }, - if (this._view_only) { return; } // View only, skip mouse events + _handleMouseButton: function (x, y, down, bmask) { + if (down) { + this._mouse_buttonMask |= bmask; + } else { + this._mouse_buttonMask ^= bmask; + } - if (this._rfb_connection_state !== 'connected') { return; } - RFB.messages.pointerEvent(this._sock, this._display.absX(x), this._display.absY(y), this._mouse_buttonMask); - }, - - _handleMouseMove: function (x, y) { - if (this._viewportDragging) { - var deltaX = this._viewportDragPos.x - x; - var deltaY = this._viewportDragPos.y - y; - - // The goal is to trigger on a certain physical width, the - // devicePixelRatio brings us a bit closer but is not optimal. - var dragThreshold = 10 * (window.devicePixelRatio || 1); - - if (this._viewportHasMoved || (Math.abs(deltaX) > dragThreshold || - Math.abs(deltaY) > dragThreshold)) { - this._viewportHasMoved = true; - - this._viewportDragPos = {'x': x, 'y': y}; - this._display.viewportChangePos(deltaX, deltaY); - } + if (this._viewportDrag) { + if (down && !this._viewportDragging) { + this._viewportDragging = true; + this._viewportDragPos = {'x': x, 'y': y}; // Skip sending mouse events return; - } - - if (this._view_only) { return; } // View only, skip mouse events - - if (this._rfb_connection_state !== 'connected') { return; } - RFB.messages.pointerEvent(this._sock, this._display.absX(x), this._display.absY(y), this._mouse_buttonMask); - }, - - // Message Handlers - - _negotiate_protocol_version: function () { - if (this._sock.rQlen() < 12) { - return this._fail("Error while negotiating with server", - "Incomplete protocol version"); - } - - var sversion = this._sock.rQshiftStr(12).substr(4, 7); - Util.Info("Server ProtocolVersion: " + sversion); - var is_repeater = 0; - switch (sversion) { - case "000.000": // UltraVNC repeater - is_repeater = 1; - break; - case "003.003": - case "003.006": // UltraVNC - case "003.889": // Apple Remote Desktop - this._rfb_version = 3.3; - break; - case "003.007": - this._rfb_version = 3.7; - break; - case "003.008": - case "004.000": // Intel AMT KVM - case "004.001": // RealVNC 4.6 - case "005.000": // RealVNC 5.3 - this._rfb_version = 3.8; - break; - default: - return this._fail("Unsupported server", - "Invalid server version: " + sversion); - } - - if (is_repeater) { - var repeaterID = this._repeaterID; - while (repeaterID.length < 250) { - repeaterID += "\0"; - } - this._sock.send_string(repeaterID); - return true; - } - - if (this._rfb_version > this._rfb_max_version) { - this._rfb_version = this._rfb_max_version; - } - - var cversion = "00" + parseInt(this._rfb_version, 10) + - ".00" + ((this._rfb_version * 10) % 10); - this._sock.send_string("RFB " + cversion + "\n"); - Util.Debug('Sent ProtocolVersion: ' + cversion); - - this._rfb_init_state = 'Security'; - }, - - _negotiate_security: function () { - if (this._rfb_version >= 3.7) { - // Server sends supported list, client decides - var num_types = this._sock.rQshift8(); - if (this._sock.rQwait("security type", num_types, 1)) { return false; } - - if (num_types === 0) { - var strlen = this._sock.rQshift32(); - var reason = this._sock.rQshiftStr(strlen); - return this._fail("Error while negotiating with server", - "Security failure: " + reason); - } - - var types = this._sock.rQshiftBytes(num_types); - Util.Debug("Server security types: " + types); - - // Polyfill since IE and PhantomJS doesn't have - // TypedArray.includes() - function includes(item, array) { - for (var i = 0; i < array.length; i++) { - if (array[i] === item) { - return true; - } - } - return false; - } - - // Look for each auth in preferred order - this._rfb_auth_scheme = 0; - if (includes(1, types)) { - this._rfb_auth_scheme = 1; // None - } else if (includes(22, types)) { - this._rfb_auth_scheme = 22; // XVP - } else if (includes(16, types)) { - this._rfb_auth_scheme = 16; // Tight - } else if (includes(2, types)) { - this._rfb_auth_scheme = 2; // VNC Auth - } else { - return this._fail("Unsupported server", - "Unsupported security types: " + types); - } - - this._sock.send([this._rfb_auth_scheme]); } else { - // Server decides - if (this._sock.rQwait("security scheme", 4)) { return false; } - this._rfb_auth_scheme = this._sock.rQshift32(); - } + this._viewportDragging = false; - this._rfb_init_state = 'Authentication'; - Util.Debug('Authenticating using scheme: ' + this._rfb_auth_scheme); - - return this._init_msg(); // jump to authentication - }, - - // authentication - _negotiate_xvp_auth: function () { - var xvp_sep = this._xvp_password_sep; - var xvp_auth = this._rfb_password.split(xvp_sep); - if (xvp_auth.length < 3) { - var msg = 'XVP credentials required (user' + xvp_sep + - 'target' + xvp_sep + 'password) -- got only ' + this._rfb_password; - this._onPasswordRequired(this, msg); - return false; - } - - var xvp_auth_str = String.fromCharCode(xvp_auth[0].length) + - String.fromCharCode(xvp_auth[1].length) + - xvp_auth[0] + - xvp_auth[1]; - this._sock.send_string(xvp_auth_str); - this._rfb_password = xvp_auth.slice(2).join(xvp_sep); - this._rfb_auth_scheme = 2; - return this._negotiate_authentication(); - }, - - _negotiate_std_vnc_auth: function () { - if (this._rfb_password.length === 0) { - this._onPasswordRequired(this); - return false; - } - - if (this._sock.rQwait("auth challenge", 16)) { return false; } - - // TODO(directxman12): make genDES not require an Array - var challenge = Array.prototype.slice.call(this._sock.rQshiftBytes(16)); - var response = RFB.genDES(this._rfb_password, challenge); - this._sock.send(response); - this._rfb_init_state = "SecurityResult"; - return true; - }, - - _negotiate_tight_tunnels: function (numTunnels) { - var clientSupportedTunnelTypes = { - 0: { vendor: 'TGHT', signature: 'NOTUNNEL' } - }; - var serverSupportedTunnelTypes = {}; - // receive tunnel capabilities - for (var i = 0; i < numTunnels; i++) { - var cap_code = this._sock.rQshift32(); - var cap_vendor = this._sock.rQshiftStr(4); - var cap_signature = this._sock.rQshiftStr(8); - serverSupportedTunnelTypes[cap_code] = { vendor: cap_vendor, signature: cap_signature }; - } - - // choose the notunnel type - if (serverSupportedTunnelTypes[0]) { - if (serverSupportedTunnelTypes[0].vendor != clientSupportedTunnelTypes[0].vendor || - serverSupportedTunnelTypes[0].signature != clientSupportedTunnelTypes[0].signature) { - return this._fail("Unsupported server", - "Client's tunnel type had the incorrect " + - "vendor or signature"); + // If the viewport didn't actually move, then treat as a mouse click event + // Send the button down event here, as the button up event is sent at the end of this function + if (!this._viewportHasMoved && !this._view_only) { + RFB.messages.pointerEvent(this._sock, this._display.absX(x), this._display.absY(y), bmask); } - this._sock.send([0, 0, 0, 0]); // use NOTUNNEL - return false; // wait until we receive the sub auth count to continue + this._viewportHasMoved = false; + } + } + + if (this._view_only) { return; } // View only, skip mouse events + + if (this._rfb_connection_state !== 'connected') { return; } + RFB.messages.pointerEvent(this._sock, this._display.absX(x), this._display.absY(y), this._mouse_buttonMask); + }, + + _handleMouseMove: function (x, y) { + if (this._viewportDragging) { + var deltaX = this._viewportDragPos.x - x; + var deltaY = this._viewportDragPos.y - y; + + // The goal is to trigger on a certain physical width, the + // devicePixelRatio brings us a bit closer but is not optimal. + var dragThreshold = 10 * (window.devicePixelRatio || 1); + + if (this._viewportHasMoved || (Math.abs(deltaX) > dragThreshold || + Math.abs(deltaY) > dragThreshold)) { + this._viewportHasMoved = true; + + this._viewportDragPos = {'x': x, 'y': y}; + this._display.viewportChangePos(deltaX, deltaY); + } + + // Skip sending mouse events + return; + } + + if (this._view_only) { return; } // View only, skip mouse events + + if (this._rfb_connection_state !== 'connected') { return; } + RFB.messages.pointerEvent(this._sock, this._display.absX(x), this._display.absY(y), this._mouse_buttonMask); + }, + + // Message Handlers + + _negotiate_protocol_version: function () { + if (this._sock.rQlen() < 12) { + return this._fail("Error while negotiating with server", + "Incomplete protocol version"); + } + + var sversion = this._sock.rQshiftStr(12).substr(4, 7); + Log.Info("Server ProtocolVersion: " + sversion); + var is_repeater = 0; + switch (sversion) { + case "000.000": // UltraVNC repeater + is_repeater = 1; + break; + case "003.003": + case "003.006": // UltraVNC + case "003.889": // Apple Remote Desktop + this._rfb_version = 3.3; + break; + case "003.007": + this._rfb_version = 3.7; + break; + case "003.008": + case "004.000": // Intel AMT KVM + case "004.001": // RealVNC 4.6 + case "005.000": // RealVNC 5.3 + this._rfb_version = 3.8; + break; + default: + return this._fail("Unsupported server", + "Invalid server version: " + sversion); + } + + if (is_repeater) { + var repeaterID = this._repeaterID; + while (repeaterID.length < 250) { + repeaterID += "\0"; + } + this._sock.send_string(repeaterID); + return true; + } + + if (this._rfb_version > this._rfb_max_version) { + this._rfb_version = this._rfb_max_version; + } + + var cversion = "00" + parseInt(this._rfb_version, 10) + + ".00" + ((this._rfb_version * 10) % 10); + this._sock.send_string("RFB " + cversion + "\n"); + Log.Debug('Sent ProtocolVersion: ' + cversion); + + this._rfb_init_state = 'Security'; + }, + + _negotiate_security: function () { + // Polyfill since IE and PhantomJS doesn't have + // TypedArray.includes() + function includes(item, array) { + for (var i = 0; i < array.length; i++) { + if (array[i] === item) { + return true; + } + } + return false; + } + + if (this._rfb_version >= 3.7) { + // Server sends supported list, client decides + var num_types = this._sock.rQshift8(); + if (this._sock.rQwait("security type", num_types, 1)) { return false; } + + if (num_types === 0) { + var strlen = this._sock.rQshift32(); + var reason = this._sock.rQshiftStr(strlen); + return this._fail("Error while negotiating with server", + "Security failure: " + reason); + } + + var types = this._sock.rQshiftBytes(num_types); + Log.Debug("Server security types: " + types); + + // Look for each auth in preferred order + this._rfb_auth_scheme = 0; + if (includes(1, types)) { + this._rfb_auth_scheme = 1; // None + } else if (includes(22, types)) { + this._rfb_auth_scheme = 22; // XVP + } else if (includes(16, types)) { + this._rfb_auth_scheme = 16; // Tight + } else if (includes(2, types)) { + this._rfb_auth_scheme = 2; // VNC Auth } else { return this._fail("Unsupported server", - "Server wanted tunnels, but doesn't support " + - "the notunnel type"); - } - }, - - _negotiate_tight_auth: function () { - if (!this._rfb_tightvnc) { // first pass, do the tunnel negotiation - if (this._sock.rQwait("num tunnels", 4)) { return false; } - var numTunnels = this._sock.rQshift32(); - if (numTunnels > 0 && this._sock.rQwait("tunnel capabilities", 16 * numTunnels, 4)) { return false; } - - this._rfb_tightvnc = true; - - if (numTunnels > 0) { - this._negotiate_tight_tunnels(numTunnels); - return false; // wait until we receive the sub auth to continue - } + "Unsupported security types: " + types); } - // second pass, do the sub-auth negotiation - if (this._sock.rQwait("sub auth count", 4)) { return false; } - var subAuthCount = this._sock.rQshift32(); - if (subAuthCount === 0) { // empty sub-auth list received means 'no auth' subtype selected - this._rfb_init_state = 'SecurityResult'; - return true; + this._sock.send([this._rfb_auth_scheme]); + } else { + // Server decides + if (this._sock.rQwait("security scheme", 4)) { return false; } + this._rfb_auth_scheme = this._sock.rQshift32(); + } + + this._rfb_init_state = 'Authentication'; + Log.Debug('Authenticating using scheme: ' + this._rfb_auth_scheme); + + return this._init_msg(); // jump to authentication + }, + + // authentication + _negotiate_xvp_auth: function () { + var xvp_sep = this._xvp_password_sep; + var xvp_auth = this._rfb_password.split(xvp_sep); + if (xvp_auth.length < 3) { + var msg = 'XVP credentials required (user' + xvp_sep + + 'target' + xvp_sep + 'password) -- got only ' + this._rfb_password; + this._onPasswordRequired(this, msg); + return false; + } + + var xvp_auth_str = String.fromCharCode(xvp_auth[0].length) + + String.fromCharCode(xvp_auth[1].length) + + xvp_auth[0] + + xvp_auth[1]; + this._sock.send_string(xvp_auth_str); + this._rfb_password = xvp_auth.slice(2).join(xvp_sep); + this._rfb_auth_scheme = 2; + return this._negotiate_authentication(); + }, + + _negotiate_std_vnc_auth: function () { + if (this._rfb_password.length === 0) { + this._onPasswordRequired(this); + return false; + } + + if (this._sock.rQwait("auth challenge", 16)) { return false; } + + // TODO(directxman12): make genDES not require an Array + var challenge = Array.prototype.slice.call(this._sock.rQshiftBytes(16)); + var response = RFB.genDES(this._rfb_password, challenge); + this._sock.send(response); + this._rfb_init_state = "SecurityResult"; + return true; + }, + + _negotiate_tight_tunnels: function (numTunnels) { + var clientSupportedTunnelTypes = { + 0: { vendor: 'TGHT', signature: 'NOTUNNEL' } + }; + var serverSupportedTunnelTypes = {}; + // receive tunnel capabilities + for (var i = 0; i < numTunnels; i++) { + var cap_code = this._sock.rQshift32(); + var cap_vendor = this._sock.rQshiftStr(4); + var cap_signature = this._sock.rQshiftStr(8); + serverSupportedTunnelTypes[cap_code] = { vendor: cap_vendor, signature: cap_signature }; + } + + // choose the notunnel type + if (serverSupportedTunnelTypes[0]) { + if (serverSupportedTunnelTypes[0].vendor != clientSupportedTunnelTypes[0].vendor || + serverSupportedTunnelTypes[0].signature != clientSupportedTunnelTypes[0].signature) { + return this._fail("Unsupported server", + "Client's tunnel type had the incorrect " + + "vendor or signature"); } - - if (this._sock.rQwait("sub auth capabilities", 16 * subAuthCount, 4)) { return false; } - - var clientSupportedTypes = { - 'STDVNOAUTH__': 1, - 'STDVVNCAUTH_': 2 - }; - - var serverSupportedTypes = []; - - for (var i = 0; i < subAuthCount; i++) { - var capNum = this._sock.rQshift32(); - var capabilities = this._sock.rQshiftStr(12); - serverSupportedTypes.push(capabilities); - } - - for (var authType in clientSupportedTypes) { - if (serverSupportedTypes.indexOf(authType) != -1) { - this._sock.send([0, 0, 0, clientSupportedTypes[authType]]); - - switch (authType) { - case 'STDVNOAUTH__': // no auth - this._rfb_init_state = 'SecurityResult'; - return true; - case 'STDVVNCAUTH_': // VNC auth - this._rfb_auth_scheme = 2; - return this._init_msg(); - default: - return this._fail("Unsupported server", - "Unsupported tiny auth scheme: " + - authType); - } - } - } - + this._sock.send([0, 0, 0, 0]); // use NOTUNNEL + return false; // wait until we receive the sub auth count to continue + } else { return this._fail("Unsupported server", - "No supported sub-auth types!"); - }, + "Server wanted tunnels, but doesn't support " + + "the notunnel type"); + } + }, - _negotiate_authentication: function () { - switch (this._rfb_auth_scheme) { - case 0: // connection failed - if (this._sock.rQwait("auth reason", 4)) { return false; } - var strlen = this._sock.rQshift32(); - var reason = this._sock.rQshiftStr(strlen); - return this._fail("Authentication failure", reason); + _negotiate_tight_auth: function () { + if (!this._rfb_tightvnc) { // first pass, do the tunnel negotiation + if (this._sock.rQwait("num tunnels", 4)) { return false; } + var numTunnels = this._sock.rQshift32(); + if (numTunnels > 0 && this._sock.rQwait("tunnel capabilities", 16 * numTunnels, 4)) { return false; } - case 1: // no auth - if (this._rfb_version >= 3.8) { + this._rfb_tightvnc = true; + + if (numTunnels > 0) { + this._negotiate_tight_tunnels(numTunnels); + return false; // wait until we receive the sub auth to continue + } + } + + // second pass, do the sub-auth negotiation + if (this._sock.rQwait("sub auth count", 4)) { return false; } + var subAuthCount = this._sock.rQshift32(); + if (subAuthCount === 0) { // empty sub-auth list received means 'no auth' subtype selected + this._rfb_init_state = 'SecurityResult'; + return true; + } + + if (this._sock.rQwait("sub auth capabilities", 16 * subAuthCount, 4)) { return false; } + + var clientSupportedTypes = { + 'STDVNOAUTH__': 1, + 'STDVVNCAUTH_': 2 + }; + + var serverSupportedTypes = []; + + for (var i = 0; i < subAuthCount; i++) { + var capNum = this._sock.rQshift32(); + var capabilities = this._sock.rQshiftStr(12); + serverSupportedTypes.push(capabilities); + } + + for (var authType in clientSupportedTypes) { + if (serverSupportedTypes.indexOf(authType) != -1) { + this._sock.send([0, 0, 0, clientSupportedTypes[authType]]); + + switch (authType) { + case 'STDVNOAUTH__': // no auth this._rfb_init_state = 'SecurityResult'; return true; - } - this._rfb_init_state = 'ClientInitialisation'; - return this._init_msg(); - - case 22: // XVP auth - return this._negotiate_xvp_auth(); - - case 2: // VNC authentication - return this._negotiate_std_vnc_auth(); - - case 16: // TightVNC Security Type - return this._negotiate_tight_auth(); - - default: - return this._fail("Unsupported server", - "Unsupported auth scheme: " + - this._rfb_auth_scheme); + case 'STDVVNCAUTH_': // VNC auth + this._rfb_auth_scheme = 2; + return this._init_msg(); + default: + return this._fail("Unsupported server", + "Unsupported tiny auth scheme: " + + authType); + } } - }, + } - _handle_security_result: function () { - if (this._sock.rQwait('VNC auth response ', 4)) { return false; } - switch (this._sock.rQshift32()) { - case 0: // OK - this._rfb_init_state = 'ClientInitialisation'; - Util.Debug('Authentication OK'); - return this._init_msg(); - case 1: // failed - if (this._rfb_version >= 3.8) { - var length = this._sock.rQshift32(); - if (this._sock.rQwait("SecurityResult reason", length, 8)) { return false; } - var reason = this._sock.rQshiftStr(length); - return this._fail("Authentication failure", reason); - } else { - return this._fail("Authentication failure"); - } - return false; - case 2: - return this._fail("Too many authentication attempts"); - default: - return this._fail("Unsupported server", - "Unknown SecurityResult"); - } - }, + return this._fail("Unsupported server", + "No supported sub-auth types!"); + }, - _negotiate_server_init: function () { - if (this._sock.rQwait("server initialization", 24)) { return false; } + _negotiate_authentication: function () { + switch (this._rfb_auth_scheme) { + case 0: // connection failed + if (this._sock.rQwait("auth reason", 4)) { return false; } + var strlen = this._sock.rQshift32(); + var reason = this._sock.rQshiftStr(strlen); + return this._fail("Authentication failure", reason); - /* Screen size */ - this._fb_width = this._sock.rQshift16(); - this._fb_height = this._sock.rQshift16(); - this._destBuff = new Uint8Array(this._fb_width * this._fb_height * 4); + case 1: // no auth + if (this._rfb_version >= 3.8) { + this._rfb_init_state = 'SecurityResult'; + return true; + } + this._rfb_init_state = 'ClientInitialisation'; + return this._init_msg(); - /* PIXEL_FORMAT */ - var bpp = this._sock.rQshift8(); - var depth = this._sock.rQshift8(); - var big_endian = this._sock.rQshift8(); - var true_color = this._sock.rQshift8(); + case 22: // XVP auth + return this._negotiate_xvp_auth(); - var red_max = this._sock.rQshift16(); - var green_max = this._sock.rQshift16(); - var blue_max = this._sock.rQshift16(); - var red_shift = this._sock.rQshift8(); - var green_shift = this._sock.rQshift8(); - var blue_shift = this._sock.rQshift8(); - this._sock.rQskipBytes(3); // padding + case 2: // VNC authentication + return this._negotiate_std_vnc_auth(); - // NB(directxman12): we don't want to call any callbacks or print messages until - // *after* we're past the point where we could backtrack + case 16: // TightVNC Security Type + return this._negotiate_tight_auth(); - /* Connection name/title */ - var name_length = this._sock.rQshift32(); - if (this._sock.rQwait('server init name', name_length, 24)) { return false; } - this._fb_name = Util.decodeUTF8(this._sock.rQshiftStr(name_length)); + default: + return this._fail("Unsupported server", + "Unsupported auth scheme: " + + this._rfb_auth_scheme); + } + }, - if (this._rfb_tightvnc) { - if (this._sock.rQwait('TightVNC extended server init header', 8, 24 + name_length)) { return false; } - // In TightVNC mode, ServerInit message is extended - var numServerMessages = this._sock.rQshift16(); - var numClientMessages = this._sock.rQshift16(); - var numEncodings = this._sock.rQshift16(); - this._sock.rQskipBytes(2); // padding + _handle_security_result: function () { + if (this._sock.rQwait('VNC auth response ', 4)) { return false; } + switch (this._sock.rQshift32()) { + case 0: // OK + this._rfb_init_state = 'ClientInitialisation'; + Log.Debug('Authentication OK'); + return this._init_msg(); + case 1: // failed + if (this._rfb_version >= 3.8) { + var length = this._sock.rQshift32(); + if (this._sock.rQwait("SecurityResult reason", length, 8)) { return false; } + var reason = this._sock.rQshiftStr(length); + return this._fail("Authentication failure", reason); + } else { + return this._fail("Authentication failure"); + } + return false; + case 2: + return this._fail("Too many authentication attempts"); + default: + return this._fail("Unsupported server", + "Unknown SecurityResult"); + } + }, - var totalMessagesLength = (numServerMessages + numClientMessages + numEncodings) * 16; - if (this._sock.rQwait('TightVNC extended server init header', totalMessagesLength, 32 + name_length)) { return false; } + _negotiate_server_init: function () { + if (this._sock.rQwait("server initialization", 24)) { return false; } - // we don't actually do anything with the capability information that TIGHT sends, - // so we just skip the all of this. + /* Screen size */ + this._fb_width = this._sock.rQshift16(); + this._fb_height = this._sock.rQshift16(); + this._destBuff = new Uint8Array(this._fb_width * this._fb_height * 4); - // TIGHT server message capabilities - this._sock.rQskipBytes(16 * numServerMessages); + /* PIXEL_FORMAT */ + var bpp = this._sock.rQshift8(); + var depth = this._sock.rQshift8(); + var big_endian = this._sock.rQshift8(); + var true_color = this._sock.rQshift8(); - // TIGHT client message capabilities - this._sock.rQskipBytes(16 * numClientMessages); + var red_max = this._sock.rQshift16(); + var green_max = this._sock.rQshift16(); + var blue_max = this._sock.rQshift16(); + var red_shift = this._sock.rQshift8(); + var green_shift = this._sock.rQshift8(); + var blue_shift = this._sock.rQshift8(); + this._sock.rQskipBytes(3); // padding - // TIGHT encoding capabilities - this._sock.rQskipBytes(16 * numEncodings); - } + // NB(directxman12): we don't want to call any callbacks or print messages until + // *after* we're past the point where we could backtrack - // NB(directxman12): these are down here so that we don't run them multiple times - // if we backtrack - Util.Info("Screen: " + this._fb_width + "x" + this._fb_height + - ", bpp: " + bpp + ", depth: " + depth + - ", big_endian: " + big_endian + - ", true_color: " + true_color + - ", red_max: " + red_max + - ", green_max: " + green_max + - ", blue_max: " + blue_max + - ", red_shift: " + red_shift + - ", green_shift: " + green_shift + - ", blue_shift: " + blue_shift); + /* Connection name/title */ + var name_length = this._sock.rQshift32(); + if (this._sock.rQwait('server init name', name_length, 24)) { return false; } + this._fb_name = decodeUTF8(this._sock.rQshiftStr(name_length)); - if (big_endian !== 0) { - Util.Warn("Server native endian is not little endian"); - } + if (this._rfb_tightvnc) { + if (this._sock.rQwait('TightVNC extended server init header', 8, 24 + name_length)) { return false; } + // In TightVNC mode, ServerInit message is extended + var numServerMessages = this._sock.rQshift16(); + var numClientMessages = this._sock.rQshift16(); + var numEncodings = this._sock.rQshift16(); + this._sock.rQskipBytes(2); // padding - if (red_shift !== 16) { - Util.Warn("Server native red-shift is not 16"); - } + var totalMessagesLength = (numServerMessages + numClientMessages + numEncodings) * 16; + if (this._sock.rQwait('TightVNC extended server init header', totalMessagesLength, 32 + name_length)) { return false; } - if (blue_shift !== 0) { - Util.Warn("Server native blue-shift is not 0"); - } + // we don't actually do anything with the capability information that TIGHT sends, + // so we just skip the all of this. - // we're past the point where we could backtrack, so it's safe to call this - this._onDesktopName(this, this._fb_name); + // TIGHT server message capabilities + this._sock.rQskipBytes(16 * numServerMessages); - if (this._true_color && this._fb_name === "Intel(r) AMT KVM") { - Util.Warn("Intel AMT KVM only supports 8/16 bit depths. Disabling true color"); - this._true_color = false; - } + // TIGHT client message capabilities + this._sock.rQskipBytes(16 * numClientMessages); - this._display.set_true_color(this._true_color); - this._display.resize(this._fb_width, this._fb_height); - this._onFBResize(this, this._fb_width, this._fb_height); + // TIGHT encoding capabilities + this._sock.rQskipBytes(16 * numEncodings); + } - if (!this._view_only) { this._keyboard.grab(); } - if (!this._view_only) { this._mouse.grab(); } + // NB(directxman12): these are down here so that we don't run them multiple times + // if we backtrack + Log.Info("Screen: " + this._fb_width + "x" + this._fb_height + + ", bpp: " + bpp + ", depth: " + depth + + ", big_endian: " + big_endian + + ", true_color: " + true_color + + ", red_max: " + red_max + + ", green_max: " + green_max + + ", blue_max: " + blue_max + + ", red_shift: " + red_shift + + ", green_shift: " + green_shift + + ", blue_shift: " + blue_shift); - if (this._true_color) { - this._fb_Bpp = 4; - this._fb_depth = 3; - } else { - this._fb_Bpp = 1; - this._fb_depth = 1; - } + if (big_endian !== 0) { + Log.Warn("Server native endian is not little endian"); + } - RFB.messages.pixelFormat(this._sock, this._fb_Bpp, this._fb_depth, this._true_color); - RFB.messages.clientEncodings(this._sock, this._encodings, this._local_cursor, this._true_color); - RFB.messages.fbUpdateRequest(this._sock, false, 0, 0, this._fb_width, this._fb_height); + if (red_shift !== 16) { + Log.Warn("Server native red-shift is not 16"); + } - this._timing.fbu_rt_start = (new Date()).getTime(); - this._timing.pixels = 0; + if (blue_shift !== 0) { + Log.Warn("Server native blue-shift is not 0"); + } - this._updateConnectionState('connected'); - return true; - }, + // we're past the point where we could backtrack, so it's safe to call this + this._onDesktopName(this, this._fb_name); - /* RFB protocol initialization states: - * ProtocolVersion - * Security - * Authentication - * SecurityResult - * ClientInitialization - not triggered by server message - * ServerInitialization + if (this._true_color && this._fb_name === "Intel(r) AMT KVM") { + Log.Warn("Intel AMT KVM only supports 8/16 bit depths. Disabling true color"); + this._true_color = false; + } + + this._display.set_true_color(this._true_color); + this._display.resize(this._fb_width, this._fb_height); + this._onFBResize(this, this._fb_width, this._fb_height); + + if (!this._view_only) { this._keyboard.grab(); } + if (!this._view_only) { this._mouse.grab(); } + + if (this._true_color) { + this._fb_Bpp = 4; + this._fb_depth = 3; + } else { + this._fb_Bpp = 1; + this._fb_depth = 1; + } + + RFB.messages.pixelFormat(this._sock, this._fb_Bpp, this._fb_depth, this._true_color); + RFB.messages.clientEncodings(this._sock, this._encodings, this._local_cursor, this._true_color); + RFB.messages.fbUpdateRequest(this._sock, false, 0, 0, this._fb_width, this._fb_height); + + this._timing.fbu_rt_start = (new Date()).getTime(); + this._timing.pixels = 0; + + this._updateConnectionState('connected'); + return true; + }, + + /* RFB protocol initialization states: + * ProtocolVersion + * Security + * Authentication + * SecurityResult + * ClientInitialization - not triggered by server message + * ServerInitialization + */ + _init_msg: function () { + switch (this._rfb_init_state) { + case 'ProtocolVersion': + return this._negotiate_protocol_version(); + + case 'Security': + return this._negotiate_security(); + + case 'Authentication': + return this._negotiate_authentication(); + + case 'SecurityResult': + return this._handle_security_result(); + + case 'ClientInitialisation': + this._sock.send([this._shared ? 1 : 0]); // ClientInitialisation + this._rfb_init_state = 'ServerInitialisation'; + return true; + + case 'ServerInitialisation': + return this._negotiate_server_init(); + + default: + return this._fail("Internal error", "Unknown init state: " + + this._rfb_init_state); + } + }, + + _handle_set_colour_map_msg: function () { + Log.Debug("SetColorMapEntries"); + this._sock.rQskip8(); // Padding + + var first_colour = this._sock.rQshift16(); + var num_colours = this._sock.rQshift16(); + if (this._sock.rQwait('SetColorMapEntries', num_colours * 6, 6)) { return false; } + + for (var c = 0; c < num_colours; c++) { + var red = parseInt(this._sock.rQshift16() / 256, 10); + var green = parseInt(this._sock.rQshift16() / 256, 10); + var blue = parseInt(this._sock.rQshift16() / 256, 10); + this._display.set_colourMap([blue, green, red], first_colour + c); + } + Log.Debug("colourMap: " + this._display.get_colourMap()); + Log.Info("Registered " + num_colours + " colourMap entries"); + + return true; + }, + + _handle_server_cut_text: function () { + Log.Debug("ServerCutText"); + + if (this._sock.rQwait("ServerCutText header", 7, 1)) { return false; } + this._sock.rQskipBytes(3); // Padding + var length = this._sock.rQshift32(); + if (this._sock.rQwait("ServerCutText", length, 8)) { return false; } + + var text = this._sock.rQshiftStr(length); + + if (this._view_only) { return true; } + + this._onClipboard(this, text); + + return true; + }, + + _handle_server_fence_msg: function() { + if (this._sock.rQwait("ServerFence header", 8, 1)) { return false; } + this._sock.rQskipBytes(3); // Padding + var flags = this._sock.rQshift32(); + var length = this._sock.rQshift8(); + + if (this._sock.rQwait("ServerFence payload", length, 9)) { return false; } + + if (length > 64) { + Log.Warn("Bad payload length (" + length + ") in fence response"); + length = 64; + } + + var payload = this._sock.rQshiftStr(length); + + this._supportsFence = true; + + /* + * Fence flags + * + * (1<<0) - BlockBefore + * (1<<1) - BlockAfter + * (1<<2) - SyncNext + * (1<<31) - Request */ - _init_msg: function () { - switch (this._rfb_init_state) { - case 'ProtocolVersion': - return this._negotiate_protocol_version(); - case 'Security': - return this._negotiate_security(); + if (!(flags & (1<<31))) { + return this._fail("Internal error", + "Unexpected fence response"); + } - case 'Authentication': - return this._negotiate_authentication(); + // Filter out unsupported flags + // FIXME: support syncNext + flags &= (1<<0) | (1<<1); - case 'SecurityResult': - return this._handle_security_result(); + // BlockBefore and BlockAfter are automatically handled by + // the fact that we process each incoming message + // synchronuosly. + RFB.messages.clientFence(this._sock, flags, payload); - case 'ClientInitialisation': - this._sock.send([this._shared ? 1 : 0]); // ClientInitialisation - this._rfb_init_state = 'ServerInitialisation'; - return true; + return true; + }, - case 'ServerInitialisation': - return this._negotiate_server_init(); + _handle_xvp_msg: function () { + if (this._sock.rQwait("XVP version and message", 3, 1)) { return false; } + this._sock.rQskip8(); // Padding + var xvp_ver = this._sock.rQshift8(); + var xvp_msg = this._sock.rQshift8(); - default: - return this._fail("Internal error", "Unknown init state: " + - this._rfb_init_state); - } - }, + switch (xvp_msg) { + case 0: // XVP_FAIL + Log.Error("Operation Failed"); + this._notification("XVP Operation Failed", 'error'); + break; + case 1: // XVP_INIT + this._rfb_xvp_ver = xvp_ver; + Log.Info("XVP extensions enabled (version " + this._rfb_xvp_ver + ")"); + this._onXvpInit(this._rfb_xvp_ver); + break; + default: + this._fail("Unexpected server message", + "Illegal server XVP message " + xvp_msg); + break; + } - _handle_set_colour_map_msg: function () { - Util.Debug("SetColorMapEntries"); + return true; + }, + + _normal_msg: function () { + var msg_type; + + if (this._FBU.rects > 0) { + msg_type = 0; + } else { + msg_type = this._sock.rQshift8(); + } + + switch (msg_type) { + case 0: // FramebufferUpdate + var ret = this._framebufferUpdate(); + if (ret && !this._enabledContinuousUpdates) { + RFB.messages.fbUpdateRequest(this._sock, true, 0, 0, + this._fb_width, this._fb_height); + } + return ret; + + case 1: // SetColorMapEntries + return this._handle_set_colour_map_msg(); + + case 2: // Bell + Log.Debug("Bell"); + this._onBell(this); + return true; + + case 3: // ServerCutText + return this._handle_server_cut_text(); + + case 150: // EndOfContinuousUpdates + var first = !(this._supportsContinuousUpdates); + this._supportsContinuousUpdates = true; + this._enabledContinuousUpdates = false; + if (first) { + this._enabledContinuousUpdates = true; + this._updateContinuousUpdates(); + Log.Info("Enabling continuous updates."); + } else { + // FIXME: We need to send a framebufferupdaterequest here + // if we add support for turning off continuous updates + } + return true; + + case 248: // ServerFence + return this._handle_server_fence_msg(); + + case 250: // XVP + return this._handle_xvp_msg(); + + default: + this._fail("Unexpected server message", "Type:" + msg_type); + Log.Debug("sock.rQslice(0, 30): " + this._sock.rQslice(0, 30)); + return true; + } + }, + + _onFlush: function() { + this._flushing = false; + // Resume processing + if (this._sock.rQlen() > 0) { + this._handle_message(); + } + }, + + _framebufferUpdate: function () { + var ret = true; + var now; + + if (this._FBU.rects === 0) { + if (this._sock.rQwait("FBU header", 3, 1)) { return false; } this._sock.rQskip8(); // Padding - - var first_colour = this._sock.rQshift16(); - var num_colours = this._sock.rQshift16(); - if (this._sock.rQwait('SetColorMapEntries', num_colours * 6, 6)) { return false; } - - for (var c = 0; c < num_colours; c++) { - var red = parseInt(this._sock.rQshift16() / 256, 10); - var green = parseInt(this._sock.rQshift16() / 256, 10); - var blue = parseInt(this._sock.rQshift16() / 256, 10); - this._display.set_colourMap([blue, green, red], first_colour + c); - } - Util.Debug("colourMap: " + this._display.get_colourMap()); - Util.Info("Registered " + num_colours + " colourMap entries"); - - return true; - }, - - _handle_server_cut_text: function () { - Util.Debug("ServerCutText"); - if (this._view_only) { return true; } - - if (this._sock.rQwait("ServerCutText header", 7, 1)) { return false; } - this._sock.rQskipBytes(3); // Padding - var length = this._sock.rQshift32(); - if (this._sock.rQwait("ServerCutText", length, 8)) { return false; } - - var text = this._sock.rQshiftStr(length); - this._onClipboard(this, text); - - return true; - }, - - _handle_server_fence_msg: function() { - if (this._sock.rQwait("ServerFence header", 8, 1)) { return false; } - this._sock.rQskipBytes(3); // Padding - var flags = this._sock.rQshift32(); - var length = this._sock.rQshift8(); - - if (this._sock.rQwait("ServerFence payload", length, 9)) { return false; } - - if (length > 64) { - Util.Warn("Bad payload length (" + length + ") in fence response"); - length = 64; - } - - var payload = this._sock.rQshiftStr(length); - - this._supportsFence = true; - - /* - * Fence flags - * - * (1<<0) - BlockBefore - * (1<<1) - BlockAfter - * (1<<2) - SyncNext - * (1<<31) - Request - */ - - if (!(flags & (1<<31))) { - return this._fail("Internal error", - "Unexpected fence response"); - } - - // Filter out unsupported flags - // FIXME: support syncNext - flags &= (1<<0) | (1<<1); - - // BlockBefore and BlockAfter are automatically handled by - // the fact that we process each incoming message - // synchronuosly. - RFB.messages.clientFence(this._sock, flags, payload); - - return true; - }, - - _handle_xvp_msg: function () { - if (this._sock.rQwait("XVP version and message", 3, 1)) { return false; } - this._sock.rQskip8(); // Padding - var xvp_ver = this._sock.rQshift8(); - var xvp_msg = this._sock.rQshift8(); - - switch (xvp_msg) { - case 0: // XVP_FAIL - Util.Error("Operation Failed"); - this._notification("XVP Operation Failed", 'error'); - break; - case 1: // XVP_INIT - this._rfb_xvp_ver = xvp_ver; - Util.Info("XVP extensions enabled (version " + this._rfb_xvp_ver + ")"); - this._onXvpInit(this._rfb_xvp_ver); - break; - default: - this._fail("Unexpected server message", - "Illegal server XVP message " + xvp_msg); - break; - } - - return true; - }, - - _normal_msg: function () { - var msg_type; - - if (this._FBU.rects > 0) { - msg_type = 0; - } else { - msg_type = this._sock.rQshift8(); - } - - switch (msg_type) { - case 0: // FramebufferUpdate - var ret = this._framebufferUpdate(); - if (ret && !this._enabledContinuousUpdates) { - RFB.messages.fbUpdateRequest(this._sock, true, 0, 0, - this._fb_width, this._fb_height); - } - return ret; - - case 1: // SetColorMapEntries - return this._handle_set_colour_map_msg(); - - case 2: // Bell - Util.Debug("Bell"); - this._onBell(this); - return true; - - case 3: // ServerCutText - return this._handle_server_cut_text(); - - case 150: // EndOfContinuousUpdates - var first = !(this._supportsContinuousUpdates); - this._supportsContinuousUpdates = true; - this._enabledContinuousUpdates = false; - if (first) { - this._enabledContinuousUpdates = true; - this._updateContinuousUpdates(); - Util.Info("Enabling continuous updates."); - } else { - // FIXME: We need to send a framebufferupdaterequest here - // if we add support for turning off continuous updates - } - return true; - - case 248: // ServerFence - return this._handle_server_fence_msg(); - - case 250: // XVP - return this._handle_xvp_msg(); - - default: - this._fail("Unexpected server message", "Type:" + msg_type); - Util.Debug("sock.rQslice(0, 30): " + this._sock.rQslice(0, 30)); - return true; - } - }, - - _onFlush: function() { - this._flushing = false; - // Resume processing - if (this._sock.rQlen() > 0) { - this._handle_message(); - } - }, - - _framebufferUpdate: function () { - var ret = true; - var now; - - if (this._FBU.rects === 0) { - if (this._sock.rQwait("FBU header", 3, 1)) { return false; } - this._sock.rQskip8(); // Padding - this._FBU.rects = this._sock.rQshift16(); - this._FBU.bytes = 0; - this._timing.cur_fbu = 0; - if (this._timing.fbu_rt_start > 0) { - now = (new Date()).getTime(); - Util.Info("First FBU latency: " + (now - this._timing.fbu_rt_start)); - } - - // Make sure the previous frame is fully rendered first - // to avoid building up an excessive queue - if (this._display.pending()) { - this._flushing = true; - this._display.flush(); - return false; - } - } - - while (this._FBU.rects > 0) { - if (this._rfb_connection_state !== 'connected') { return false; } - - if (this._sock.rQwait("FBU", this._FBU.bytes)) { return false; } - if (this._FBU.bytes === 0) { - if (this._sock.rQwait("rect header", 12)) { return false; } - /* New FramebufferUpdate */ - - var hdr = this._sock.rQshiftBytes(12); - this._FBU.x = (hdr[0] << 8) + hdr[1]; - this._FBU.y = (hdr[2] << 8) + hdr[3]; - this._FBU.width = (hdr[4] << 8) + hdr[5]; - this._FBU.height = (hdr[6] << 8) + hdr[7]; - this._FBU.encoding = parseInt((hdr[8] << 24) + (hdr[9] << 16) + - (hdr[10] << 8) + hdr[11], 10); - - this._onFBUReceive(this, - {'x': this._FBU.x, 'y': this._FBU.y, - 'width': this._FBU.width, 'height': this._FBU.height, - 'encoding': this._FBU.encoding, - 'encodingName': this._encNames[this._FBU.encoding]}); - - if (!this._encNames[this._FBU.encoding]) { - this._fail("Unexpected server message", - "Unsupported encoding " + - this._FBU.encoding); - return false; - } - } - - this._timing.last_fbu = (new Date()).getTime(); - - ret = this._encHandlers[this._FBU.encoding](); - + this._FBU.rects = this._sock.rQshift16(); + this._FBU.bytes = 0; + this._timing.cur_fbu = 0; + if (this._timing.fbu_rt_start > 0) { now = (new Date()).getTime(); - this._timing.cur_fbu += (now - this._timing.last_fbu); - - if (ret) { - this._encStats[this._FBU.encoding][0]++; - this._encStats[this._FBU.encoding][1]++; - this._timing.pixels += this._FBU.width * this._FBU.height; - } - - if (this._timing.pixels >= (this._fb_width * this._fb_height)) { - if ((this._FBU.width === this._fb_width && this._FBU.height === this._fb_height) || - this._timing.fbu_rt_start > 0) { - this._timing.full_fbu_total += this._timing.cur_fbu; - this._timing.full_fbu_cnt++; - Util.Info("Timing of full FBU, curr: " + - this._timing.cur_fbu + ", total: " + - this._timing.full_fbu_total + ", cnt: " + - this._timing.full_fbu_cnt + ", avg: " + - (this._timing.full_fbu_total / this._timing.full_fbu_cnt)); - } - - if (this._timing.fbu_rt_start > 0) { - var fbu_rt_diff = now - this._timing.fbu_rt_start; - this._timing.fbu_rt_total += fbu_rt_diff; - this._timing.fbu_rt_cnt++; - Util.Info("full FBU round-trip, cur: " + - fbu_rt_diff + ", total: " + - this._timing.fbu_rt_total + ", cnt: " + - this._timing.fbu_rt_cnt + ", avg: " + - (this._timing.fbu_rt_total / this._timing.fbu_rt_cnt)); - this._timing.fbu_rt_start = 0; - } - } - - if (!ret) { return ret; } // need more data + Log.Info("First FBU latency: " + (now - this._timing.fbu_rt_start)); } - this._display.flip(); + // Make sure the previous frame is fully rendered first + // to avoid building up an excessive queue + if (this._display.pending()) { + this._flushing = true; + this._display.flush(); + return false; + } + } - this._onFBUComplete(this, + while (this._FBU.rects > 0) { + if (this._rfb_connection_state !== 'connected') { return false; } + + if (this._sock.rQwait("FBU", this._FBU.bytes)) { return false; } + if (this._FBU.bytes === 0) { + if (this._sock.rQwait("rect header", 12)) { return false; } + /* New FramebufferUpdate */ + + var hdr = this._sock.rQshiftBytes(12); + this._FBU.x = (hdr[0] << 8) + hdr[1]; + this._FBU.y = (hdr[2] << 8) + hdr[3]; + this._FBU.width = (hdr[4] << 8) + hdr[5]; + this._FBU.height = (hdr[6] << 8) + hdr[7]; + this._FBU.encoding = parseInt((hdr[8] << 24) + (hdr[9] << 16) + + (hdr[10] << 8) + hdr[11], 10); + + this._onFBUReceive(this, {'x': this._FBU.x, 'y': this._FBU.y, 'width': this._FBU.width, 'height': this._FBU.height, 'encoding': this._FBU.encoding, 'encodingName': this._encNames[this._FBU.encoding]}); - return true; // We finished this FBU - }, - - _updateContinuousUpdates: function() { - if (!this._enabledContinuousUpdates) { return; } - - RFB.messages.enableContinuousUpdates(this._sock, true, 0, 0, - this._fb_width, this._fb_height); - } - }; - - Util.make_properties(RFB, [ - ['target', 'wo', 'dom'], // VNC display rendering Canvas object - ['focusContainer', 'wo', 'dom'], // DOM element that captures keyboard input - ['encrypt', 'rw', 'bool'], // Use TLS/SSL/wss encryption - ['true_color', 'rw', 'bool'], // Request true color pixel data - ['local_cursor', 'rw', 'bool'], // Request locally rendered cursor - ['shared', 'rw', 'bool'], // Request shared mode - ['view_only', 'rw', 'bool'], // Disable client mouse/keyboard - ['xvp_password_sep', 'rw', 'str'], // Separator for XVP password fields - ['disconnectTimeout', 'rw', 'int'], // Time (s) to wait for disconnection - ['wsProtocols', 'rw', 'arr'], // Protocols to use in the WebSocket connection - ['repeaterID', 'rw', 'str'], // [UltraVNC] RepeaterID to connect to - ['viewportDrag', 'rw', 'bool'], // Move the viewport on mouse drags - - // Callback functions - ['onUpdateState', 'rw', 'func'], // onUpdateState(rfb, state, oldstate): connection state change - ['onNotification', 'rw', 'func'], // onNotification(rfb, msg, level, options): notification for the UI - ['onDisconnected', 'rw', 'func'], // onDisconnected(rfb, reason): disconnection finished - ['onPasswordRequired', 'rw', 'func'], // onPasswordRequired(rfb, msg): VNC password is required - ['onClipboard', 'rw', 'func'], // onClipboard(rfb, text): RFB clipboard contents received - ['onBell', 'rw', 'func'], // onBell(rfb): RFB Bell message received - ['onFBUReceive', 'rw', 'func'], // onFBUReceive(rfb, fbu): RFB FBU received but not yet processed - ['onFBUComplete', 'rw', 'func'], // onFBUComplete(rfb, fbu): RFB FBU received and processed - ['onFBResize', 'rw', 'func'], // onFBResize(rfb, width, height): frame buffer resized - ['onDesktopName', 'rw', 'func'], // onDesktopName(rfb, name): desktop name received - ['onXvpInit', 'rw', 'func'] // onXvpInit(version): XVP extensions active for this connection - ]); - - RFB.prototype.set_local_cursor = function (cursor) { - if (!cursor || (cursor in {'0': 1, 'no': 1, 'false': 1})) { - this._local_cursor = false; - this._display.disableLocalCursor(); //Only show server-side cursor - } else { - if (this._display.get_cursor_uri()) { - this._local_cursor = true; - } else { - Util.Warn("Browser does not support local cursor"); - this._display.disableLocalCursor(); - } - } - - // Need to send an updated list of encodings if we are connected - if (this._rfb_connection_state === "connected") { - RFB.messages.clientEncodings(this._sock, this._encodings, cursor, - this._true_color); - } - }; - - RFB.prototype.set_view_only = function (view_only) { - this._view_only = view_only; - - if (this._rfb_connection_state === "connecting" || - this._rfb_connection_state === "connected") { - if (view_only) { - this._keyboard.ungrab(); - this._mouse.ungrab(); - } else { - this._keyboard.grab(); - this._mouse.grab(); - } - } - }; - - RFB.prototype.get_display = function () { return this._display; }; - RFB.prototype.get_keyboard = function () { return this._keyboard; }; - RFB.prototype.get_mouse = function () { return this._mouse; }; - - // Class Methods - RFB.messages = { - keyEvent: function (sock, keysym, down) { - var buff = sock._sQ; - var offset = sock._sQlen; - - buff[offset] = 4; // msg-type - buff[offset + 1] = down; - - buff[offset + 2] = 0; - buff[offset + 3] = 0; - - buff[offset + 4] = (keysym >> 24); - buff[offset + 5] = (keysym >> 16); - buff[offset + 6] = (keysym >> 8); - buff[offset + 7] = keysym; - - sock._sQlen += 8; - sock.flush(); - }, - - QEMUExtendedKeyEvent: function (sock, keysym, down, keycode) { - function getRFBkeycode(xt_scancode) { - var upperByte = (keycode >> 8); - var lowerByte = (keycode & 0x00ff); - if (upperByte === 0xe0 && lowerByte < 0x7f) { - lowerByte = lowerByte | 0x80; - return lowerByte; - } - return xt_scancode; - } - - var buff = sock._sQ; - var offset = sock._sQlen; - - buff[offset] = 255; // msg-type - buff[offset + 1] = 0; // sub msg-type - - buff[offset + 2] = (down >> 8); - buff[offset + 3] = down; - - buff[offset + 4] = (keysym >> 24); - buff[offset + 5] = (keysym >> 16); - buff[offset + 6] = (keysym >> 8); - buff[offset + 7] = keysym; - - var RFBkeycode = getRFBkeycode(keycode); - - buff[offset + 8] = (RFBkeycode >> 24); - buff[offset + 9] = (RFBkeycode >> 16); - buff[offset + 10] = (RFBkeycode >> 8); - buff[offset + 11] = RFBkeycode; - - sock._sQlen += 12; - sock.flush(); - }, - - pointerEvent: function (sock, x, y, mask) { - var buff = sock._sQ; - var offset = sock._sQlen; - - buff[offset] = 5; // msg-type - - buff[offset + 1] = mask; - - buff[offset + 2] = x >> 8; - buff[offset + 3] = x; - - buff[offset + 4] = y >> 8; - buff[offset + 5] = y; - - sock._sQlen += 6; - sock.flush(); - }, - - // TODO(directxman12): make this unicode compatible? - clientCutText: function (sock, text) { - var buff = sock._sQ; - var offset = sock._sQlen; - - buff[offset] = 6; // msg-type - - buff[offset + 1] = 0; // padding - buff[offset + 2] = 0; // padding - buff[offset + 3] = 0; // padding - - var n = text.length; - - buff[offset + 4] = n >> 24; - buff[offset + 5] = n >> 16; - buff[offset + 6] = n >> 8; - buff[offset + 7] = n; - - for (var i = 0; i < n; i++) { - buff[offset + 8 + i] = text.charCodeAt(i); - } - - sock._sQlen += 8 + n; - sock.flush(); - }, - - setDesktopSize: function (sock, width, height, id, flags) { - var buff = sock._sQ; - var offset = sock._sQlen; - - buff[offset] = 251; // msg-type - buff[offset + 1] = 0; // padding - buff[offset + 2] = width >> 8; // width - buff[offset + 3] = width; - buff[offset + 4] = height >> 8; // height - buff[offset + 5] = height; - - buff[offset + 6] = 1; // number-of-screens - buff[offset + 7] = 0; // padding - - // screen array - buff[offset + 8] = id >> 24; // id - buff[offset + 9] = id >> 16; - buff[offset + 10] = id >> 8; - buff[offset + 11] = id; - buff[offset + 12] = 0; // x-position - buff[offset + 13] = 0; - buff[offset + 14] = 0; // y-position - buff[offset + 15] = 0; - buff[offset + 16] = width >> 8; // width - buff[offset + 17] = width; - buff[offset + 18] = height >> 8; // height - buff[offset + 19] = height; - buff[offset + 20] = flags >> 24; // flags - buff[offset + 21] = flags >> 16; - buff[offset + 22] = flags >> 8; - buff[offset + 23] = flags; - - sock._sQlen += 24; - sock.flush(); - }, - - clientFence: function (sock, flags, payload) { - var buff = sock._sQ; - var offset = sock._sQlen; - - buff[offset] = 248; // msg-type - - buff[offset + 1] = 0; // padding - buff[offset + 2] = 0; // padding - buff[offset + 3] = 0; // padding - - buff[offset + 4] = flags >> 24; // flags - buff[offset + 5] = flags >> 16; - buff[offset + 6] = flags >> 8; - buff[offset + 7] = flags; - - var n = payload.length; - - buff[offset + 8] = n; // length - - for (var i = 0; i < n; i++) { - buff[offset + 9 + i] = payload.charCodeAt(i); - } - - sock._sQlen += 9 + n; - sock.flush(); - }, - - enableContinuousUpdates: function (sock, enable, x, y, width, height) { - var buff = sock._sQ; - var offset = sock._sQlen; - - buff[offset] = 150; // msg-type - buff[offset + 1] = enable; // enable-flag - - buff[offset + 2] = x >> 8; // x - buff[offset + 3] = x; - buff[offset + 4] = y >> 8; // y - buff[offset + 5] = y; - buff[offset + 6] = width >> 8; // width - buff[offset + 7] = width; - buff[offset + 8] = height >> 8; // height - buff[offset + 9] = height; - - sock._sQlen += 10; - sock.flush(); - }, - - pixelFormat: function (sock, bpp, depth, true_color) { - var buff = sock._sQ; - var offset = sock._sQlen; - - buff[offset] = 0; // msg-type - - buff[offset + 1] = 0; // padding - buff[offset + 2] = 0; // padding - buff[offset + 3] = 0; // padding - - buff[offset + 4] = bpp * 8; // bits-per-pixel - buff[offset + 5] = depth * 8; // depth - buff[offset + 6] = 0; // little-endian - buff[offset + 7] = true_color ? 1 : 0; // true-color - - buff[offset + 8] = 0; // red-max - buff[offset + 9] = 255; // red-max - - buff[offset + 10] = 0; // green-max - buff[offset + 11] = 255; // green-max - - buff[offset + 12] = 0; // blue-max - buff[offset + 13] = 255; // blue-max - - buff[offset + 14] = 16; // red-shift - buff[offset + 15] = 8; // green-shift - buff[offset + 16] = 0; // blue-shift - - buff[offset + 17] = 0; // padding - buff[offset + 18] = 0; // padding - buff[offset + 19] = 0; // padding - - sock._sQlen += 20; - sock.flush(); - }, - - clientEncodings: function (sock, encodings, local_cursor, true_color) { - var buff = sock._sQ; - var offset = sock._sQlen; - - buff[offset] = 2; // msg-type - buff[offset + 1] = 0; // padding - - // offset + 2 and offset + 3 are encoding count - - var i, j = offset + 4, cnt = 0; - for (i = 0; i < encodings.length; i++) { - if (encodings[i][0] === "Cursor" && !local_cursor) { - Util.Debug("Skipping Cursor pseudo-encoding"); - } else if (encodings[i][0] === "TIGHT" && !true_color) { - // TODO: remove this when we have tight+non-true-color - Util.Warn("Skipping tight as it is only supported with true color"); - } else { - var enc = encodings[i][1]; - buff[j] = enc >> 24; - buff[j + 1] = enc >> 16; - buff[j + 2] = enc >> 8; - buff[j + 3] = enc; - - j += 4; - cnt++; - } - } - - buff[offset + 2] = cnt >> 8; - buff[offset + 3] = cnt; - - sock._sQlen += j - offset; - sock.flush(); - }, - - fbUpdateRequest: function (sock, incremental, x, y, w, h) { - var buff = sock._sQ; - var offset = sock._sQlen; - - if (typeof(x) === "undefined") { x = 0; } - if (typeof(y) === "undefined") { y = 0; } - - buff[offset] = 3; // msg-type - buff[offset + 1] = incremental ? 1 : 0; - - buff[offset + 2] = (x >> 8) & 0xFF; - buff[offset + 3] = x & 0xFF; - - buff[offset + 4] = (y >> 8) & 0xFF; - buff[offset + 5] = y & 0xFF; - - buff[offset + 6] = (w >> 8) & 0xFF; - buff[offset + 7] = w & 0xFF; - - buff[offset + 8] = (h >> 8) & 0xFF; - buff[offset + 9] = h & 0xFF; - - sock._sQlen += 10; - sock.flush(); - } - }; - - RFB.genDES = function (password, challenge) { - var passwd = []; - for (var i = 0; i < password.length; i++) { - passwd.push(password.charCodeAt(i)); - } - return (new DES(passwd)).encrypt(challenge); - }; - - RFB.encodingHandlers = { - RAW: function () { - if (this._FBU.lines === 0) { - this._FBU.lines = this._FBU.height; - } - - this._FBU.bytes = this._FBU.width * this._fb_Bpp; // at least a line - if (this._sock.rQwait("RAW", this._FBU.bytes)) { return false; } - var cur_y = this._FBU.y + (this._FBU.height - this._FBU.lines); - var curr_height = Math.min(this._FBU.lines, - Math.floor(this._sock.rQlen() / (this._FBU.width * this._fb_Bpp))); - this._display.blitImage(this._FBU.x, cur_y, this._FBU.width, - curr_height, this._sock.get_rQ(), - this._sock.get_rQi()); - this._sock.rQskipBytes(this._FBU.width * curr_height * this._fb_Bpp); - this._FBU.lines -= curr_height; - - if (this._FBU.lines > 0) { - this._FBU.bytes = this._FBU.width * this._fb_Bpp; // At least another line - } else { - this._FBU.rects--; - this._FBU.bytes = 0; - } - - return true; - }, - - COPYRECT: function () { - this._FBU.bytes = 4; - if (this._sock.rQwait("COPYRECT", 4)) { return false; } - this._display.copyImage(this._sock.rQshift16(), this._sock.rQshift16(), - this._FBU.x, this._FBU.y, this._FBU.width, - this._FBU.height); - - this._FBU.rects--; - this._FBU.bytes = 0; - return true; - }, - - RRE: function () { - var color; - if (this._FBU.subrects === 0) { - this._FBU.bytes = 4 + this._fb_Bpp; - if (this._sock.rQwait("RRE", 4 + this._fb_Bpp)) { return false; } - this._FBU.subrects = this._sock.rQshift32(); - color = this._sock.rQshiftBytes(this._fb_Bpp); // Background - this._display.fillRect(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, color); - } - - while (this._FBU.subrects > 0 && this._sock.rQlen() >= (this._fb_Bpp + 8)) { - color = this._sock.rQshiftBytes(this._fb_Bpp); - var x = this._sock.rQshift16(); - var y = this._sock.rQshift16(); - var width = this._sock.rQshift16(); - var height = this._sock.rQshift16(); - this._display.fillRect(this._FBU.x + x, this._FBU.y + y, width, height, color); - this._FBU.subrects--; - } - - if (this._FBU.subrects > 0) { - var chunk = Math.min(this._rre_chunk_sz, this._FBU.subrects); - this._FBU.bytes = (this._fb_Bpp + 8) * chunk; - } else { - this._FBU.rects--; - this._FBU.bytes = 0; - } - - return true; - }, - - HEXTILE: function () { - var rQ = this._sock.get_rQ(); - var rQi = this._sock.get_rQi(); - - if (this._FBU.tiles === 0) { - this._FBU.tiles_x = Math.ceil(this._FBU.width / 16); - this._FBU.tiles_y = Math.ceil(this._FBU.height / 16); - this._FBU.total_tiles = this._FBU.tiles_x * this._FBU.tiles_y; - this._FBU.tiles = this._FBU.total_tiles; - } - - while (this._FBU.tiles > 0) { - this._FBU.bytes = 1; - if (this._sock.rQwait("HEXTILE subencoding", this._FBU.bytes)) { return false; } - var subencoding = rQ[rQi]; // Peek - if (subencoding > 30) { // Raw + if (!this._encNames[this._FBU.encoding]) { this._fail("Unexpected server message", - "Illegal hextile subencoding: " + subencoding); + "Unsupported encoding " + + this._FBU.encoding); return false; } + } - var subrects = 0; - var curr_tile = this._FBU.total_tiles - this._FBU.tiles; - var tile_x = curr_tile % this._FBU.tiles_x; - var tile_y = Math.floor(curr_tile / this._FBU.tiles_x); - var x = this._FBU.x + tile_x * 16; - var y = this._FBU.y + tile_y * 16; - var w = Math.min(16, (this._FBU.x + this._FBU.width) - x); - var h = Math.min(16, (this._FBU.y + this._FBU.height) - y); + this._timing.last_fbu = (new Date()).getTime(); - // Figure out how much we are expecting - if (subencoding & 0x01) { // Raw - this._FBU.bytes += w * h * this._fb_Bpp; - } else { - if (subencoding & 0x02) { // Background - this._FBU.bytes += this._fb_Bpp; - } - if (subencoding & 0x04) { // Foreground - this._FBU.bytes += this._fb_Bpp; - } - if (subencoding & 0x08) { // AnySubrects - this._FBU.bytes++; // Since we aren't shifting it off - if (this._sock.rQwait("hextile subrects header", this._FBU.bytes)) { return false; } - subrects = rQ[rQi + this._FBU.bytes - 1]; // Peek - if (subencoding & 0x10) { // SubrectsColoured - this._FBU.bytes += subrects * (this._fb_Bpp + 2); - } else { - this._FBU.bytes += subrects * 2; - } - } + ret = this._encHandlers[this._FBU.encoding](); + + now = (new Date()).getTime(); + this._timing.cur_fbu += (now - this._timing.last_fbu); + + if (ret) { + this._encStats[this._FBU.encoding][0]++; + this._encStats[this._FBU.encoding][1]++; + this._timing.pixels += this._FBU.width * this._FBU.height; + } + + if (this._timing.pixels >= (this._fb_width * this._fb_height)) { + if ((this._FBU.width === this._fb_width && this._FBU.height === this._fb_height) || + this._timing.fbu_rt_start > 0) { + this._timing.full_fbu_total += this._timing.cur_fbu; + this._timing.full_fbu_cnt++; + Log.Info("Timing of full FBU, curr: " + + this._timing.cur_fbu + ", total: " + + this._timing.full_fbu_total + ", cnt: " + + this._timing.full_fbu_cnt + ", avg: " + + (this._timing.full_fbu_total / this._timing.full_fbu_cnt)); } - if (this._sock.rQwait("hextile", this._FBU.bytes)) { return false; } + if (this._timing.fbu_rt_start > 0) { + var fbu_rt_diff = now - this._timing.fbu_rt_start; + this._timing.fbu_rt_total += fbu_rt_diff; + this._timing.fbu_rt_cnt++; + Log.Info("full FBU round-trip, cur: " + + fbu_rt_diff + ", total: " + + this._timing.fbu_rt_total + ", cnt: " + + this._timing.fbu_rt_cnt + ", avg: " + + (this._timing.fbu_rt_total / this._timing.fbu_rt_cnt)); + this._timing.fbu_rt_start = 0; + } + } - // We know the encoding and have a whole tile - this._FBU.subencoding = rQ[rQi]; - rQi++; - if (this._FBU.subencoding === 0) { - if (this._FBU.lastsubencoding & 0x01) { - // Weird: ignore blanks are RAW - Util.Debug(" Ignoring blank after RAW"); + if (!ret) { return ret; } // need more data + } + + this._display.flip(); + + this._onFBUComplete(this, + {'x': this._FBU.x, 'y': this._FBU.y, + 'width': this._FBU.width, 'height': this._FBU.height, + 'encoding': this._FBU.encoding, + 'encodingName': this._encNames[this._FBU.encoding]}); + + return true; // We finished this FBU + }, + + _updateContinuousUpdates: function() { + if (!this._enabledContinuousUpdates) { return; } + + RFB.messages.enableContinuousUpdates(this._sock, true, 0, 0, + this._fb_width, this._fb_height); + } +}; + +make_properties(RFB, [ + ['target', 'wo', 'dom'], // VNC display rendering Canvas object + ['focusContainer', 'wo', 'dom'], // DOM element that captures keyboard input + ['encrypt', 'rw', 'bool'], // Use TLS/SSL/wss encryption + ['true_color', 'rw', 'bool'], // Request true color pixel data + ['local_cursor', 'rw', 'bool'], // Request locally rendered cursor + ['shared', 'rw', 'bool'], // Request shared mode + ['view_only', 'rw', 'bool'], // Disable client mouse/keyboard + ['xvp_password_sep', 'rw', 'str'], // Separator for XVP password fields + ['disconnectTimeout', 'rw', 'int'], // Time (s) to wait for disconnection + ['wsProtocols', 'rw', 'arr'], // Protocols to use in the WebSocket connection + ['repeaterID', 'rw', 'str'], // [UltraVNC] RepeaterID to connect to + ['viewportDrag', 'rw', 'bool'], // Move the viewport on mouse drags + + // Callback functions + ['onUpdateState', 'rw', 'func'], // onUpdateState(rfb, state, oldstate): connection state change + ['onNotification', 'rw', 'func'], // onNotification(rfb, msg, level, options): notification for the UI + ['onDisconnected', 'rw', 'func'], // onDisconnected(rfb, reason): disconnection finished + ['onPasswordRequired', 'rw', 'func'], // onPasswordRequired(rfb, msg): VNC password is required + ['onClipboard', 'rw', 'func'], // onClipboard(rfb, text): RFB clipboard contents received + ['onBell', 'rw', 'func'], // onBell(rfb): RFB Bell message received + ['onFBUReceive', 'rw', 'func'], // onFBUReceive(rfb, fbu): RFB FBU received but not yet processed + ['onFBUComplete', 'rw', 'func'], // onFBUComplete(rfb, fbu): RFB FBU received and processed + ['onFBResize', 'rw', 'func'], // onFBResize(rfb, width, height): frame buffer resized + ['onDesktopName', 'rw', 'func'], // onDesktopName(rfb, name): desktop name received + ['onXvpInit', 'rw', 'func'] // onXvpInit(version): XVP extensions active for this connection +]); + +RFB.prototype.set_local_cursor = function (cursor) { + if (!cursor || (cursor in {'0': 1, 'no': 1, 'false': 1})) { + this._local_cursor = false; + this._display.disableLocalCursor(); //Only show server-side cursor + } else { + if (this._display.get_cursor_uri()) { + this._local_cursor = true; + } else { + Log.Warn("Browser does not support local cursor"); + this._display.disableLocalCursor(); + } + } + + // Need to send an updated list of encodings if we are connected + if (this._rfb_connection_state === "connected") { + RFB.messages.clientEncodings(this._sock, this._encodings, cursor, + this._true_color); + } +}; + +RFB.prototype.set_view_only = function (view_only) { + this._view_only = view_only; + + if (this._rfb_connection_state === "connecting" || + this._rfb_connection_state === "connected") { + if (view_only) { + this._keyboard.ungrab(); + this._mouse.ungrab(); + } else { + this._keyboard.grab(); + this._mouse.grab(); + } + } +}; + +RFB.prototype.get_display = function () { return this._display; }; +RFB.prototype.get_keyboard = function () { return this._keyboard; }; +RFB.prototype.get_mouse = function () { return this._mouse; }; + +// Class Methods +RFB.messages = { + keyEvent: function (sock, keysym, down) { + var buff = sock._sQ; + var offset = sock._sQlen; + + buff[offset] = 4; // msg-type + buff[offset + 1] = down; + + buff[offset + 2] = 0; + buff[offset + 3] = 0; + + buff[offset + 4] = (keysym >> 24); + buff[offset + 5] = (keysym >> 16); + buff[offset + 6] = (keysym >> 8); + buff[offset + 7] = keysym; + + sock._sQlen += 8; + sock.flush(); + }, + + QEMUExtendedKeyEvent: function (sock, keysym, down, keycode) { + function getRFBkeycode(xt_scancode) { + var upperByte = (keycode >> 8); + var lowerByte = (keycode & 0x00ff); + if (upperByte === 0xe0 && lowerByte < 0x7f) { + lowerByte = lowerByte | 0x80; + return lowerByte; + } + return xt_scancode; + } + + var buff = sock._sQ; + var offset = sock._sQlen; + + buff[offset] = 255; // msg-type + buff[offset + 1] = 0; // sub msg-type + + buff[offset + 2] = (down >> 8); + buff[offset + 3] = down; + + buff[offset + 4] = (keysym >> 24); + buff[offset + 5] = (keysym >> 16); + buff[offset + 6] = (keysym >> 8); + buff[offset + 7] = keysym; + + var RFBkeycode = getRFBkeycode(keycode); + + buff[offset + 8] = (RFBkeycode >> 24); + buff[offset + 9] = (RFBkeycode >> 16); + buff[offset + 10] = (RFBkeycode >> 8); + buff[offset + 11] = RFBkeycode; + + sock._sQlen += 12; + sock.flush(); + }, + + pointerEvent: function (sock, x, y, mask) { + var buff = sock._sQ; + var offset = sock._sQlen; + + buff[offset] = 5; // msg-type + + buff[offset + 1] = mask; + + buff[offset + 2] = x >> 8; + buff[offset + 3] = x; + + buff[offset + 4] = y >> 8; + buff[offset + 5] = y; + + sock._sQlen += 6; + sock.flush(); + }, + + // TODO(directxman12): make this unicode compatible? + clientCutText: function (sock, text) { + var buff = sock._sQ; + var offset = sock._sQlen; + + buff[offset] = 6; // msg-type + + buff[offset + 1] = 0; // padding + buff[offset + 2] = 0; // padding + buff[offset + 3] = 0; // padding + + var n = text.length; + + buff[offset + 4] = n >> 24; + buff[offset + 5] = n >> 16; + buff[offset + 6] = n >> 8; + buff[offset + 7] = n; + + for (var i = 0; i < n; i++) { + buff[offset + 8 + i] = text.charCodeAt(i); + } + + sock._sQlen += 8 + n; + sock.flush(); + }, + + setDesktopSize: function (sock, width, height, id, flags) { + var buff = sock._sQ; + var offset = sock._sQlen; + + buff[offset] = 251; // msg-type + buff[offset + 1] = 0; // padding + buff[offset + 2] = width >> 8; // width + buff[offset + 3] = width; + buff[offset + 4] = height >> 8; // height + buff[offset + 5] = height; + + buff[offset + 6] = 1; // number-of-screens + buff[offset + 7] = 0; // padding + + // screen array + buff[offset + 8] = id >> 24; // id + buff[offset + 9] = id >> 16; + buff[offset + 10] = id >> 8; + buff[offset + 11] = id; + buff[offset + 12] = 0; // x-position + buff[offset + 13] = 0; + buff[offset + 14] = 0; // y-position + buff[offset + 15] = 0; + buff[offset + 16] = width >> 8; // width + buff[offset + 17] = width; + buff[offset + 18] = height >> 8; // height + buff[offset + 19] = height; + buff[offset + 20] = flags >> 24; // flags + buff[offset + 21] = flags >> 16; + buff[offset + 22] = flags >> 8; + buff[offset + 23] = flags; + + sock._sQlen += 24; + sock.flush(); + }, + + clientFence: function (sock, flags, payload) { + var buff = sock._sQ; + var offset = sock._sQlen; + + buff[offset] = 248; // msg-type + + buff[offset + 1] = 0; // padding + buff[offset + 2] = 0; // padding + buff[offset + 3] = 0; // padding + + buff[offset + 4] = flags >> 24; // flags + buff[offset + 5] = flags >> 16; + buff[offset + 6] = flags >> 8; + buff[offset + 7] = flags; + + var n = payload.length; + + buff[offset + 8] = n; // length + + for (var i = 0; i < n; i++) { + buff[offset + 9 + i] = payload.charCodeAt(i); + } + + sock._sQlen += 9 + n; + sock.flush(); + }, + + enableContinuousUpdates: function (sock, enable, x, y, width, height) { + var buff = sock._sQ; + var offset = sock._sQlen; + + buff[offset] = 150; // msg-type + buff[offset + 1] = enable; // enable-flag + + buff[offset + 2] = x >> 8; // x + buff[offset + 3] = x; + buff[offset + 4] = y >> 8; // y + buff[offset + 5] = y; + buff[offset + 6] = width >> 8; // width + buff[offset + 7] = width; + buff[offset + 8] = height >> 8; // height + buff[offset + 9] = height; + + sock._sQlen += 10; + sock.flush(); + }, + + pixelFormat: function (sock, bpp, depth, true_color) { + var buff = sock._sQ; + var offset = sock._sQlen; + + buff[offset] = 0; // msg-type + + buff[offset + 1] = 0; // padding + buff[offset + 2] = 0; // padding + buff[offset + 3] = 0; // padding + + buff[offset + 4] = bpp * 8; // bits-per-pixel + buff[offset + 5] = depth * 8; // depth + buff[offset + 6] = 0; // little-endian + buff[offset + 7] = true_color ? 1 : 0; // true-color + + buff[offset + 8] = 0; // red-max + buff[offset + 9] = 255; // red-max + + buff[offset + 10] = 0; // green-max + buff[offset + 11] = 255; // green-max + + buff[offset + 12] = 0; // blue-max + buff[offset + 13] = 255; // blue-max + + buff[offset + 14] = 16; // red-shift + buff[offset + 15] = 8; // green-shift + buff[offset + 16] = 0; // blue-shift + + buff[offset + 17] = 0; // padding + buff[offset + 18] = 0; // padding + buff[offset + 19] = 0; // padding + + sock._sQlen += 20; + sock.flush(); + }, + + clientEncodings: function (sock, encodings, local_cursor, true_color) { + var buff = sock._sQ; + var offset = sock._sQlen; + + buff[offset] = 2; // msg-type + buff[offset + 1] = 0; // padding + + // offset + 2 and offset + 3 are encoding count + + var i, j = offset + 4, cnt = 0; + for (i = 0; i < encodings.length; i++) { + if (encodings[i][0] === "Cursor" && !local_cursor) { + Log.Debug("Skipping Cursor pseudo-encoding"); + } else if (encodings[i][0] === "TIGHT" && !true_color) { + // TODO: remove this when we have tight+non-true-color + Log.Warn("Skipping tight as it is only supported with true color"); + } else { + var enc = encodings[i][1]; + buff[j] = enc >> 24; + buff[j + 1] = enc >> 16; + buff[j + 2] = enc >> 8; + buff[j + 3] = enc; + + j += 4; + cnt++; + } + } + + buff[offset + 2] = cnt >> 8; + buff[offset + 3] = cnt; + + sock._sQlen += j - offset; + sock.flush(); + }, + + fbUpdateRequest: function (sock, incremental, x, y, w, h) { + var buff = sock._sQ; + var offset = sock._sQlen; + + if (typeof(x) === "undefined") { x = 0; } + if (typeof(y) === "undefined") { y = 0; } + + buff[offset] = 3; // msg-type + buff[offset + 1] = incremental ? 1 : 0; + + buff[offset + 2] = (x >> 8) & 0xFF; + buff[offset + 3] = x & 0xFF; + + buff[offset + 4] = (y >> 8) & 0xFF; + buff[offset + 5] = y & 0xFF; + + buff[offset + 6] = (w >> 8) & 0xFF; + buff[offset + 7] = w & 0xFF; + + buff[offset + 8] = (h >> 8) & 0xFF; + buff[offset + 9] = h & 0xFF; + + sock._sQlen += 10; + sock.flush(); + } +}; + +RFB.genDES = function (password, challenge) { + var passwd = []; + for (var i = 0; i < password.length; i++) { + passwd.push(password.charCodeAt(i)); + } + return (new DES(passwd)).encrypt(challenge); +}; + +RFB.encodingHandlers = { + RAW: function () { + if (this._FBU.lines === 0) { + this._FBU.lines = this._FBU.height; + } + + this._FBU.bytes = this._FBU.width * this._fb_Bpp; // at least a line + if (this._sock.rQwait("RAW", this._FBU.bytes)) { return false; } + var cur_y = this._FBU.y + (this._FBU.height - this._FBU.lines); + var curr_height = Math.min(this._FBU.lines, + Math.floor(this._sock.rQlen() / (this._FBU.width * this._fb_Bpp))); + this._display.blitImage(this._FBU.x, cur_y, this._FBU.width, + curr_height, this._sock.get_rQ(), + this._sock.get_rQi()); + this._sock.rQskipBytes(this._FBU.width * curr_height * this._fb_Bpp); + this._FBU.lines -= curr_height; + + if (this._FBU.lines > 0) { + this._FBU.bytes = this._FBU.width * this._fb_Bpp; // At least another line + } else { + this._FBU.rects--; + this._FBU.bytes = 0; + } + + return true; + }, + + COPYRECT: function () { + this._FBU.bytes = 4; + if (this._sock.rQwait("COPYRECT", 4)) { return false; } + this._display.copyImage(this._sock.rQshift16(), this._sock.rQshift16(), + this._FBU.x, this._FBU.y, this._FBU.width, + this._FBU.height); + + this._FBU.rects--; + this._FBU.bytes = 0; + return true; + }, + + RRE: function () { + var color; + if (this._FBU.subrects === 0) { + this._FBU.bytes = 4 + this._fb_Bpp; + if (this._sock.rQwait("RRE", 4 + this._fb_Bpp)) { return false; } + this._FBU.subrects = this._sock.rQshift32(); + color = this._sock.rQshiftBytes(this._fb_Bpp); // Background + this._display.fillRect(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, color); + } + + while (this._FBU.subrects > 0 && this._sock.rQlen() >= (this._fb_Bpp + 8)) { + color = this._sock.rQshiftBytes(this._fb_Bpp); + var x = this._sock.rQshift16(); + var y = this._sock.rQshift16(); + var width = this._sock.rQshift16(); + var height = this._sock.rQshift16(); + this._display.fillRect(this._FBU.x + x, this._FBU.y + y, width, height, color); + this._FBU.subrects--; + } + + if (this._FBU.subrects > 0) { + var chunk = Math.min(this._rre_chunk_sz, this._FBU.subrects); + this._FBU.bytes = (this._fb_Bpp + 8) * chunk; + } else { + this._FBU.rects--; + this._FBU.bytes = 0; + } + + return true; + }, + + HEXTILE: function () { + var rQ = this._sock.get_rQ(); + var rQi = this._sock.get_rQi(); + + if (this._FBU.tiles === 0) { + this._FBU.tiles_x = Math.ceil(this._FBU.width / 16); + this._FBU.tiles_y = Math.ceil(this._FBU.height / 16); + this._FBU.total_tiles = this._FBU.tiles_x * this._FBU.tiles_y; + this._FBU.tiles = this._FBU.total_tiles; + } + + while (this._FBU.tiles > 0) { + this._FBU.bytes = 1; + if (this._sock.rQwait("HEXTILE subencoding", this._FBU.bytes)) { return false; } + var subencoding = rQ[rQi]; // Peek + if (subencoding > 30) { // Raw + this._fail("Unexpected server message", + "Illegal hextile subencoding: " + subencoding); + return false; + } + + var subrects = 0; + var curr_tile = this._FBU.total_tiles - this._FBU.tiles; + var tile_x = curr_tile % this._FBU.tiles_x; + var tile_y = Math.floor(curr_tile / this._FBU.tiles_x); + var x = this._FBU.x + tile_x * 16; + var y = this._FBU.y + tile_y * 16; + var w = Math.min(16, (this._FBU.x + this._FBU.width) - x); + var h = Math.min(16, (this._FBU.y + this._FBU.height) - y); + + // Figure out how much we are expecting + if (subencoding & 0x01) { // Raw + this._FBU.bytes += w * h * this._fb_Bpp; + } else { + if (subencoding & 0x02) { // Background + this._FBU.bytes += this._fb_Bpp; + } + if (subencoding & 0x04) { // Foreground + this._FBU.bytes += this._fb_Bpp; + } + if (subencoding & 0x08) { // AnySubrects + this._FBU.bytes++; // Since we aren't shifting it off + if (this._sock.rQwait("hextile subrects header", this._FBU.bytes)) { return false; } + subrects = rQ[rQi + this._FBU.bytes - 1]; // Peek + if (subencoding & 0x10) { // SubrectsColoured + this._FBU.bytes += subrects * (this._fb_Bpp + 2); } else { - this._display.fillRect(x, y, w, h, this._FBU.background); + this._FBU.bytes += subrects * 2; } - } else if (this._FBU.subencoding & 0x01) { // Raw - this._display.blitImage(x, y, w, h, rQ, rQi); - rQi += this._FBU.bytes - 1; + } + } + + if (this._sock.rQwait("hextile", this._FBU.bytes)) { return false; } + + // We know the encoding and have a whole tile + this._FBU.subencoding = rQ[rQi]; + rQi++; + if (this._FBU.subencoding === 0) { + if (this._FBU.lastsubencoding & 0x01) { + // Weird: ignore blanks are RAW + Log.Debug(" Ignoring blank after RAW"); } else { - if (this._FBU.subencoding & 0x02) { // Background - if (this._fb_Bpp == 1) { - this._FBU.background = rQ[rQi]; - } else { - // fb_Bpp is 4 - this._FBU.background = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]]; - } - rQi += this._fb_Bpp; + this._display.fillRect(x, y, w, h, this._FBU.background); + } + } else if (this._FBU.subencoding & 0x01) { // Raw + this._display.blitImage(x, y, w, h, rQ, rQi); + rQi += this._FBU.bytes - 1; + } else { + if (this._FBU.subencoding & 0x02) { // Background + if (this._fb_Bpp == 1) { + this._FBU.background = rQ[rQi]; + } else { + // fb_Bpp is 4 + this._FBU.background = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]]; } - if (this._FBU.subencoding & 0x04) { // Foreground - if (this._fb_Bpp == 1) { - this._FBU.foreground = rQ[rQi]; - } else { - // this._fb_Bpp is 4 - this._FBU.foreground = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]]; - } - rQi += this._fb_Bpp; + rQi += this._fb_Bpp; + } + if (this._FBU.subencoding & 0x04) { // Foreground + if (this._fb_Bpp == 1) { + this._FBU.foreground = rQ[rQi]; + } else { + // this._fb_Bpp is 4 + this._FBU.foreground = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]]; } + rQi += this._fb_Bpp; + } - this._display.startTile(x, y, w, h, this._FBU.background); - if (this._FBU.subencoding & 0x08) { // AnySubrects - subrects = rQ[rQi]; - rQi++; + this._display.startTile(x, y, w, h, this._FBU.background); + if (this._FBU.subencoding & 0x08) { // AnySubrects + subrects = rQ[rQi]; + rQi++; - for (var s = 0; s < subrects; s++) { - var color; - if (this._FBU.subencoding & 0x10) { // SubrectsColoured - if (this._fb_Bpp === 1) { - color = rQ[rQi]; - } else { - // _fb_Bpp is 4 - color = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]]; - } - rQi += this._fb_Bpp; + for (var s = 0; s < subrects; s++) { + var color; + if (this._FBU.subencoding & 0x10) { // SubrectsColoured + if (this._fb_Bpp === 1) { + color = rQ[rQi]; } else { - color = this._FBU.foreground; + // _fb_Bpp is 4 + color = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]]; } - var xy = rQ[rQi]; - rQi++; - var sx = (xy >> 4); - var sy = (xy & 0x0f); - - var wh = rQ[rQi]; - rQi++; - var sw = (wh >> 4) + 1; - var sh = (wh & 0x0f) + 1; - - this._display.subTile(sx, sy, sw, sh, color); + rQi += this._fb_Bpp; + } else { + color = this._FBU.foreground; } + var xy = rQ[rQi]; + rQi++; + var sx = (xy >> 4); + var sy = (xy & 0x0f); + + var wh = rQ[rQi]; + rQi++; + var sw = (wh >> 4) + 1; + var sh = (wh & 0x0f) + 1; + + this._display.subTile(sx, sy, sw, sh, color); } - this._display.finishTile(); } - this._sock.set_rQi(rQi); - this._FBU.lastsubencoding = this._FBU.subencoding; - this._FBU.bytes = 0; - this._FBU.tiles--; + this._display.finishTile(); } + this._sock.set_rQi(rQi); + this._FBU.lastsubencoding = this._FBU.subencoding; + this._FBU.bytes = 0; + this._FBU.tiles--; + } - if (this._FBU.tiles === 0) { - this._FBU.rects--; - } + if (this._FBU.tiles === 0) { + this._FBU.rects--; + } - return true; - }, + return true; + }, - getTightCLength: function (arr) { - var header = 1, data = 0; - data += arr[0] & 0x7f; - if (arr[0] & 0x80) { + getTightCLength: function (arr) { + var header = 1, data = 0; + data += arr[0] & 0x7f; + if (arr[0] & 0x80) { + header++; + data += (arr[1] & 0x7f) << 7; + if (arr[1] & 0x80) { header++; - data += (arr[1] & 0x7f) << 7; - if (arr[1] & 0x80) { - header++; - data += arr[2] << 14; + data += arr[2] << 14; + } + } + return [header, data]; + }, + + display_tight: function (isTightPNG) { + if (this._fb_depth === 1) { + this._fail("Internal error", + "Tight protocol handler only implements " + + "true color mode"); + } + + this._FBU.bytes = 1; // compression-control byte + if (this._sock.rQwait("TIGHT compression-control", this._FBU.bytes)) { return false; } + + var checksum = function (data) { + var sum = 0; + for (var i = 0; i < data.length; i++) { + sum += data[i]; + if (sum > 65536) sum -= 65536; + } + return sum; + }; + + var resetStreams = 0; + var streamId = -1; + var decompress = function (data, expected) { + for (var i = 0; i < 4; i++) { + if ((resetStreams >> i) & 1) { + this._FBU.zlibs[i].reset(); + Log.Info("Reset zlib stream " + i); } } - return [header, data]; - }, - display_tight: function (isTightPNG) { - if (this._fb_depth === 1) { - this._fail("Internal error", - "Tight protocol handler only implements " + - "true color mode"); - } + //var uncompressed = this._FBU.zlibs[streamId].uncompress(data, 0); + var uncompressed = this._FBU.zlibs[streamId].inflate(data, true, expected); + /*if (uncompressed.status !== 0) { + Log.Error("Invalid data in zlib stream"); + }*/ - this._FBU.bytes = 1; // compression-control byte - if (this._sock.rQwait("TIGHT compression-control", this._FBU.bytes)) { return false; } + //return uncompressed.data; + return uncompressed; + }.bind(this); - var checksum = function (data) { - var sum = 0; - for (var i = 0; i < data.length; i++) { - sum += data[i]; - if (sum > 65536) sum -= 65536; - } - return sum; - }; - - var resetStreams = 0; - var streamId = -1; - var decompress = function (data, expected) { - for (var i = 0; i < 4; i++) { - if ((resetStreams >> i) & 1) { - this._FBU.zlibs[i].reset(); - Util.Info("Reset zlib stream " + i); - } - } - - //var uncompressed = this._FBU.zlibs[streamId].uncompress(data, 0); - var uncompressed = this._FBU.zlibs[streamId].inflate(data, true, expected); - /*if (uncompressed.status !== 0) { - Util.Error("Invalid data in zlib stream"); - }*/ - - //return uncompressed.data; - return uncompressed; - }.bind(this); - - var indexedToRGBX2Color = function (data, palette, width, height) { - // Convert indexed (palette based) image data to RGB - // TODO: reduce number of calculations inside loop - var dest = this._destBuff; - var w = Math.floor((width + 7) / 8); - var w1 = Math.floor(width / 8); - - /*for (var y = 0; y < height; y++) { - var b, x, dp, sp; - var yoffset = y * width; - var ybitoffset = y * w; - var xoffset, targetbyte; - for (x = 0; x < w1; x++) { - xoffset = yoffset + x * 8; - targetbyte = data[ybitoffset + x]; - for (b = 7; b >= 0; b--) { - dp = (xoffset + 7 - b) * 3; - sp = (targetbyte >> b & 1) * 3; - dest[dp] = palette[sp]; - dest[dp + 1] = palette[sp + 1]; - dest[dp + 2] = palette[sp + 2]; - } - } + var indexedToRGBX2Color = function (data, palette, width, height) { + // Convert indexed (palette based) image data to RGB + // TODO: reduce number of calculations inside loop + var dest = this._destBuff; + var w = Math.floor((width + 7) / 8); + var w1 = Math.floor(width / 8); + /*for (var y = 0; y < height; y++) { + var b, x, dp, sp; + var yoffset = y * width; + var ybitoffset = y * w; + var xoffset, targetbyte; + for (x = 0; x < w1; x++) { xoffset = yoffset + x * 8; targetbyte = data[ybitoffset + x]; - for (b = 7; b >= 8 - width % 8; b--) { + for (b = 7; b >= 0; b--) { dp = (xoffset + 7 - b) * 3; sp = (targetbyte >> b & 1) * 3; dest[dp] = palette[sp]; dest[dp + 1] = palette[sp + 1]; dest[dp + 2] = palette[sp + 2]; } - }*/ + } - for (var y = 0; y < height; y++) { - var b, x, dp, sp; - for (x = 0; x < w1; x++) { - for (b = 7; b >= 0; b--) { - dp = (y * width + x * 8 + 7 - b) * 4; - sp = (data[y * w + x] >> b & 1) * 3; - dest[dp] = palette[sp]; - dest[dp + 1] = palette[sp + 1]; - dest[dp + 2] = palette[sp + 2]; - dest[dp + 3] = 255; - } - } + xoffset = yoffset + x * 8; + targetbyte = data[ybitoffset + x]; + for (b = 7; b >= 8 - width % 8; b--) { + dp = (xoffset + 7 - b) * 3; + sp = (targetbyte >> b & 1) * 3; + dest[dp] = palette[sp]; + dest[dp + 1] = palette[sp + 1]; + dest[dp + 2] = palette[sp + 2]; + } + }*/ - for (b = 7; b >= 8 - width % 8; b--) { + for (var y = 0; y < height; y++) { + var b, x, dp, sp; + for (x = 0; x < w1; x++) { + for (b = 7; b >= 0; b--) { dp = (y * width + x * 8 + 7 - b) * 4; sp = (data[y * w + x] >> b & 1) * 3; dest[dp] = palette[sp]; @@ -2121,356 +2110,365 @@ } } - return dest; - }.bind(this); - - var indexedToRGBX = function (data, palette, width, height) { - // Convert indexed (palette based) image data to RGB - var dest = this._destBuff; - var total = width * height * 4; - for (var i = 0, j = 0; i < total; i += 4, j++) { - var sp = data[j] * 3; - dest[i] = palette[sp]; - dest[i + 1] = palette[sp + 1]; - dest[i + 2] = palette[sp + 2]; - dest[i + 3] = 255; + for (b = 7; b >= 8 - width % 8; b--) { + dp = (y * width + x * 8 + 7 - b) * 4; + sp = (data[y * w + x] >> b & 1) * 3; + dest[dp] = palette[sp]; + dest[dp + 1] = palette[sp + 1]; + dest[dp + 2] = palette[sp + 2]; + dest[dp + 3] = 255; } - - return dest; - }.bind(this); - - var rQi = this._sock.get_rQi(); - var rQ = this._sock.rQwhole(); - var cmode, data; - var cl_header, cl_data; - - var handlePalette = function () { - var numColors = rQ[rQi + 2] + 1; - var paletteSize = numColors * this._fb_depth; - this._FBU.bytes += paletteSize; - if (this._sock.rQwait("TIGHT palette " + cmode, this._FBU.bytes)) { return false; } - - var bpp = (numColors <= 2) ? 1 : 8; - var rowSize = Math.floor((this._FBU.width * bpp + 7) / 8); - var raw = false; - if (rowSize * this._FBU.height < 12) { - raw = true; - cl_header = 0; - cl_data = rowSize * this._FBU.height; - //clength = [0, rowSize * this._FBU.height]; - } else { - // begin inline getTightCLength (returning two-item arrays is bad for performance with GC) - var cl_offset = rQi + 3 + paletteSize; - cl_header = 1; - cl_data = 0; - cl_data += rQ[cl_offset] & 0x7f; - if (rQ[cl_offset] & 0x80) { - cl_header++; - cl_data += (rQ[cl_offset + 1] & 0x7f) << 7; - if (rQ[cl_offset + 1] & 0x80) { - cl_header++; - cl_data += rQ[cl_offset + 2] << 14; - } - } - // end inline getTightCLength - } - - this._FBU.bytes += cl_header + cl_data; - if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; } - - // Shift ctl, filter id, num colors, palette entries, and clength off - this._sock.rQskipBytes(3); - //var palette = this._sock.rQshiftBytes(paletteSize); - this._sock.rQshiftTo(this._paletteBuff, paletteSize); - this._sock.rQskipBytes(cl_header); - - if (raw) { - data = this._sock.rQshiftBytes(cl_data); - } else { - data = decompress(this._sock.rQshiftBytes(cl_data), rowSize * this._FBU.height); - } - - // Convert indexed (palette based) image data to RGB - var rgbx; - if (numColors == 2) { - rgbx = indexedToRGBX2Color(data, this._paletteBuff, this._FBU.width, this._FBU.height); - this._display.blitRgbxImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, rgbx, 0, false); - } else { - rgbx = indexedToRGBX(data, this._paletteBuff, this._FBU.width, this._FBU.height); - this._display.blitRgbxImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, rgbx, 0, false); - } - - - return true; - }.bind(this); - - var handleCopy = function () { - var raw = false; - var uncompressedSize = this._FBU.width * this._FBU.height * this._fb_depth; - if (uncompressedSize < 12) { - raw = true; - cl_header = 0; - cl_data = uncompressedSize; - } else { - // begin inline getTightCLength (returning two-item arrays is for peformance with GC) - var cl_offset = rQi + 1; - cl_header = 1; - cl_data = 0; - cl_data += rQ[cl_offset] & 0x7f; - if (rQ[cl_offset] & 0x80) { - cl_header++; - cl_data += (rQ[cl_offset + 1] & 0x7f) << 7; - if (rQ[cl_offset + 1] & 0x80) { - cl_header++; - cl_data += rQ[cl_offset + 2] << 14; - } - } - // end inline getTightCLength - } - this._FBU.bytes = 1 + cl_header + cl_data; - if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; } - - // Shift ctl, clength off - this._sock.rQshiftBytes(1 + cl_header); - - if (raw) { - data = this._sock.rQshiftBytes(cl_data); - } else { - data = decompress(this._sock.rQshiftBytes(cl_data), uncompressedSize); - } - - this._display.blitRgbImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, data, 0, false); - - return true; - }.bind(this); - - var ctl = this._sock.rQpeek8(); - - // Keep tight reset bits - resetStreams = ctl & 0xF; - - // Figure out filter - ctl = ctl >> 4; - streamId = ctl & 0x3; - - if (ctl === 0x08) cmode = "fill"; - else if (ctl === 0x09) cmode = "jpeg"; - else if (ctl === 0x0A) cmode = "png"; - else if (ctl & 0x04) cmode = "filter"; - else if (ctl < 0x04) cmode = "copy"; - else return this._fail("Unexpected server message", - "Illegal tight compression received, " + - "ctl: " + ctl); - - if (isTightPNG && (cmode === "filter" || cmode === "copy")) { - return this._fail("Unexpected server message", - "filter/copy received in tightPNG mode"); } - switch (cmode) { - // fill use fb_depth because TPIXELs drop the padding byte - case "fill": // TPIXEL - this._FBU.bytes += this._fb_depth; - break; - case "jpeg": // max clength - this._FBU.bytes += 3; - break; - case "png": // max clength - this._FBU.bytes += 3; - break; - case "filter": // filter id + num colors if palette - this._FBU.bytes += 2; - break; - case "copy": - break; + return dest; + }.bind(this); + + var indexedToRGBX = function (data, palette, width, height) { + // Convert indexed (palette based) image data to RGB + var dest = this._destBuff; + var total = width * height * 4; + for (var i = 0, j = 0; i < total; i += 4, j++) { + var sp = data[j] * 3; + dest[i] = palette[sp]; + dest[i + 1] = palette[sp + 1]; + dest[i + 2] = palette[sp + 2]; + dest[i + 3] = 255; } + return dest; + }.bind(this); + + var rQi = this._sock.get_rQi(); + var rQ = this._sock.rQwhole(); + var cmode, data; + var cl_header, cl_data; + + var handlePalette = function () { + var numColors = rQ[rQi + 2] + 1; + var paletteSize = numColors * this._fb_depth; + this._FBU.bytes += paletteSize; + if (this._sock.rQwait("TIGHT palette " + cmode, this._FBU.bytes)) { return false; } + + var bpp = (numColors <= 2) ? 1 : 8; + var rowSize = Math.floor((this._FBU.width * bpp + 7) / 8); + var raw = false; + if (rowSize * this._FBU.height < 12) { + raw = true; + cl_header = 0; + cl_data = rowSize * this._FBU.height; + //clength = [0, rowSize * this._FBU.height]; + } else { + // begin inline getTightCLength (returning two-item arrays is bad for performance with GC) + var cl_offset = rQi + 3 + paletteSize; + cl_header = 1; + cl_data = 0; + cl_data += rQ[cl_offset] & 0x7f; + if (rQ[cl_offset] & 0x80) { + cl_header++; + cl_data += (rQ[cl_offset + 1] & 0x7f) << 7; + if (rQ[cl_offset + 1] & 0x80) { + cl_header++; + cl_data += rQ[cl_offset + 2] << 14; + } + } + // end inline getTightCLength + } + + this._FBU.bytes += cl_header + cl_data; if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; } - // Determine FBU.bytes - switch (cmode) { - case "fill": - // skip ctl byte - this._display.fillRect(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, [rQ[rQi + 3], rQ[rQi + 2], rQ[rQi + 1]], false); - this._sock.rQskipBytes(4); - break; - case "png": - case "jpeg": - // begin inline getTightCLength (returning two-item arrays is for peformance with GC) - var cl_offset = rQi + 1; - cl_header = 1; - cl_data = 0; - cl_data += rQ[cl_offset] & 0x7f; - if (rQ[cl_offset] & 0x80) { + // Shift ctl, filter id, num colors, palette entries, and clength off + this._sock.rQskipBytes(3); + //var palette = this._sock.rQshiftBytes(paletteSize); + this._sock.rQshiftTo(this._paletteBuff, paletteSize); + this._sock.rQskipBytes(cl_header); + + if (raw) { + data = this._sock.rQshiftBytes(cl_data); + } else { + data = decompress(this._sock.rQshiftBytes(cl_data), rowSize * this._FBU.height); + } + + // Convert indexed (palette based) image data to RGB + var rgbx; + if (numColors == 2) { + rgbx = indexedToRGBX2Color(data, this._paletteBuff, this._FBU.width, this._FBU.height); + this._display.blitRgbxImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, rgbx, 0, false); + } else { + rgbx = indexedToRGBX(data, this._paletteBuff, this._FBU.width, this._FBU.height); + this._display.blitRgbxImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, rgbx, 0, false); + } + + + return true; + }.bind(this); + + var handleCopy = function () { + var raw = false; + var uncompressedSize = this._FBU.width * this._FBU.height * this._fb_depth; + if (uncompressedSize < 12) { + raw = true; + cl_header = 0; + cl_data = uncompressedSize; + } else { + // begin inline getTightCLength (returning two-item arrays is for peformance with GC) + var cl_offset = rQi + 1; + cl_header = 1; + cl_data = 0; + cl_data += rQ[cl_offset] & 0x7f; + if (rQ[cl_offset] & 0x80) { + cl_header++; + cl_data += (rQ[cl_offset + 1] & 0x7f) << 7; + if (rQ[cl_offset + 1] & 0x80) { cl_header++; - cl_data += (rQ[cl_offset + 1] & 0x7f) << 7; - if (rQ[cl_offset + 1] & 0x80) { - cl_header++; - cl_data += rQ[cl_offset + 2] << 14; - } + cl_data += rQ[cl_offset + 2] << 14; } - // end inline getTightCLength - this._FBU.bytes = 1 + cl_header + cl_data; // ctl + clength size + jpeg-data - if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; } - - // We have everything, render it - this._sock.rQskipBytes(1 + cl_header); // shift off clt + compact length - data = this._sock.rQshiftBytes(cl_data); - this._display.imageRect(this._FBU.x, this._FBU.y, "image/" + cmode, data); - break; - case "filter": - var filterId = rQ[rQi + 1]; - if (filterId === 1) { - if (!handlePalette()) { return false; } - } else { - // Filter 0, Copy could be valid here, but servers don't send it as an explicit filter - // Filter 2, Gradient is valid but not use if jpeg is enabled - this._fail("Unexpected server message", - "Unsupported tight subencoding received, " + - "filter: " + filterId); - } - break; - case "copy": - if (!handleCopy()) { return false; } - break; - } - - - this._FBU.bytes = 0; - this._FBU.rects--; - - return true; - }, - - TIGHT: function () { return this._encHandlers.display_tight(false); }, - TIGHT_PNG: function () { return this._encHandlers.display_tight(true); }, - - last_rect: function () { - this._FBU.rects = 0; - return true; - }, - - handle_FB_resize: function () { - this._fb_width = this._FBU.width; - this._fb_height = this._FBU.height; - this._destBuff = new Uint8Array(this._fb_width * this._fb_height * 4); - this._display.resize(this._fb_width, this._fb_height); - this._onFBResize(this, this._fb_width, this._fb_height); - this._timing.fbu_rt_start = (new Date()).getTime(); - this._updateContinuousUpdates(); - - this._FBU.bytes = 0; - this._FBU.rects -= 1; - return true; - }, - - ExtendedDesktopSize: function () { - this._FBU.bytes = 1; - if (this._sock.rQwait("ExtendedDesktopSize", this._FBU.bytes)) { return false; } - - this._supportsSetDesktopSize = true; - var number_of_screens = this._sock.rQpeek8(); - - this._FBU.bytes = 4 + (number_of_screens * 16); - if (this._sock.rQwait("ExtendedDesktopSize", this._FBU.bytes)) { return false; } - - this._sock.rQskipBytes(1); // number-of-screens - this._sock.rQskipBytes(3); // padding - - for (var i = 0; i < number_of_screens; i += 1) { - // Save the id and flags of the first screen - if (i === 0) { - this._screen_id = this._sock.rQshiftBytes(4); // id - this._sock.rQskipBytes(2); // x-position - this._sock.rQskipBytes(2); // y-position - this._sock.rQskipBytes(2); // width - this._sock.rQskipBytes(2); // height - this._screen_flags = this._sock.rQshiftBytes(4); // flags - } else { - this._sock.rQskipBytes(16); } + // end inline getTightCLength + } + this._FBU.bytes = 1 + cl_header + cl_data; + if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; } + + // Shift ctl, clength off + this._sock.rQshiftBytes(1 + cl_header); + + if (raw) { + data = this._sock.rQshiftBytes(cl_data); + } else { + data = decompress(this._sock.rQshiftBytes(cl_data), uncompressedSize); } - /* - * The x-position indicates the reason for the change: - * - * 0 - server resized on its own - * 1 - this client requested the resize - * 2 - another client requested the resize - */ + this._display.blitRgbImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, data, 0, false); - // We need to handle errors when we requested the resize. - if (this._FBU.x === 1 && this._FBU.y !== 0) { - var msg = ""; - // The y-position indicates the status code from the server - switch (this._FBU.y) { - case 1: - msg = "Resize is administratively prohibited"; - break; - case 2: - msg = "Out of resources"; - break; - case 3: - msg = "Invalid screen layout"; - break; - default: - msg = "Unknown reason"; - break; - } - this._notification("Server did not accept the resize request: " - + msg, 'normal'); - return true; - } - - this._encHandlers.handle_FB_resize(); return true; - }, + }.bind(this); - DesktopSize: function () { - this._encHandlers.handle_FB_resize(); - return true; - }, + var ctl = this._sock.rQpeek8(); - Cursor: function () { - Util.Debug(">> set_cursor"); - var x = this._FBU.x; // hotspot-x - var y = this._FBU.y; // hotspot-y - var w = this._FBU.width; - var h = this._FBU.height; + // Keep tight reset bits + resetStreams = ctl & 0xF; - var pixelslength = w * h * this._fb_Bpp; - var masklength = Math.floor((w + 7) / 8) * h; + // Figure out filter + ctl = ctl >> 4; + streamId = ctl & 0x3; - this._FBU.bytes = pixelslength + masklength; - if (this._sock.rQwait("cursor encoding", this._FBU.bytes)) { return false; } + if (ctl === 0x08) cmode = "fill"; + else if (ctl === 0x09) cmode = "jpeg"; + else if (ctl === 0x0A) cmode = "png"; + else if (ctl & 0x04) cmode = "filter"; + else if (ctl < 0x04) cmode = "copy"; + else return this._fail("Unexpected server message", + "Illegal tight compression received, " + + "ctl: " + ctl); - this._display.changeCursor(this._sock.rQshiftBytes(pixelslength), - this._sock.rQshiftBytes(masklength), - x, y, w, h); - - this._FBU.bytes = 0; - this._FBU.rects--; - - Util.Debug("<< set_cursor"); - return true; - }, - - QEMUExtendedKeyEvent: function () { - this._FBU.rects--; - - var keyboardEvent = document.createEvent("keyboardEvent"); - if (keyboardEvent.code !== undefined) { - this._qemuExtKeyEventSupported = true; - this._keyboard.setQEMUVNCKeyboardHandler(); - } - }, - - JPEG_quality_lo: function () { - Util.Error("Server sent jpeg_quality pseudo-encoding"); - }, - - compress_lo: function () { - Util.Error("Server sent compress level pseudo-encoding"); + if (isTightPNG && (cmode === "filter" || cmode === "copy")) { + return this._fail("Unexpected server message", + "filter/copy received in tightPNG mode"); } - }; -})(); + + switch (cmode) { + // fill use fb_depth because TPIXELs drop the padding byte + case "fill": // TPIXEL + this._FBU.bytes += this._fb_depth; + break; + case "jpeg": // max clength + this._FBU.bytes += 3; + break; + case "png": // max clength + this._FBU.bytes += 3; + break; + case "filter": // filter id + num colors if palette + this._FBU.bytes += 2; + break; + case "copy": + break; + } + + if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; } + + // Determine FBU.bytes + switch (cmode) { + case "fill": + // skip ctl byte + this._display.fillRect(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, [rQ[rQi + 3], rQ[rQi + 2], rQ[rQi + 1]], false); + this._sock.rQskipBytes(4); + break; + case "png": + case "jpeg": + // begin inline getTightCLength (returning two-item arrays is for peformance with GC) + var cl_offset = rQi + 1; + cl_header = 1; + cl_data = 0; + cl_data += rQ[cl_offset] & 0x7f; + if (rQ[cl_offset] & 0x80) { + cl_header++; + cl_data += (rQ[cl_offset + 1] & 0x7f) << 7; + if (rQ[cl_offset + 1] & 0x80) { + cl_header++; + cl_data += rQ[cl_offset + 2] << 14; + } + } + // end inline getTightCLength + this._FBU.bytes = 1 + cl_header + cl_data; // ctl + clength size + jpeg-data + if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; } + + // We have everything, render it + this._sock.rQskipBytes(1 + cl_header); // shift off clt + compact length + data = this._sock.rQshiftBytes(cl_data); + this._display.imageRect(this._FBU.x, this._FBU.y, "image/" + cmode, data); + break; + case "filter": + var filterId = rQ[rQi + 1]; + if (filterId === 1) { + if (!handlePalette()) { return false; } + } else { + // Filter 0, Copy could be valid here, but servers don't send it as an explicit filter + // Filter 2, Gradient is valid but not use if jpeg is enabled + this._fail("Unexpected server message", + "Unsupported tight subencoding received, " + + "filter: " + filterId); + } + break; + case "copy": + if (!handleCopy()) { return false; } + break; + } + + + this._FBU.bytes = 0; + this._FBU.rects--; + + return true; + }, + + TIGHT: function () { return this._encHandlers.display_tight(false); }, + TIGHT_PNG: function () { return this._encHandlers.display_tight(true); }, + + last_rect: function () { + this._FBU.rects = 0; + return true; + }, + + handle_FB_resize: function () { + this._fb_width = this._FBU.width; + this._fb_height = this._FBU.height; + this._destBuff = new Uint8Array(this._fb_width * this._fb_height * 4); + this._display.resize(this._fb_width, this._fb_height); + this._onFBResize(this, this._fb_width, this._fb_height); + this._timing.fbu_rt_start = (new Date()).getTime(); + this._updateContinuousUpdates(); + + this._FBU.bytes = 0; + this._FBU.rects -= 1; + return true; + }, + + ExtendedDesktopSize: function () { + this._FBU.bytes = 1; + if (this._sock.rQwait("ExtendedDesktopSize", this._FBU.bytes)) { return false; } + + this._supportsSetDesktopSize = true; + var number_of_screens = this._sock.rQpeek8(); + + this._FBU.bytes = 4 + (number_of_screens * 16); + if (this._sock.rQwait("ExtendedDesktopSize", this._FBU.bytes)) { return false; } + + this._sock.rQskipBytes(1); // number-of-screens + this._sock.rQskipBytes(3); // padding + + for (var i = 0; i < number_of_screens; i += 1) { + // Save the id and flags of the first screen + if (i === 0) { + this._screen_id = this._sock.rQshiftBytes(4); // id + this._sock.rQskipBytes(2); // x-position + this._sock.rQskipBytes(2); // y-position + this._sock.rQskipBytes(2); // width + this._sock.rQskipBytes(2); // height + this._screen_flags = this._sock.rQshiftBytes(4); // flags + } else { + this._sock.rQskipBytes(16); + } + } + + /* + * The x-position indicates the reason for the change: + * + * 0 - server resized on its own + * 1 - this client requested the resize + * 2 - another client requested the resize + */ + + // We need to handle errors when we requested the resize. + if (this._FBU.x === 1 && this._FBU.y !== 0) { + var msg = ""; + // The y-position indicates the status code from the server + switch (this._FBU.y) { + case 1: + msg = "Resize is administratively prohibited"; + break; + case 2: + msg = "Out of resources"; + break; + case 3: + msg = "Invalid screen layout"; + break; + default: + msg = "Unknown reason"; + break; + } + this._notification("Server did not accept the resize request: " + + msg, 'normal'); + return true; + } + + this._encHandlers.handle_FB_resize(); + return true; + }, + + DesktopSize: function () { + this._encHandlers.handle_FB_resize(); + return true; + }, + + Cursor: function () { + Log.Debug(">> set_cursor"); + var x = this._FBU.x; // hotspot-x + var y = this._FBU.y; // hotspot-y + var w = this._FBU.width; + var h = this._FBU.height; + + var pixelslength = w * h * this._fb_Bpp; + var masklength = Math.floor((w + 7) / 8) * h; + + this._FBU.bytes = pixelslength + masklength; + if (this._sock.rQwait("cursor encoding", this._FBU.bytes)) { return false; } + + this._display.changeCursor(this._sock.rQshiftBytes(pixelslength), + this._sock.rQshiftBytes(masklength), + x, y, w, h); + + this._FBU.bytes = 0; + this._FBU.rects--; + + Log.Debug("<< set_cursor"); + return true; + }, + + QEMUExtendedKeyEvent: function () { + this._FBU.rects--; + + var keyboardEvent = document.createEvent("keyboardEvent"); + if (keyboardEvent.code !== undefined) { + this._qemuExtKeyEventSupported = true; + this._keyboard.setQEMUVNCKeyboardHandler(); + } + }, + + JPEG_quality_lo: function () { + Log.Error("Server sent jpeg_quality pseudo-encoding"); + }, + + compress_lo: function () { + Log.Error("Server sent compress level pseudo-encoding"); + } +}; diff --git a/core/util.js b/core/util.js deleted file mode 100644 index 8edaace7..00000000 --- a/core/util.js +++ /dev/null @@ -1,621 +0,0 @@ -/* - * noVNC: HTML5 VNC client - * Copyright (C) 2012 Joel Martin - * Licensed under MPL 2.0 (see LICENSE.txt) - * - * See README.md for usage and integration instructions. - */ - -/* jshint white: false, nonstandard: true */ -/*global window, console, document, navigator, ActiveXObject, INCLUDE_URI */ - -var Util = {}; - -/* - * ------------------------------------------------------ - * Namespaced in Util - * ------------------------------------------------------ - */ - -/* - * Logging/debug routines - */ - -Util._log_level = 'warn'; -Util.init_logging = function (level) { - "use strict"; - if (typeof level === 'undefined') { - level = Util._log_level; - } else { - Util._log_level = level; - } - - Util.Debug = Util.Info = Util.Warn = Util.Error = function (msg) {}; - if (typeof window.console !== "undefined") { - /* jshint -W086 */ - switch (level) { - case 'debug': - Util.Debug = console.debug.bind(window.console); - case 'info': - Util.Info = console.info.bind(window.console); - case 'warn': - Util.Warn = console.warn.bind(window.console); - case 'error': - Util.Error = console.error.bind(window.console); - case 'none': - break; - default: - throw new Error("invalid logging type '" + level + "'"); - } - /* jshint +W086 */ - } -}; -Util.get_logging = function () { - return Util._log_level; -}; -// Initialize logging level -Util.init_logging(); - -Util.make_property = function (proto, name, mode, type) { - "use strict"; - - var getter; - if (type === 'arr') { - getter = function (idx) { - if (typeof idx !== 'undefined') { - return this['_' + name][idx]; - } else { - return this['_' + name]; - } - }; - } else { - getter = function () { - return this['_' + name]; - }; - } - - var make_setter = function (process_val) { - if (process_val) { - return function (val, idx) { - if (typeof idx !== 'undefined') { - this['_' + name][idx] = process_val(val); - } else { - this['_' + name] = process_val(val); - } - }; - } else { - return function (val, idx) { - if (typeof idx !== 'undefined') { - this['_' + name][idx] = val; - } else { - this['_' + name] = val; - } - }; - } - }; - - var setter; - if (type === 'bool') { - setter = make_setter(function (val) { - if (!val || (val in {'0': 1, 'no': 1, 'false': 1})) { - return false; - } else { - return true; - } - }); - } else if (type === 'int') { - setter = make_setter(function (val) { return parseInt(val, 10); }); - } else if (type === 'float') { - setter = make_setter(parseFloat); - } else if (type === 'str') { - setter = make_setter(String); - } else if (type === 'func') { - setter = make_setter(function (val) { - if (!val) { - return function () {}; - } else { - return val; - } - }); - } else if (type === 'arr' || type === 'dom' || type == 'raw') { - setter = make_setter(); - } else { - throw new Error('Unknown property type ' + type); // some sanity checking - } - - // set the getter - if (typeof proto['get_' + name] === 'undefined') { - proto['get_' + name] = getter; - } - - // set the setter if needed - if (typeof proto['set_' + name] === 'undefined') { - if (mode === 'rw') { - proto['set_' + name] = setter; - } else if (mode === 'wo') { - proto['set_' + name] = function (val, idx) { - if (typeof this['_' + name] !== 'undefined') { - throw new Error(name + " can only be set once"); - } - setter.call(this, val, idx); - }; - } - } - - // make a special setter that we can use in set defaults - proto['_raw_set_' + name] = function (val, idx) { - setter.call(this, val, idx); - //delete this['_init_set_' + name]; // remove it after use - }; -}; - -Util.make_properties = function (constructor, arr) { - "use strict"; - for (var i = 0; i < arr.length; i++) { - Util.make_property(constructor.prototype, arr[i][0], arr[i][1], arr[i][2]); - } -}; - -Util.set_defaults = function (obj, conf, defaults) { - var defaults_keys = Object.keys(defaults); - var conf_keys = Object.keys(conf); - var keys_obj = {}; - var i; - for (i = 0; i < defaults_keys.length; i++) { keys_obj[defaults_keys[i]] = 1; } - for (i = 0; i < conf_keys.length; i++) { keys_obj[conf_keys[i]] = 1; } - var keys = Object.keys(keys_obj); - - for (i = 0; i < keys.length; i++) { - var setter = obj['_raw_set_' + keys[i]]; - if (!setter) { - Util.Warn('Invalid property ' + keys[i]); - continue; - } - - if (keys[i] in conf) { - setter.call(obj, conf[keys[i]]); - } else { - setter.call(obj, defaults[keys[i]]); - } - } -}; - -/* - * Decode from UTF-8 - */ -Util.decodeUTF8 = function (utf8string) { - "use strict"; - return decodeURIComponent(escape(utf8string)); -}; - - - -/* - * Cross-browser routines - */ - -Util.getPointerEvent = function (e) { - return e.changedTouches ? e.changedTouches[0] : e.touches ? e.touches[0] : e; -}; - -Util.stopEvent = function (e) { - e.stopPropagation(); - e.preventDefault(); -}; - -// Touch detection -Util.isTouchDevice = ('ontouchstart' in document.documentElement) || - // requried for Chrome debugger - (document.ontouchstart !== undefined) || - // required for MS Surface - (navigator.maxTouchPoints > 0) || - (navigator.msMaxTouchPoints > 0); -window.addEventListener('touchstart', function onFirstTouch() { - Util.isTouchDevice = true; - window.removeEventListener('touchstart', onFirstTouch, false); -}, false); - -Util._cursor_uris_supported = null; - -Util.browserSupportsCursorURIs = function () { - if (Util._cursor_uris_supported === null) { - try { - var target = document.createElement('canvas'); - target.style.cursor = 'url("data:image/x-icon;base64,AAACAAEACAgAAAIAAgA4AQAAFgAAACgAAAAIAAAAEAAAAAEAIAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAA==") 2 2, default'; - - if (target.style.cursor) { - Util.Info("Data URI scheme cursor supported"); - Util._cursor_uris_supported = true; - } else { - Util.Warn("Data URI scheme cursor not supported"); - Util._cursor_uris_supported = false; - } - } catch (exc) { - Util.Error("Data URI scheme cursor test exception: " + exc); - Util._cursor_uris_supported = false; - } - } - - return Util._cursor_uris_supported; -}; - -// Set browser engine versions. Based on mootools. -Util.Features = {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)}; - -(function () { - "use strict"; - // 'presto': (function () { return (!window.opera) ? false : true; }()), - var detectPresto = function () { - return !!window.opera; - }; - - // 'trident': (function () { return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4); - var detectTrident = function () { - if (!window.ActiveXObject) { - return false; - } else { - if (window.XMLHttpRequest) { - return (document.querySelectorAll) ? 6 : 5; - } else { - return 4; - } - } - }; - - // 'webkit': (function () { try { return (navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); } catch (e) { return false; } }()), - var detectInitialWebkit = function () { - try { - if (navigator.taintEnabled) { - return false; - } else { - if (Util.Features.xpath) { - return (Util.Features.query) ? 525 : 420; - } else { - return 419; - } - } - } catch (e) { - return false; - } - }; - - var detectActualWebkit = function (initial_ver) { - var re = /WebKit\/([0-9\.]*) /; - var str_ver = (navigator.userAgent.match(re) || ['', initial_ver])[1]; - return parseFloat(str_ver, 10); - }; - - // 'gecko': (function () { return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19ssName) ? 19 : 18 : 18); }()) - var detectGecko = function () { - /* jshint -W041 */ - if (!document.getBoxObjectFor && window.mozInnerScreenX == null) { - return false; - } else { - return (document.getElementsByClassName) ? 19 : 18; - } - /* jshint +W041 */ - }; - - Util.Engine = { - // Version detection break in Opera 11.60 (errors on arguments.callee.caller reference) - //'presto': (function() { - // return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925)); }()), - 'presto': detectPresto(), - 'trident': detectTrident(), - 'webkit': detectInitialWebkit(), - 'gecko': detectGecko() - }; - - if (Util.Engine.webkit) { - // Extract actual webkit version if available - Util.Engine.webkit = detectActualWebkit(Util.Engine.webkit); - } -})(); - -Util.Flash = (function () { - "use strict"; - var v, version; - try { - v = navigator.plugins['Shockwave Flash'].description; - } catch (err1) { - try { - v = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); - } catch (err2) { - v = '0 r0'; - } - } - version = v.match(/\d+/g); - return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0}; -}()); - - -Util.Localisation = { - // Currently configured language - language: 'en', - - // Configure suitable language based on user preferences - setup: function (supportedLanguages) { - var userLanguages; - - Util.Localisation.language = 'en'; // Default: US English - - /* - * Navigator.languages only available in Chrome (32+) and FireFox (32+) - * Fall back to navigator.language for other browsers - */ - if (typeof window.navigator.languages == 'object') { - userLanguages = window.navigator.languages; - } else { - userLanguages = [navigator.language || navigator.userLanguage]; - } - - for (var i = 0;i < userLanguages.length;i++) { - var userLang = userLanguages[i]; - userLang = userLang.toLowerCase(); - userLang = userLang.replace("_", "-"); - userLang = userLang.split("-"); - - // Built-in default? - if ((userLang[0] === 'en') && - ((userLang[1] === undefined) || (userLang[1] === 'us'))) { - return; - } - - // First pass: perfect match - for (var j = 0;j < supportedLanguages.length;j++) { - var supLang = supportedLanguages[j]; - supLang = supLang.toLowerCase(); - supLang = supLang.replace("_", "-"); - supLang = supLang.split("-"); - - if (userLang[0] !== supLang[0]) - continue; - if (userLang[1] !== supLang[1]) - continue; - - Util.Localisation.language = supportedLanguages[j]; - return; - } - - // Second pass: fallback - for (var j = 0;j < supportedLanguages.length;j++) { - supLang = supportedLanguages[j]; - supLang = supLang.toLowerCase(); - supLang = supLang.replace("_", "-"); - supLang = supLang.split("-"); - - if (userLang[0] !== supLang[0]) - continue; - if (supLang[1] !== undefined) - continue; - - Util.Localisation.language = supportedLanguages[j]; - return; - } - } - }, - - // Retrieve localised text - get: function (id) { - if (typeof Language !== 'undefined' && Language[id]) { - return Language[id]; - } else { - return id; - } - }, - - // Traverses the DOM and translates relevant fields - // See https://html.spec.whatwg.org/multipage/dom.html#attr-translate - translateDOM: function () { - function process(elem, enabled) { - function isAnyOf(searchElement, items) { - return items.indexOf(searchElement) !== -1; - } - - function translateAttribute(elem, attr) { - var str = elem.getAttribute(attr); - str = Util.Localisation.get(str); - elem.setAttribute(attr, str); - } - - function translateTextNode(node) { - var str = node.data.trim(); - str = Util.Localisation.get(str); - node.data = str; - } - - if (elem.hasAttribute("translate")) { - if (isAnyOf(elem.getAttribute("translate"), ["", "yes"])) { - enabled = true; - } else if (isAnyOf(elem.getAttribute("translate"), ["no"])) { - enabled = false; - } - } - - if (enabled) { - if (elem.hasAttribute("abbr") && - elem.tagName === "TH") { - translateAttribute(elem, "abbr"); - } - if (elem.hasAttribute("alt") && - isAnyOf(elem.tagName, ["AREA", "IMG", "INPUT"])) { - translateAttribute(elem, "alt"); - } - if (elem.hasAttribute("download") && - isAnyOf(elem.tagName, ["A", "AREA"])) { - translateAttribute(elem, "download"); - } - if (elem.hasAttribute("label") && - isAnyOf(elem.tagName, ["MENUITEM", "MENU", "OPTGROUP", - "OPTION", "TRACK"])) { - translateAttribute(elem, "label"); - } - // FIXME: Should update "lang" - if (elem.hasAttribute("placeholder") && - isAnyOf(elem.tagName, ["INPUT", "TEXTAREA"])) { - translateAttribute(elem, "placeholder"); - } - if (elem.hasAttribute("title")) { - translateAttribute(elem, "title"); - } - if (elem.hasAttribute("value") && - elem.tagName === "INPUT" && - isAnyOf(elem.getAttribute("type"), ["reset", "button"])) { - translateAttribute(elem, "value"); - } - } - - for (var i = 0;i < elem.childNodes.length;i++) { - node = elem.childNodes[i]; - if (node.nodeType === node.ELEMENT_NODE) { - process(node, enabled); - } else if (node.nodeType === node.TEXT_NODE && enabled) { - translateTextNode(node); - } - } - } - - process(document.body, true); - }, -}; - -// Emulate Element.setCapture() when not supported - -Util._captureRecursion = false; -Util._captureProxy = function (e) { - // Recursion protection as we'll see our own event - if (Util._captureRecursion) return; - - // Clone the event as we cannot dispatch an already dispatched event - var newEv = new e.constructor(e.type, e); - - Util._captureRecursion = true; - Util._captureElem.dispatchEvent(newEv); - Util._captureRecursion = false; - - // Avoid double events - e.stopPropagation(); - - // Respect the wishes of the redirected event handlers - if (newEv.defaultPrevented) { - e.preventDefault(); - } - - // Implicitly release the capture on button release - if ((e.type === "mouseup") || (e.type === "touchend")) { - Util.releaseCapture(); - } -}; - -// Follow cursor style of target element -Util._captureElemChanged = function() { - var captureElem = document.getElementById("noVNC_mouse_capture_elem"); - captureElem.style.cursor = window.getComputedStyle(Util._captureElem).cursor; -}; -Util._captureObserver = new MutationObserver(Util._captureElemChanged); - -Util._captureIndex = 0; - -Util.setCapture = function (elem) { - if (elem.setCapture) { - - elem.setCapture(); - - // IE releases capture on 'click' events which might not trigger - elem.addEventListener('mouseup', Util.releaseCapture); - elem.addEventListener('touchend', Util.releaseCapture); - - } else { - // Release any existing capture in case this method is - // called multiple times without coordination - Util.releaseCapture(); - - // Safari on iOS 9 has a broken constructor for TouchEvent. - // We are fine in this case however, since Safari seems to - // have some sort of implicit setCapture magic anyway. - if (window.TouchEvent !== undefined) { - try { - new TouchEvent("touchstart"); - } catch (TypeError) { - return; - } - } - - var captureElem = document.getElementById("noVNC_mouse_capture_elem"); - - if (captureElem === null) { - captureElem = document.createElement("div"); - captureElem.id = "noVNC_mouse_capture_elem"; - captureElem.style.position = "fixed"; - captureElem.style.top = "0px"; - captureElem.style.left = "0px"; - captureElem.style.width = "100%"; - captureElem.style.height = "100%"; - captureElem.style.zIndex = 10000; - captureElem.style.display = "none"; - document.body.appendChild(captureElem); - - // This is to make sure callers don't get confused by having - // our blocking element as the target - captureElem.addEventListener('contextmenu', Util._captureProxy); - - captureElem.addEventListener('mousemove', Util._captureProxy); - captureElem.addEventListener('mouseup', Util._captureProxy); - - captureElem.addEventListener('touchmove', Util._captureProxy); - captureElem.addEventListener('touchend', Util._captureProxy); - } - - Util._captureElem = elem; - Util._captureIndex++; - - // Track cursor and get initial cursor - Util._captureObserver.observe(elem, {attributes:true}); - Util._captureElemChanged(); - - captureElem.style.display = null; - - // We listen to events on window in order to keep tracking if it - // happens to leave the viewport - window.addEventListener('mousemove', Util._captureProxy); - window.addEventListener('mouseup', Util._captureProxy); - - window.addEventListener('touchmove', Util._captureProxy); - window.addEventListener('touchend', Util._captureProxy); - } -}; - -Util.releaseCapture = function () { - if (document.releaseCapture) { - - document.releaseCapture(); - - } else { - if (!Util._captureElem) { - return; - } - - // There might be events already queued, so we need to wait for - // them to flush. E.g. contextmenu in Microsoft Edge - window.setTimeout(function(expected) { - // Only clear it if it's the expected grab (i.e. no one - // else has initiated a new grab) - if (Util._captureIndex === expected) { - Util._captureElem = null; - } - }, 0, Util._captureIndex); - - Util._captureObserver.disconnect(); - - var captureElem = document.getElementById("noVNC_mouse_capture_elem"); - captureElem.style.display = "none"; - - window.removeEventListener('mousemove', Util._captureProxy); - window.removeEventListener('mouseup', Util._captureProxy); - - window.removeEventListener('touchmove', Util._captureProxy); - window.removeEventListener('touchend', Util._captureProxy); - } -}; - -/* [module] export default Util; */ diff --git a/core/util/browsers.js b/core/util/browsers.js new file mode 100644 index 00000000..ab5e09f3 --- /dev/null +++ b/core/util/browsers.js @@ -0,0 +1,120 @@ +/* + * noVNC: HTML5 VNC client + * Copyright (C) 2012 Joel Martin + * Licensed under MPL 2.0 (see LICENSE.txt) + * + * See README.md for usage and integration instructions. + */ + +import * as Log from './logging.js'; + +// Set browser engine versions. Based on mootools. +const Features = {xpath: !!(document.evaluate), query: !!(document.querySelector)}; + +// 'presto': (function () { return (!window.opera) ? false : true; }()), +var detectPresto = function () { + return !!window.opera; +}; + +// 'trident': (function () { return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4); +var detectTrident = function () { + if (!window.ActiveXObject) { + return false; + } else { + if (window.XMLHttpRequest) { + return (document.querySelectorAll) ? 6 : 5; + } else { + return 4; + } + } +}; + +// 'webkit': (function () { try { return (navigator.taintEnabled) ? false : ((Features.xpath) ? ((Features.query) ? 525 : 420) : 419); } catch (e) { return false; } }()), +var detectInitialWebkit = function () { + try { + if (navigator.taintEnabled) { + return false; + } else { + if (Features.xpath) { + return (Features.query) ? 525 : 420; + } else { + return 419; + } + } + } catch (e) { + return false; + } +}; + +var detectActualWebkit = function (initial_ver) { + var re = /WebKit\/([0-9\.]*) /; + var str_ver = (navigator.userAgent.match(re) || ['', initial_ver])[1]; + return parseFloat(str_ver, 10); +}; + +// 'gecko': (function () { return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19ssName) ? 19 : 18 : 18); }()) +var detectGecko = function () { + /* jshint -W041 */ + if (!document.getBoxObjectFor && window.mozInnerScreenX == null) { + return false; + } else { + return (document.getElementsByClassName) ? 19 : 18; + } + /* jshint +W041 */ +}; + +const isWebkitInitial = detectInitialWebkit(); + +export const Engine = { + // Version detection break in Opera 11.60 (errors on arguments.callee.caller reference) + //'presto': (function() { + // return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925)); }()), + 'presto': detectPresto(), + 'trident': detectTrident(), + 'webkit': isWebkitInitial ? detectActualWebkit(isWebkitInitial) : false, + 'gecko': detectGecko() +}; + +// Touch detection +export var isTouchDevice = ('ontouchstart' in document.documentElement) || + // requried for Chrome debugger + (document.ontouchstart !== undefined) || + // required for MS Surface + (navigator.maxTouchPoints > 0) || + (navigator.msMaxTouchPoints > 0); +window.addEventListener('touchstart', function onFirstTouch() { + isTouchDevice = true; + window.removeEventListener('touchstart', onFirstTouch, false); +}, false); + +var _cursor_uris_supported = null; + +export function browserSupportsCursorURIs () { + if (_cursor_uris_supported === null) { + try { + var target = document.createElement('canvas'); + target.style.cursor = 'url("data:image/x-icon;base64,AAACAAEACAgAAAIAAgA4AQAAFgAAACgAAAAIAAAAEAAAAAEAIAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAA==") 2 2, default'; + + if (target.style.cursor) { + Log.Info("Data URI scheme cursor supported"); + _cursor_uris_supported = true; + } else { + Log.Warn("Data URI scheme cursor not supported"); + _cursor_uris_supported = false; + } + } catch (exc) { + Log.Error("Data URI scheme cursor test exception: " + exc); + _cursor_uris_supported = false; + } + } + + return _cursor_uris_supported; +}; + +export function _forceCursorURIs(enabled) { + if (enabled === undefined || enabled) { + _cursor_uris_supported = true; + } else { + _cursor_uris_supported = false; + } +} diff --git a/core/util/events.js b/core/util/events.js new file mode 100644 index 00000000..8fdf6aa6 --- /dev/null +++ b/core/util/events.js @@ -0,0 +1,161 @@ +/* + * noVNC: HTML5 VNC client + * Copyright (C) 2012 Joel Martin + * Licensed under MPL 2.0 (see LICENSE.txt) + * + * See README.md for usage and integration instructions. + */ + +/* + * Cross-browser event and position routines + */ + +import * as Log from './logging.js'; + +export function getPointerEvent (e) { + return e.changedTouches ? e.changedTouches[0] : e.touches ? e.touches[0] : e; +}; + +export function stopEvent (e) { + e.stopPropagation(); + e.preventDefault(); +}; + +// Emulate Element.setCapture() when not supported +var _captureRecursion = false; +var _captureElem = null; +const _captureProxy = function (e) { + // Recursion protection as we'll see our own event + if (_captureRecursion) return; + + // Clone the event as we cannot dispatch an already dispatched event + var newEv = new e.constructor(e.type, e); + + _captureRecursion = true; + _captureElem.dispatchEvent(newEv); + _captureRecursion = false; + + // Avoid double events + e.stopPropagation(); + + // Respect the wishes of the redirected event handlers + if (newEv.defaultPrevented) { + e.preventDefault(); + } + + // Implicitly release the capture on button release + if ((e.type === "mouseup") || (e.type === "touchend")) { + releaseCapture(); + } +}; + +// Follow cursor style of target element +const _captureElemChanged = function() { + var captureElem = document.getElementById("noVNC_mouse_capture_elem"); + captureElem.style.cursor = window.getComputedStyle(_captureElem).cursor; +}; +const _captureObserver = new MutationObserver(_captureElemChanged); + +var _captureIndex = 0; + +export function setCapture (elem) { + if (elem.setCapture) { + + elem.setCapture(); + + // IE releases capture on 'click' events which might not trigger + elem.addEventListener('mouseup', releaseCapture); + elem.addEventListener('touchend', releaseCapture); + + } else { + // Release any existing capture in case this method is + // called multiple times without coordination + releaseCapture(); + + // Safari on iOS 9 has a broken constructor for TouchEvent. + // We are fine in this case however, since Safari seems to + // have some sort of implicit setCapture magic anyway. + if (window.TouchEvent !== undefined) { + try { + new TouchEvent("touchstart"); + } catch (TypeError) { + return; + } + } + + var captureElem = document.getElementById("noVNC_mouse_capture_elem"); + + if (captureElem === null) { + captureElem = document.createElement("div"); + captureElem.id = "noVNC_mouse_capture_elem"; + captureElem.style.position = "fixed"; + captureElem.style.top = "0px"; + captureElem.style.left = "0px"; + captureElem.style.width = "100%"; + captureElem.style.height = "100%"; + captureElem.style.zIndex = 10000; + captureElem.style.display = "none"; + document.body.appendChild(captureElem); + + // This is to make sure callers don't get confused by having + // our blocking element as the target + captureElem.addEventListener('contextmenu', _captureProxy); + + captureElem.addEventListener('mousemove', _captureProxy); + captureElem.addEventListener('mouseup', _captureProxy); + + captureElem.addEventListener('touchmove', _captureProxy); + captureElem.addEventListener('touchend', _captureProxy); + } + + _captureElem = elem; + _captureIndex++; + + // Track cursor and get initial cursor + _captureObserver.observe(elem, {attributes:true}); + _captureElemChanged(); + + captureElem.style.display = null; + + // We listen to events on window in order to keep tracking if it + // happens to leave the viewport + window.addEventListener('mousemove', _captureProxy); + window.addEventListener('mouseup', _captureProxy); + + window.addEventListener('touchmove', _captureProxy); + window.addEventListener('touchend', _captureProxy); + } +}; + +export function releaseCapture () { + if (document.releaseCapture) { + + document.releaseCapture(); + + } else { + if (!_captureElem) { + return; + } + + // There might be events already queued, so we need to wait for + // them to flush. E.g. contextmenu in Microsoft Edge + window.setTimeout(function(expected) { + // Only clear it if it's the expected grab (i.e. no one + // else has initiated a new grab) + if (_captureIndex === expected) { + _captureElem = null; + } + }, 0, _captureIndex); + + _captureObserver.disconnect(); + + var captureElem = document.getElementById("noVNC_mouse_capture_elem"); + captureElem.style.display = "none"; + + window.removeEventListener('mousemove', _captureProxy); + window.removeEventListener('mouseup', _captureProxy); + + window.removeEventListener('touchmove', _captureProxy); + window.removeEventListener('touchend', _captureProxy); + } +}; diff --git a/core/util/localization.js b/core/util/localization.js new file mode 100644 index 00000000..2a27a69c --- /dev/null +++ b/core/util/localization.js @@ -0,0 +1,170 @@ +/* + * noVNC: HTML5 VNC client + * Copyright (C) 2012 Joel Martin + * Licensed under MPL 2.0 (see LICENSE.txt) + * + * See README.md for usage and integration instructions. + */ + +/* + * Localization Utilities + */ + +export function Localizer() { + // Currently configured language + this.language = 'en'; + + // Current dictionary of translations + this.dictionary = undefined; +} + +Localizer.prototype = { + // Configure suitable language based on user preferences + setup: function (supportedLanguages) { + var userLanguages; + + this.language = 'en'; // Default: US English + + /* + * Navigator.languages only available in Chrome (32+) and FireFox (32+) + * Fall back to navigator.language for other browsers + */ + if (typeof window.navigator.languages == 'object') { + userLanguages = window.navigator.languages; + } else { + userLanguages = [navigator.language || navigator.userLanguage]; + } + + for (var i = 0;i < userLanguages.length;i++) { + var userLang = userLanguages[i]; + userLang = userLang.toLowerCase(); + userLang = userLang.replace("_", "-"); + userLang = userLang.split("-"); + + // Built-in default? + if ((userLang[0] === 'en') && + ((userLang[1] === undefined) || (userLang[1] === 'us'))) { + return; + } + + // First pass: perfect match + for (var j = 0;j < supportedLanguages.length;j++) { + var supLang = supportedLanguages[j]; + supLang = supLang.toLowerCase(); + supLang = supLang.replace("_", "-"); + supLang = supLang.split("-"); + + if (userLang[0] !== supLang[0]) + continue; + if (userLang[1] !== supLang[1]) + continue; + + this.language = supportedLanguages[j]; + return; + } + + // Second pass: fallback + for (var j = 0;j < supportedLanguages.length;j++) { + supLang = supportedLanguages[j]; + supLang = supLang.toLowerCase(); + supLang = supLang.replace("_", "-"); + supLang = supLang.split("-"); + + if (userLang[0] !== supLang[0]) + continue; + if (supLang[1] !== undefined) + continue; + + this.language = supportedLanguages[j]; + return; + } + } + }, + + // Retrieve localised text + get: function (id) { + if (typeof this.dictionary !== 'undefined' && this.dictionary[id]) { + return this.dictionary[id]; + } else { + return id; + } + }, + + // Traverses the DOM and translates relevant fields + // See https://html.spec.whatwg.org/multipage/dom.html#attr-translate + translateDOM: function () { + var self = this; + function process(elem, enabled) { + function isAnyOf(searchElement, items) { + return items.indexOf(searchElement) !== -1; + } + + function translateAttribute(elem, attr) { + var str = elem.getAttribute(attr); + str = self.get(str); + elem.setAttribute(attr, str); + } + + function translateTextNode(node) { + var str = node.data.trim(); + str = self.get(str); + node.data = str; + } + + if (elem.hasAttribute("translate")) { + if (isAnyOf(elem.getAttribute("translate"), ["", "yes"])) { + enabled = true; + } else if (isAnyOf(elem.getAttribute("translate"), ["no"])) { + enabled = false; + } + } + + if (enabled) { + if (elem.hasAttribute("abbr") && + elem.tagName === "TH") { + translateAttribute(elem, "abbr"); + } + if (elem.hasAttribute("alt") && + isAnyOf(elem.tagName, ["AREA", "IMG", "INPUT"])) { + translateAttribute(elem, "alt"); + } + if (elem.hasAttribute("download") && + isAnyOf(elem.tagName, ["A", "AREA"])) { + translateAttribute(elem, "download"); + } + if (elem.hasAttribute("label") && + isAnyOf(elem.tagName, ["MENUITEM", "MENU", "OPTGROUP", + "OPTION", "TRACK"])) { + translateAttribute(elem, "label"); + } + // FIXME: Should update "lang" + if (elem.hasAttribute("placeholder") && + isAnyOf(elem.tagName, ["INPUT", "TEXTAREA"])) { + translateAttribute(elem, "placeholder"); + } + if (elem.hasAttribute("title")) { + translateAttribute(elem, "title"); + } + if (elem.hasAttribute("value") && + elem.tagName === "INPUT" && + isAnyOf(elem.getAttribute("type"), ["reset", "button"])) { + translateAttribute(elem, "value"); + } + } + + for (var i = 0;i < elem.childNodes.length;i++) { + let node = elem.childNodes[i]; + if (node.nodeType === node.ELEMENT_NODE) { + process(node, enabled); + } else if (node.nodeType === node.TEXT_NODE && enabled) { + translateTextNode(node); + } + } + } + + process(document.body, true); + }, +} + +export const l10n = new Localizer(); +export default l10n.get.bind(l10n); diff --git a/core/util/logging.js b/core/util/logging.js new file mode 100644 index 00000000..342bfa7c --- /dev/null +++ b/core/util/logging.js @@ -0,0 +1,53 @@ +/* + * noVNC: HTML5 VNC client + * Copyright (C) 2012 Joel Martin + * Licensed under MPL 2.0 (see LICENSE.txt) + * + * See README.md for usage and integration instructions. + */ + +/* + * Logging/debug routines + */ + +var _log_level = 'warn'; + +var Debug = function (msg) {}; +var Info = function (msg) {}; +var Warn = function (msg) {}; +var Error = function (msg) {}; + +export function init_logging (level) { + if (typeof level === 'undefined') { + level = _log_level; + } else { + _log_level = level; + } + + Debug = Info = Warn = Error = function (msg) {}; + if (typeof window.console !== "undefined") { + /* jshint -W086 */ + switch (level) { + case 'debug': + Debug = console.debug.bind(window.console); + case 'info': + Info = console.info.bind(window.console); + case 'warn': + Warn = console.warn.bind(window.console); + case 'error': + Error = console.error.bind(window.console); + case 'none': + break; + default: + throw new Error("invalid logging type '" + level + "'"); + } + /* jshint +W086 */ + } +}; +export function get_logging () { + return _log_level; +}; +export { Debug, Info, Warn, Error }; + +// Initialize logging level +init_logging(); diff --git a/core/util/properties.js b/core/util/properties.js new file mode 100644 index 00000000..e1d607e0 --- /dev/null +++ b/core/util/properties.js @@ -0,0 +1,138 @@ +/* + * noVNC: HTML5 VNC client + * Copyright (C) 2012 Joel Martin + * Licensed under MPL 2.0 (see LICENSE.txt) + * + * See README.md for usage and integration instructions. + */ + +/* + * Getter/Setter Creation Utilities + */ + +import * as Log from './logging.js'; + +function make_property (proto, name, mode, type) { + "use strict"; + + var getter; + if (type === 'arr') { + getter = function (idx) { + if (typeof idx !== 'undefined') { + return this['_' + name][idx]; + } else { + return this['_' + name]; + } + }; + } else { + getter = function () { + return this['_' + name]; + }; + } + + var make_setter = function (process_val) { + if (process_val) { + return function (val, idx) { + if (typeof idx !== 'undefined') { + this['_' + name][idx] = process_val(val); + } else { + this['_' + name] = process_val(val); + } + }; + } else { + return function (val, idx) { + if (typeof idx !== 'undefined') { + this['_' + name][idx] = val; + } else { + this['_' + name] = val; + } + }; + } + }; + + var setter; + if (type === 'bool') { + setter = make_setter(function (val) { + if (!val || (val in {'0': 1, 'no': 1, 'false': 1})) { + return false; + } else { + return true; + } + }); + } else if (type === 'int') { + setter = make_setter(function (val) { return parseInt(val, 10); }); + } else if (type === 'float') { + setter = make_setter(parseFloat); + } else if (type === 'str') { + setter = make_setter(String); + } else if (type === 'func') { + setter = make_setter(function (val) { + if (!val) { + return function () {}; + } else { + return val; + } + }); + } else if (type === 'arr' || type === 'dom' || type == 'raw') { + setter = make_setter(); + } else { + throw new Error('Unknown property type ' + type); // some sanity checking + } + + // set the getter + if (typeof proto['get_' + name] === 'undefined') { + proto['get_' + name] = getter; + } + + // set the setter if needed + if (typeof proto['set_' + name] === 'undefined') { + if (mode === 'rw') { + proto['set_' + name] = setter; + } else if (mode === 'wo') { + proto['set_' + name] = function (val, idx) { + if (typeof this['_' + name] !== 'undefined') { + throw new Error(name + " can only be set once"); + } + setter.call(this, val, idx); + }; + } + } + + // make a special setter that we can use in set defaults + proto['_raw_set_' + name] = function (val, idx) { + setter.call(this, val, idx); + //delete this['_init_set_' + name]; // remove it after use + }; +}; + +export function make_properties (constructor, arr) { + "use strict"; + for (var i = 0; i < arr.length; i++) { + make_property(constructor.prototype, arr[i][0], arr[i][1], arr[i][2]); + } +}; + +export function set_defaults (obj, conf, defaults) { + var defaults_keys = Object.keys(defaults); + var conf_keys = Object.keys(conf); + var keys_obj = {}; + var i; + for (i = 0; i < defaults_keys.length; i++) { keys_obj[defaults_keys[i]] = 1; } + for (i = 0; i < conf_keys.length; i++) { keys_obj[conf_keys[i]] = 1; } + var keys = Object.keys(keys_obj); + + for (i = 0; i < keys.length; i++) { + var setter = obj['_raw_set_' + keys[i]]; + if (!setter) { + Log.Warn('Invalid property ' + keys[i]); + continue; + } + + if (keys[i] in conf) { + setter.call(obj, conf[keys[i]]); + } else { + setter.call(obj, defaults[keys[i]]); + } + } +}; + diff --git a/core/util/strings.js b/core/util/strings.js new file mode 100644 index 00000000..00a6156c --- /dev/null +++ b/core/util/strings.js @@ -0,0 +1,15 @@ +/* + * noVNC: HTML5 VNC client + * Copyright (C) 2012 Joel Martin + * Licensed under MPL 2.0 (see LICENSE.txt) + * + * See README.md for usage and integration instructions. + */ + +/* + * Decode from UTF-8 + */ +export function decodeUTF8 (utf8string) { + "use strict"; + return decodeURIComponent(escape(utf8string)); +}; diff --git a/core/websock.js b/core/websock.js index 51d9b625..78809a1a 100644 --- a/core/websock.js +++ b/core/websock.js @@ -12,14 +12,12 @@ * read binary data off of the receive queue. */ -/* [module] - * import Util from "./util"; - */ +import * as Log from './util/logging.js'; /*jslint browser: true, bitwise: true */ /*global Util*/ -/* [module] export default */ function Websock() { +export default function Websock() { "use strict"; this._websocket = null; // WebSocket object @@ -44,313 +42,310 @@ }; }; -(function () { - "use strict"; - // this has performance issues in some versions Chromium, and - // doesn't gain a tremendous amount of performance increase in Firefox - // at the moment. It may be valuable to turn it on in the future. - var ENABLE_COPYWITHIN = false; +// this has performance issues in some versions Chromium, and +// doesn't gain a tremendous amount of performance increase in Firefox +// at the moment. It may be valuable to turn it on in the future. +var ENABLE_COPYWITHIN = false; - var MAX_RQ_GROW_SIZE = 40 * 1024 * 1024; // 40 MiB +var MAX_RQ_GROW_SIZE = 40 * 1024 * 1024; // 40 MiB - var typedArrayToString = (function () { - // This is only for PhantomJS, which doesn't like apply-ing - // with Typed Arrays - try { - var arr = new Uint8Array([1, 2, 3]); - String.fromCharCode.apply(null, arr); - return function (a) { return String.fromCharCode.apply(null, a); }; - } catch (ex) { - return function (a) { - return String.fromCharCode.apply( - null, Array.prototype.slice.call(a)); - }; - } - })(); - - Websock.prototype = { - // Getters and Setters - get_sQ: function () { - return this._sQ; - }, - - get_rQ: function () { - return this._rQ; - }, - - get_rQi: function () { - return this._rQi; - }, - - set_rQi: function (val) { - this._rQi = val; - }, - - // Receive Queue - rQlen: function () { - return this._rQlen - this._rQi; - }, - - rQpeek8: function () { - return this._rQ[this._rQi]; - }, - - rQshift8: function () { - return this._rQ[this._rQi++]; - }, - - rQskip8: function () { - this._rQi++; - }, - - rQskipBytes: function (num) { - this._rQi += num; - }, - - // TODO(directxman12): test performance with these vs a DataView - rQshift16: function () { - return (this._rQ[this._rQi++] << 8) + - this._rQ[this._rQi++]; - }, - - rQshift32: function () { - return (this._rQ[this._rQi++] << 24) + - (this._rQ[this._rQi++] << 16) + - (this._rQ[this._rQi++] << 8) + - this._rQ[this._rQi++]; - }, - - rQshiftStr: function (len) { - if (typeof(len) === 'undefined') { len = this.rQlen(); } - var arr = new Uint8Array(this._rQ.buffer, this._rQi, len); - this._rQi += len; - return typedArrayToString(arr); - }, - - rQshiftBytes: function (len) { - if (typeof(len) === 'undefined') { len = this.rQlen(); } - this._rQi += len; - return new Uint8Array(this._rQ.buffer, this._rQi - len, len); - }, - - rQshiftTo: function (target, len) { - if (len === undefined) { len = this.rQlen(); } - // TODO: make this just use set with views when using a ArrayBuffer to store the rQ - target.set(new Uint8Array(this._rQ.buffer, this._rQi, len)); - this._rQi += len; - }, - - rQwhole: function () { - return new Uint8Array(this._rQ.buffer, 0, this._rQlen); - }, - - rQslice: function (start, end) { - if (end) { - return new Uint8Array(this._rQ.buffer, this._rQi + start, end - start); - } else { - return new Uint8Array(this._rQ.buffer, this._rQi + start, this._rQlen - this._rQi - start); - } - }, - - // Check to see if we must wait for 'num' bytes (default to FBU.bytes) - // to be available in the receive queue. Return true if we need to - // wait (and possibly print a debug message), otherwise false. - rQwait: function (msg, num, goback) { - var rQlen = this._rQlen - this._rQi; // Skip rQlen() function call - if (rQlen < num) { - if (goback) { - if (this._rQi < goback) { - throw new Error("rQwait cannot backup " + goback + " bytes"); - } - this._rQi -= goback; - } - return true; // true means need more data - } - return false; - }, - - // Send Queue - - flush: function () { - if (this._websocket.bufferedAmount !== 0) { - Util.Debug("bufferedAmount: " + this._websocket.bufferedAmount); - } - - if (this._sQlen > 0 && this._websocket.readyState === WebSocket.OPEN) { - this._websocket.send(this._encode_message()); - this._sQlen = 0; - } - }, - - send: function (arr) { - this._sQ.set(arr, this._sQlen); - this._sQlen += arr.length; - this.flush(); - }, - - send_string: function (str) { - this.send(str.split('').map(function (chr) { - return chr.charCodeAt(0); - })); - }, - - // Event Handlers - off: function (evt) { - this._eventHandlers[evt] = function () {}; - }, - - on: function (evt, handler) { - this._eventHandlers[evt] = handler; - }, - - _allocate_buffers: function () { - this._rQ = new Uint8Array(this._rQbufferSize); - this._sQ = new Uint8Array(this._sQbufferSize); - }, - - init: function () { - this._allocate_buffers(); - this._rQi = 0; - this._websocket = null; - }, - - open: function (uri, protocols) { - var ws_schema = uri.match(/^([a-z]+):\/\//)[1]; - this.init(); - - this._websocket = new WebSocket(uri, protocols); - this._websocket.binaryType = 'arraybuffer'; - - this._websocket.onmessage = this._recv_message.bind(this); - this._websocket.onopen = (function () { - Util.Debug('>> WebSock.onopen'); - if (this._websocket.protocol) { - Util.Info("Server choose sub-protocol: " + this._websocket.protocol); - } - - this._eventHandlers.open(); - Util.Debug("<< WebSock.onopen"); - }).bind(this); - this._websocket.onclose = (function (e) { - Util.Debug(">> WebSock.onclose"); - this._eventHandlers.close(e); - Util.Debug("<< WebSock.onclose"); - }).bind(this); - this._websocket.onerror = (function (e) { - Util.Debug(">> WebSock.onerror: " + e); - this._eventHandlers.error(e); - Util.Debug("<< WebSock.onerror: " + e); - }).bind(this); - }, - - close: function () { - if (this._websocket) { - if ((this._websocket.readyState === WebSocket.OPEN) || - (this._websocket.readyState === WebSocket.CONNECTING)) { - Util.Info("Closing WebSocket connection"); - this._websocket.close(); - } - - this._websocket.onmessage = function (e) { return; }; - } - }, - - // private methods - _encode_message: function () { - // Put in a binary arraybuffer - // according to the spec, you can send ArrayBufferViews with the send method - return new Uint8Array(this._sQ.buffer, 0, this._sQlen); - }, - - _expand_compact_rQ: function (min_fit) { - var resizeNeeded = min_fit || this._rQlen - this._rQi > this._rQbufferSize / 2; - if (resizeNeeded) { - if (!min_fit) { - // just double the size if we need to do compaction - this._rQbufferSize *= 2; - } else { - // otherwise, make sure we satisy rQlen - rQi + min_fit < rQbufferSize / 8 - this._rQbufferSize = (this._rQlen - this._rQi + min_fit) * 8; - } - } - - // we don't want to grow unboundedly - if (this._rQbufferSize > MAX_RQ_GROW_SIZE) { - this._rQbufferSize = MAX_RQ_GROW_SIZE; - if (this._rQbufferSize - this._rQlen - this._rQi < min_fit) { - throw new Exception("Receive Queue buffer exceeded " + MAX_RQ_GROW_SIZE + " bytes, and the new message could not fit"); - } - } - - if (resizeNeeded) { - var old_rQbuffer = this._rQ.buffer; - this._rQmax = this._rQbufferSize / 8; - this._rQ = new Uint8Array(this._rQbufferSize); - this._rQ.set(new Uint8Array(old_rQbuffer, this._rQi)); - } else { - if (ENABLE_COPYWITHIN) { - this._rQ.copyWithin(0, this._rQi); - } else { - this._rQ.set(new Uint8Array(this._rQ.buffer, this._rQi)); - } - } - - this._rQlen = this._rQlen - this._rQi; - this._rQi = 0; - }, - - _decode_message: function (data) { - // push arraybuffer values onto the end - var u8 = new Uint8Array(data); - if (u8.length > this._rQbufferSize - this._rQlen) { - this._expand_compact_rQ(u8.length); - } - this._rQ.set(u8, this._rQlen); - this._rQlen += u8.length; - }, - - _recv_message: function (e) { - try { - this._decode_message(e.data); - if (this.rQlen() > 0) { - this._eventHandlers.message(); - // Compact the receive queue - if (this._rQlen == this._rQi) { - this._rQlen = 0; - this._rQi = 0; - } else if (this._rQlen > this._rQmax) { - this._expand_compact_rQ(); - } - } else { - Util.Debug("Ignoring empty message"); - } - } catch (exc) { - var exception_str = ""; - if (exc.name) { - exception_str += "\n name: " + exc.name + "\n"; - exception_str += " message: " + exc.message + "\n"; - } - - if (typeof exc.description !== 'undefined') { - exception_str += " description: " + exc.description + "\n"; - } - - if (typeof exc.stack !== 'undefined') { - exception_str += exc.stack; - } - - if (exception_str.length > 0) { - Util.Error("recv_message, caught exception: " + exception_str); - } else { - Util.Error("recv_message, caught exception: " + exc); - } - - if (typeof exc.name !== 'undefined') { - this._eventHandlers.error(exc.name + ": " + exc.message); - } else { - this._eventHandlers.error(exc); - } - } - } - }; +var typedArrayToString = (function () { + // This is only for PhantomJS, which doesn't like apply-ing + // with Typed Arrays + try { + var arr = new Uint8Array([1, 2, 3]); + String.fromCharCode.apply(null, arr); + return function (a) { return String.fromCharCode.apply(null, a); }; + } catch (ex) { + return function (a) { + return String.fromCharCode.apply( + null, Array.prototype.slice.call(a)); + }; + } })(); + +Websock.prototype = { + // Getters and Setters + get_sQ: function () { + return this._sQ; + }, + + get_rQ: function () { + return this._rQ; + }, + + get_rQi: function () { + return this._rQi; + }, + + set_rQi: function (val) { + this._rQi = val; + }, + + // Receive Queue + rQlen: function () { + return this._rQlen - this._rQi; + }, + + rQpeek8: function () { + return this._rQ[this._rQi]; + }, + + rQshift8: function () { + return this._rQ[this._rQi++]; + }, + + rQskip8: function () { + this._rQi++; + }, + + rQskipBytes: function (num) { + this._rQi += num; + }, + + // TODO(directxman12): test performance with these vs a DataView + rQshift16: function () { + return (this._rQ[this._rQi++] << 8) + + this._rQ[this._rQi++]; + }, + + rQshift32: function () { + return (this._rQ[this._rQi++] << 24) + + (this._rQ[this._rQi++] << 16) + + (this._rQ[this._rQi++] << 8) + + this._rQ[this._rQi++]; + }, + + rQshiftStr: function (len) { + if (typeof(len) === 'undefined') { len = this.rQlen(); } + var arr = new Uint8Array(this._rQ.buffer, this._rQi, len); + this._rQi += len; + return typedArrayToString(arr); + }, + + rQshiftBytes: function (len) { + if (typeof(len) === 'undefined') { len = this.rQlen(); } + this._rQi += len; + return new Uint8Array(this._rQ.buffer, this._rQi - len, len); + }, + + rQshiftTo: function (target, len) { + if (len === undefined) { len = this.rQlen(); } + // TODO: make this just use set with views when using a ArrayBuffer to store the rQ + target.set(new Uint8Array(this._rQ.buffer, this._rQi, len)); + this._rQi += len; + }, + + rQwhole: function () { + return new Uint8Array(this._rQ.buffer, 0, this._rQlen); + }, + + rQslice: function (start, end) { + if (end) { + return new Uint8Array(this._rQ.buffer, this._rQi + start, end - start); + } else { + return new Uint8Array(this._rQ.buffer, this._rQi + start, this._rQlen - this._rQi - start); + } + }, + + // Check to see if we must wait for 'num' bytes (default to FBU.bytes) + // to be available in the receive queue. Return true if we need to + // wait (and possibly print a debug message), otherwise false. + rQwait: function (msg, num, goback) { + var rQlen = this._rQlen - this._rQi; // Skip rQlen() function call + if (rQlen < num) { + if (goback) { + if (this._rQi < goback) { + throw new Error("rQwait cannot backup " + goback + " bytes"); + } + this._rQi -= goback; + } + return true; // true means need more data + } + return false; + }, + + // Send Queue + + flush: function () { + if (this._websocket.bufferedAmount !== 0) { + Log.Debug("bufferedAmount: " + this._websocket.bufferedAmount); + } + + if (this._sQlen > 0 && this._websocket.readyState === WebSocket.OPEN) { + this._websocket.send(this._encode_message()); + this._sQlen = 0; + } + }, + + send: function (arr) { + this._sQ.set(arr, this._sQlen); + this._sQlen += arr.length; + this.flush(); + }, + + send_string: function (str) { + this.send(str.split('').map(function (chr) { + return chr.charCodeAt(0); + })); + }, + + // Event Handlers + off: function (evt) { + this._eventHandlers[evt] = function () {}; + }, + + on: function (evt, handler) { + this._eventHandlers[evt] = handler; + }, + + _allocate_buffers: function () { + this._rQ = new Uint8Array(this._rQbufferSize); + this._sQ = new Uint8Array(this._sQbufferSize); + }, + + init: function () { + this._allocate_buffers(); + this._rQi = 0; + this._websocket = null; + }, + + open: function (uri, protocols) { + var ws_schema = uri.match(/^([a-z]+):\/\//)[1]; + this.init(); + + this._websocket = new WebSocket(uri, protocols); + this._websocket.binaryType = 'arraybuffer'; + + this._websocket.onmessage = this._recv_message.bind(this); + this._websocket.onopen = (function () { + Log.Debug('>> WebSock.onopen'); + if (this._websocket.protocol) { + Log.Info("Server choose sub-protocol: " + this._websocket.protocol); + } + + this._eventHandlers.open(); + Log.Debug("<< WebSock.onopen"); + }).bind(this); + this._websocket.onclose = (function (e) { + Log.Debug(">> WebSock.onclose"); + this._eventHandlers.close(e); + Log.Debug("<< WebSock.onclose"); + }).bind(this); + this._websocket.onerror = (function (e) { + Log.Debug(">> WebSock.onerror: " + e); + this._eventHandlers.error(e); + Log.Debug("<< WebSock.onerror: " + e); + }).bind(this); + }, + + close: function () { + if (this._websocket) { + if ((this._websocket.readyState === WebSocket.OPEN) || + (this._websocket.readyState === WebSocket.CONNECTING)) { + Log.Info("Closing WebSocket connection"); + this._websocket.close(); + } + + this._websocket.onmessage = function (e) { return; }; + } + }, + + // private methods + _encode_message: function () { + // Put in a binary arraybuffer + // according to the spec, you can send ArrayBufferViews with the send method + return new Uint8Array(this._sQ.buffer, 0, this._sQlen); + }, + + _expand_compact_rQ: function (min_fit) { + var resizeNeeded = min_fit || this._rQlen - this._rQi > this._rQbufferSize / 2; + if (resizeNeeded) { + if (!min_fit) { + // just double the size if we need to do compaction + this._rQbufferSize *= 2; + } else { + // otherwise, make sure we satisy rQlen - rQi + min_fit < rQbufferSize / 8 + this._rQbufferSize = (this._rQlen - this._rQi + min_fit) * 8; + } + } + + // we don't want to grow unboundedly + if (this._rQbufferSize > MAX_RQ_GROW_SIZE) { + this._rQbufferSize = MAX_RQ_GROW_SIZE; + if (this._rQbufferSize - this._rQlen - this._rQi < min_fit) { + throw new Exception("Receive Queue buffer exceeded " + MAX_RQ_GROW_SIZE + " bytes, and the new message could not fit"); + } + } + + if (resizeNeeded) { + var old_rQbuffer = this._rQ.buffer; + this._rQmax = this._rQbufferSize / 8; + this._rQ = new Uint8Array(this._rQbufferSize); + this._rQ.set(new Uint8Array(old_rQbuffer, this._rQi)); + } else { + if (ENABLE_COPYWITHIN) { + this._rQ.copyWithin(0, this._rQi); + } else { + this._rQ.set(new Uint8Array(this._rQ.buffer, this._rQi)); + } + } + + this._rQlen = this._rQlen - this._rQi; + this._rQi = 0; + }, + + _decode_message: function (data) { + // push arraybuffer values onto the end + var u8 = new Uint8Array(data); + if (u8.length > this._rQbufferSize - this._rQlen) { + this._expand_compact_rQ(u8.length); + } + this._rQ.set(u8, this._rQlen); + this._rQlen += u8.length; + }, + + _recv_message: function (e) { + try { + this._decode_message(e.data); + if (this.rQlen() > 0) { + this._eventHandlers.message(); + // Compact the receive queue + if (this._rQlen == this._rQi) { + this._rQlen = 0; + this._rQi = 0; + } else if (this._rQlen > this._rQmax) { + this._expand_compact_rQ(); + } + } else { + Log.Debug("Ignoring empty message"); + } + } catch (exc) { + var exception_str = ""; + if (exc.name) { + exception_str += "\n name: " + exc.name + "\n"; + exception_str += " message: " + exc.message + "\n"; + } + + if (typeof exc.description !== 'undefined') { + exception_str += " description: " + exc.description + "\n"; + } + + if (typeof exc.stack !== 'undefined') { + exception_str += exc.stack; + } + + if (exception_str.length > 0) { + Log.Error("recv_message, caught exception: " + exception_str); + } else { + Log.Error("recv_message, caught exception: " + exc); + } + + if (typeof exc.name !== 'undefined') { + this._eventHandlers.error(exc.name + ": " + exc.message); + } else { + this._eventHandlers.error(exc); + } + } + } +}; diff --git a/karma.conf.js b/karma.conf.js index 5f3c20b9..821007ee 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,56 +1,6 @@ // Karma configuration module.exports = function(config) { - /*var customLaunchers = { - sl_chrome_win7: { - base: 'SauceLabs', - browserName: 'chrome', - platform: 'Windows 7' - }, - - sl_firefox30_linux: { - base: 'SauceLabs', - browserName: 'firefox', - version: '30', - platform: 'Linux' - }, - - sl_firefox26_linux: { - base: 'SauceLabs', - browserName: 'firefox', - version: 26, - platform: 'Linux' - }, - - sl_windows7_ie10: { - base: 'SauceLabs', - browserName: 'internet explorer', - platform: 'Windows 7', - version: '10' - }, - - sl_windows81_ie11: { - base: 'SauceLabs', - browserName: 'internet explorer', - platform: 'Windows 8.1', - version: '11' - }, - - sl_osxmavericks_safari7: { - base: 'SauceLabs', - browserName: 'safari', - platform: 'OS X 10.9', - version: '7' - }, - - sl_osxmtnlion_safari6: { - base: 'SauceLabs', - browserName: 'safari', - platform: 'OS X 10.8', - version: '6' - } - };*/ - var customLaunchers = {}; var browsers = []; var useSauce = false; @@ -93,7 +43,8 @@ module.exports = function(config) { browsers = Object.keys(customLaunchers); } else { useSauce = false; - browsers = ['PhantomJS']; + //browsers = ['PhantomJS']; + browsers = []; } var my_conf = { @@ -103,39 +54,30 @@ module.exports = function(config) { // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ['mocha', 'sinon', 'chai', 'sinon-chai'], - + frameworks: ['requirejs', 'mocha', 'chai'], // list of files / patterns to load in the browser (loaded in order) files: [ - 'tests/fake.*.js', - 'tests/assertions.js', - 'core/util.js', // load first to avoid issues, since methods are called immediately - //'../core/*.js', - 'core/base64.js', - 'core/input/keysym.js', - 'core/input/keysymdef.js', - 'core/input/xtscancodes.js', - 'core/input/util.js', - 'core/input/devices.js', - 'core/websock.js', - 'core/rfb.js', - 'core/des.js', - 'core/display.js', - 'core/inflator.js', - 'tests/test.*.js' + { pattern: 'vendor/sinon.js', included: false }, + { pattern: 'node_modules/sinon-chai/lib/sinon-chai.js', included: false }, + { pattern: 'core/**/*.js', included: false }, + { pattern: 'vendor/pako/**/*.js', included: false }, + { pattern: 'tests/test.*.js', included: false }, + { pattern: 'tests/fake.*.js', included: false }, + { pattern: 'tests/assertions.js', included: false }, + 'tests/karma-test-main.js', ], client: { mocha: { + // replace Karma debug page with mocha display + 'reporter': 'html', 'ui': 'bdd' } }, // list of files to exclude exclude: [ - '../tests/playback.js', - '../app/ui.js' ], customLaunchers: customLaunchers, @@ -147,14 +89,24 @@ module.exports = function(config) { // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { - + 'core/**/*.js': ['babel'], + 'tests/test.*.js': ['babel'], + 'tests/fake.*.js': ['babel'], + 'tests/assertions.js': ['babel'], + 'vendor/pako/**/*.js': ['babel'], }, + babelPreprocessor: { + options: { + plugins: ['transform-es2015-modules-amd', 'syntax-dynamic-import'], + sourceMap: 'inline', + }, + }, // test results reporter to use // possible values: 'dots', 'progress' // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ['mocha', 'saucelabs'], + reporters: ['mocha'], // web server port @@ -186,6 +138,7 @@ module.exports = function(config) { }; if (useSauce) { + my_conf.reporters.push('saucelabs'); my_conf.captureTimeout = 0; // use SL timeout my_conf.sauceLabs = { testName: 'noVNC Tests (all)', diff --git a/package.json b/package.json index 52f76f6d..716a12f9 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,7 @@ }, "scripts": { "test": "PATH=$PATH:node_modules/karma/bin karma start karma.conf.js", - "prepublish": "node ./utils/use_require.js --as-require", - "build-es6": "node ./utils/use_require.js" + "prepublish": "node ./utils/use_require.js --as commonjs" }, "repository": { "type": "git", @@ -28,36 +27,33 @@ }, "homepage": "https://github.com/kanaka/noVNC", "devDependencies": { - "ansi": "^0.3.1", + "babel-core": "^6.22.1", "babel-plugin-add-module-exports": "^0.2.1", + "babel-plugin-syntax-dynamic-import": "^6.18.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", "babel-plugin-transform-es2015-modules-commonjs": "^6.18.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.22.0", + "babel-plugin-transform-es2015-modules-umd": "^6.22.0", "babelify": "^7.3.0", "browserify": "^13.1.0", - "casperjs": "^1.1.3", "chai": "^3.5.0", "commander": "^2.9.0", + "es-module-loader": "^2.1.0", "fs-extra": "^1.0.0", "jsdom": "*", "karma": "^1.3.0", + "karma-babel-preprocessor": "^6.0.1", "karma-chai": "^0.1.0", "karma-mocha": "^1.3.0", "karma-mocha-reporter": "^2.2.0", - "karma-phantomjs-launcher": "^1.0.2", + "karma-requirejs": "^1.1.0", "karma-sauce-launcher": "^1.0.0", - "karma-sinon": "^1.0.5", - "karma-sinon-chai-latest": "^0.1.0", "mocha": "^3.1.2", "node-getopt": "*", - "open": "^0.0.5", - "phantomjs-prebuilt": "^2.1.13", "po2json": "*", - "sinon": "^1.17.6", - "sinon-chai": "^2.8.0", - "spooky": "^0.2.5", - "temp": "^0.8.3", - "through2": "^2.0.1" - }, - "dependencies": { - "pako": "^1.0.3" + "requirejs": "^2.3.2", + "rollup": "^0.41.4", + "rollup-plugin-node-resolve": "^2.0.0", + "sinon-chai": "^2.8.0" } } diff --git a/po/Makefile b/po/Makefile index b64b7638..8c6000ba 100644 --- a/po/Makefile +++ b/po/Makefile @@ -6,14 +6,14 @@ LINGUAS := de el nl sv VERSION := $(shell grep '"version"' ../package.json | cut -d '"' -f 4) POFILES := $(addsuffix .po,$(LINGUAS)) -JSFILES := $(addprefix ../app/locale/,$(addsuffix .js,$(LINGUAS))) +JSONFILES := $(addprefix ../app/locale/,$(addsuffix .json,$(LINGUAS))) update-po: $(POFILES) -update-js: $(JSFILES) +update-js: $(JSONFILES) %.po: noVNC.pot msgmerge --update --lang=$* $@ $< -../app/locale/%.js: %.po +../app/locale/%.json: %.po ./po2js $< $@ update-pot: diff --git a/po/po2js b/po/po2js index 972f0b2c..15304c9c 100755 --- a/po/po2js +++ b/po/po2js @@ -32,25 +32,12 @@ if (opt.argv.length != 2) { var data = po2json.parseFileSync(opt.argv[0]); -var output = -"/*\n" + -" * Translations for " + data[""]["language"] + "\n" + -" *\n" + -" * This file was autotomatically generated from " + opt.argv[0] + "\n" + -" * DO NOT EDIT!\n" + -" */\n" + -"\n" + -"Language = {\n"; +var bodyPart = Object.keys(data).filter((msgid) => msgid !== "").map((msgid) => { + if (msgid === "") return; + var msgstr = data[msgid][1]; + return " " + JSON.stringify(msgid) + ": " + JSON.stringify(msgstr); +}).join(",\n"); -for (msgid in data) { - if (msgid === "") - continue; - - msgstr = data[msgid][1]; - output += " " + JSON.stringify(msgid) + ": " + - JSON.stringify(msgstr) + ",\n"; -} - -output += "};\n"; +var output = "{\n" + bodyPart + "\n}"; fs.writeFileSync(opt.argv[1], output); diff --git a/tests/fake.websocket.js b/tests/fake.websocket.js index 21012059..eb4f203d 100644 --- a/tests/fake.websocket.js +++ b/tests/fake.websocket.js @@ -1,91 +1,87 @@ -var FakeWebSocket; - -(function () { - // PhantomJS can't create Event objects directly, so we need to use this - function make_event(name, props) { - var evt = document.createEvent('Event'); - evt.initEvent(name, true, true); - if (props) { - for (var prop in props) { - evt[prop] = props[prop]; - } +// PhantomJS can't create Event objects directly, so we need to use this +function make_event(name, props) { + var evt = document.createEvent('Event'); + evt.initEvent(name, true, true); + if (props) { + for (var prop in props) { + evt[prop] = props[prop]; } - return evt; + } + return evt; +} + +export default function FakeWebSocket (uri, protocols) { + this.url = uri; + this.binaryType = "arraybuffer"; + this.extensions = ""; + + if (!protocols || typeof protocols === 'string') { + this.protocol = protocols; + } else { + this.protocol = protocols[0]; } - FakeWebSocket = function (uri, protocols) { - this.url = uri; - this.binaryType = "arraybuffer"; - this.extensions = ""; + this._send_queue = new Uint8Array(20000); - if (!protocols || typeof protocols === 'string') { - this.protocol = protocols; + this.readyState = FakeWebSocket.CONNECTING; + this.bufferedAmount = 0; + + this.__is_fake = true; +}; + +FakeWebSocket.prototype = { + close: function (code, reason) { + this.readyState = FakeWebSocket.CLOSED; + if (this.onclose) { + this.onclose(make_event("close", { 'code': code, 'reason': reason, 'wasClean': true })); + } + }, + + send: function (data) { + if (this.protocol == 'base64') { + data = Base64.decode(data); } else { - this.protocol = protocols[0]; + data = new Uint8Array(data); } + this._send_queue.set(data, this.bufferedAmount); + this.bufferedAmount += data.length; + }, - this._send_queue = new Uint8Array(20000); - - this.readyState = FakeWebSocket.CONNECTING; + _get_sent_data: function () { + var res = new Uint8Array(this._send_queue.buffer, 0, this.bufferedAmount); this.bufferedAmount = 0; + return res; + }, - this.__is_fake = true; - }; - - FakeWebSocket.prototype = { - close: function (code, reason) { - this.readyState = FakeWebSocket.CLOSED; - if (this.onclose) { - this.onclose(make_event("close", { 'code': code, 'reason': reason, 'wasClean': true })); - } - }, - - send: function (data) { - if (this.protocol == 'base64') { - data = Base64.decode(data); - } else { - data = new Uint8Array(data); - } - this._send_queue.set(data, this.bufferedAmount); - this.bufferedAmount += data.length; - }, - - _get_sent_data: function () { - var res = new Uint8Array(this._send_queue.buffer, 0, this.bufferedAmount); - this.bufferedAmount = 0; - return res; - }, - - _open: function (data) { - this.readyState = FakeWebSocket.OPEN; - if (this.onopen) { - this.onopen(make_event('open')); - } - }, - - _receive_data: function (data) { - this.onmessage(make_event("message", { 'data': data })); + _open: function (data) { + this.readyState = FakeWebSocket.OPEN; + if (this.onopen) { + this.onopen(make_event('open')); } - }; + }, - FakeWebSocket.OPEN = WebSocket.OPEN; - FakeWebSocket.CONNECTING = WebSocket.CONNECTING; - FakeWebSocket.CLOSING = WebSocket.CLOSING; - FakeWebSocket.CLOSED = WebSocket.CLOSED; + _receive_data: function (data) { + this.onmessage(make_event("message", { 'data': data })); + } +}; - FakeWebSocket.__is_fake = true; +FakeWebSocket.OPEN = WebSocket.OPEN; +FakeWebSocket.CONNECTING = WebSocket.CONNECTING; +FakeWebSocket.CLOSING = WebSocket.CLOSING; +FakeWebSocket.CLOSED = WebSocket.CLOSED; - FakeWebSocket.replace = function () { - if (!WebSocket.__is_fake) { - var real_version = WebSocket; - WebSocket = FakeWebSocket; - FakeWebSocket.__real_version = real_version; - } - }; +FakeWebSocket.__is_fake = true; - FakeWebSocket.restore = function () { - if (WebSocket.__is_fake) { - WebSocket = WebSocket.__real_version; - } - }; -})(); +FakeWebSocket.replace = function () { + if (!WebSocket.__is_fake) { + var real_version = WebSocket; + WebSocket = FakeWebSocket; + FakeWebSocket.__real_version = real_version; + } +}; + +FakeWebSocket.restore = function () { + if (WebSocket.__is_fake) { + WebSocket = WebSocket.__real_version; + } +}; diff --git a/tests/karma-test-main.js b/tests/karma-test-main.js new file mode 100644 index 00000000..35b46973 --- /dev/null +++ b/tests/karma-test-main.js @@ -0,0 +1,18 @@ +var TEST_REGEXP = /test\..*\.js/; +var allTestFiles = []; + +Object.keys(window.__karma__.files).forEach(function (file) { + if (TEST_REGEXP.test(file)) { + // TODO: normalize? + allTestFiles.push(file); + } +}); + +require.config({ + baseUrl: '/base', + deps: allTestFiles, + callback: window.__karma__.start, + paths: { + 'sinon': 'vendor/sinon', + }, +}); diff --git a/tests/playback-ui.js b/tests/playback-ui.js new file mode 100644 index 00000000..f47b9d86 --- /dev/null +++ b/tests/playback-ui.js @@ -0,0 +1,174 @@ +import * as WebUtil from '../app/webutil.js'; +import RecordingPlayer from './playback.js'; + +var frames = null; +var encoding = null; + +function message(str) { + console.log(str); + var cell = document.getElementById('messages'); + cell.textContent += str + "\n"; + cell.scrollTop = cell.scrollHeight; +} + +function loadFile() { + const fname = WebUtil.getQueryVar('data', null); + + if (!fname) { + return Promise.reject("Must specify data=FOO in query string."); + } + + message("Loading " + fname); + return import(`../recordings/${fname}#nocache`); +} + +function enableUI(recording) { + var iterations = WebUtil.getQueryVar('iterations', 3); + document.getElementById('iterations').value = iterations; + + var mode = WebUtil.getQueryVar('mode', 3); + if (mode === 'realtime') { + document.getElementById('mode2').checked = true; + } else { + document.getElementById('mode1').checked = true; + } + + message("VNC_frame_data.length: " + recording.VNC_frame_data.length); + + const startButton = document.getElementById('startButton'); + startButton.disabled = false + startButton.addEventListener('click', start); + + frames = recording.VNC_frame_data; + encoding = recording.VNC_frame_encoding; +} + +const notification = function (rfb, mesg, level, options) { + document.getElementById('VNC_status').textContent = mesg; +} + +function IterationPlayer (iterations, frames, encoding) { + this._iterations = iterations; + + this._iteration = undefined; + this._player = undefined; + + this._start_time = undefined; + + this._frames = frames; + this._encoding = encoding; + + this._state = 'running'; + + this.onfinish = function() {}; + this.oniterationfinish = function() {}; + this.rfbdisconnected = function() {}; + this.rfbnotification = function() {}; +} + +IterationPlayer.prototype = { + start: function (mode) { + this._iteration = 0; + this._start_time = (new Date()).getTime(); + + this._realtime = mode.startsWith('realtime'); + this._trafficMgmt = !mode.endsWith('-no-mgmt'); + + this._nextIteration(); + }, + + _nextIteration: function () { + const player = new RecordingPlayer(this._frames, this._encoding, this._disconnected.bind(this), this._notification.bind(this)); + player.onfinish = this._iterationFinish.bind(this); + + if (this._state !== 'running') { return; } + + this._iteration++; + if (this._iteration > this._iterations) { + this._finish(); + return; + } + + player.run(this._realtime, this._trafficMgmt); + }, + + _finish: function () { + const endTime = (new Date()).getTime(); + const totalDuration = endTime - this._start_time; + + const evt = new Event('finish'); + evt.duration = totalDuration; + evt.iterations = this._iterations; + this.onfinish(evt); + }, + + _iterationFinish: function (duration) { + const evt = new Event('iterationfinish'); + evt.duration = duration; + evt.number = this._iteration; + this.oniterationfinish(evt); + + this._nextIteration(); + }, + + _disconnected: function (rfb, reason, frame) { + if (reason) { + this._state = 'failed'; + } + + var evt = new Event('rfbdisconnected'); + evt.reason = reason; + evt.frame = frame; + + this.onrfbdisconnected(evt); + }, + + _notification: function (rfb, msg, level, options) { + var evt = new Event('rfbnotification'); + evt.message = msg; + evt.level = level; + evt.options = options; + + this.onrfbnotification(evt); + }, +}; + +function start() { + document.getElementById('startButton').value = "Running"; + document.getElementById('startButton').disabled = true; + + const iterations = document.getElementById('iterations').value; + + var mode; + + if (document.getElementById('mode1').checked) { + message(`Starting performance playback (fullspeed) [${iterations} iteration(s)]`); + mode = 'perftest'; + } else { + message(`Starting realtime playback [${iterations} iteration(s)]`); + mode = 'realtime'; + } + + const player = new IterationPlayer(iterations, frames, encoding); + player.oniterationfinish = function (evt) { + message(`Iteration ${evt.number} took ${evt.duration}ms`); + }; + player.onrfbdisconnected = function (evt) { + if (evt.reason) { + message(`noVNC sent disconnected during iteration ${evt.iteration} frame ${evt.frame}`); + } + }; + player.onrfbnotification = function (evt) { + document.getElementById('VNC_status').textContent = evt.message; + }; + player.onfinish = function (evt) { + const iterTime = parseInt(evt.duration / evt.iterations, 10); + message(`${evt.iterations} iterations took ${evt.duration}ms (average ${iterTime}ms / iteration)`); + + document.getElementById('startButton').disabled = false; + document.getElementById('startButton').value = "Start"; + }; + player.start(mode); +} + +loadFile().then(enableUI).catch(message); diff --git a/tests/playback.js b/tests/playback.js index a25fac49..b39c9818 100644 --- a/tests/playback.js +++ b/tests/playback.js @@ -4,29 +4,17 @@ * Licensed under MPL 2.0 (see LICENSE.txt) */ -"use strict"; -/*jslint browser: true, white: false */ -/*global Util, VNC_frame_data, finish */ - -var rfb, mode, test_state, frame_idx, frame_length, - iteration, iterations, istart_time, encoding, - - // Pre-declarations for jslint - send_array, next_iteration, end_iteration, queue_next_packet, - do_packet, enable_test_mode; - -// Override send_array -send_array = function (arr) { - // Stub out send_array -}; +import RFB from '../core/rfb.js'; +import * as Log from '../core/util/logging.js'; +import Base64 from '../core/base64.js'; // Immediate polyfill -if (window.setImmediate === undefined) { +if (setImmediate === undefined) { var _immediateIdCounter = 1; var _immediateFuncs = {}; - window.setImmediate = function (func) { - var index = Util._immediateIdCounter++; + var setImmediate = function (func) { + var index = _immediateIdCounter++; _immediateFuncs[index] = func; window.postMessage("noVNC immediate trigger:" + index, "*"); return index; @@ -56,143 +44,160 @@ if (window.setImmediate === undefined) { window.addEventListener("message", _onMessage); } -enable_test_mode = function () { - rfb._sock.send = send_array; - rfb._sock.close = function () {}; - rfb._sock.flush = function () {}; - rfb._checkEvents = function () {}; - rfb.connect = function (host, port, password, path) { - this._rfb_host = host; - this._rfb_port = port; - this._rfb_password = (password !== undefined) ? password : ""; - this._rfb_path = (path !== undefined) ? path : ""; - this._sock.init('binary', 'ws'); - this._rfb_connection_state = 'connecting'; - this._rfb_init_state = 'ProtocolVersion'; - }; -}; +export default function RecordingPlayer (frames, encoding, disconnected, notification) { + this._frames = frames; + this._encoding = encoding; -next_iteration = function () { - rfb = new RFB({'target': document.getElementById('VNC_canvas'), - 'view_only': true, - 'onDisconnected': disconnected, - 'onNotification': notification}); - enable_test_mode(); + this._disconnected = disconnected; + this._notification = notification; - // Missing in older recordings - if (typeof VNC_frame_encoding === 'undefined') { - var frame = VNC_frame_data[0]; - var start = frame.indexOf('{', 1) + 1; + if (this._encoding === undefined) { + let frame = this._frames[0]; + let start = frame.indexOf('{', 1) + 1; if (frame.slice(start).startsWith('UkZC')) { - encoding = 'base64'; + this._encoding = 'base64'; } else { - encoding = 'binary'; + this._encoding = 'binary'; } - } else { - encoding = VNC_frame_encoding; } - if (iteration === 0) { - frame_length = VNC_frame_data.length; - test_state = 'running'; - } + this._rfb = undefined; + this._frame_length = this._frames.length; - if (test_state !== 'running') { return; } + this._frame_index = 0; + this._start_time = undefined; + this._realtime = true; + this._trafficManagement = true; - iteration += 1; - if (iteration > iterations) { - finish(); - return; - } + this._running = false; - frame_idx = 0; - istart_time = (new Date()).getTime(); - rfb.connect('test', 0, "bogus"); + this.onfinish = function () {}; +} - queue_next_packet(); +RecordingPlayer.prototype = { + run: function (realtime, trafficManagement) { + // initialize a new RFB + this._rfb = new RFB({'target': document.getElementById('VNC_canvas'), + 'view_only': true, + 'onDisconnected': this._handleDisconnect.bind(this), + 'onNotification': this._notification}); + this._enablePlaybackMode(); -}; + // reset the frame index and timer + this._frame_index = 0; + this._start_time = (new Date()).getTime(); -end_iteration = function () { - if (rfb._display.pending()) { - rfb._display.set_onFlush(function () { - if (rfb._flushing) { - rfb._onFlush(); + this._realtime = realtime; + this._trafficManagement = (trafficManagement === undefined) ? !realtime : trafficManagement; + + this._running = true; + + // launch the tests + this._rfb.connect('test', 0, 'bogus'); + + this._queueNextPacket(); + }, + + // _enablePlaybackMode mocks out things not required for running playback + _enablePlaybackMode: function () { + this._rfb._sock.send = function (arr) {}; + this._rfb._sock.close = function () {}; + this._rfb._sock.flush = function () {}; + this._rfb._checkEvents = function () {}; + this._rfb.connect = function (host, port, password, path) { + this._rfb_host = host; + this._rfb_port = port; + this._rfb_password = (password !== undefined) ? password : ""; + this._rfb_path = (path !== undefined) ? path : ""; + this._sock.init('binary', 'ws'); + this._rfb_connection_state = 'connecting'; + this._rfb_init_state = 'ProtocolVersion'; + }; + }, + + _queueNextPacket: function () { + if (!this._running) { return; } + + var frame = this._frames[this._frame_index]; + + // skip send frames + while (this._frame_index < this._frame_length && frame.charAt(0) === "}") { + this._frame_index++; + frame = this._frames[this._frame_index]; + } + + if (frame === 'EOF') { + Log.Debug('Finished, found EOF'); + this._finish(); + return; + } + + if (this._frame_index >= this._frame_length) { + Log.Debug('Finished, no more frames'); + this._finish(); + return; + } + + if (this._realtime) { + let foffset = frame.slice(1, frame.indexOf('{', 1)); + let toffset = (new Date()).getTime() - this._start_time; + let delay = foffset - toffset; + if (delay < 1) delay = 1; + + setTimeout(this._doPacket.bind(this), delay); + } else { + setImmediate(this._doPacket.bind(this)); + } + }, + + _doPacket: function () { + // Avoid having excessive queue buildup in non-realtime mode + if (!this._trafficManagement && this._rfb._flushing) { + let player = this; + this._rfb.display.set_onFlush(function () { + this._rfb._display.set_onFlush(this._rfb._onFlush.bind(this._rfb)); + this._rfb._onFlush(); + player._doPacket(); + }); + return; + } + + const frame = this._frames[this._frame_index]; + var start = frame.indexOf('{', 1) + 1; + if (this._encoding === 'base64') { + var u8 = Base64.decode(frame.slice(start)); + start = 0; + } else { + var u8 = new Uint8Array(frame.length - start); + for (let i = 0; i < frame.length - start; i++) { + u8[i] = frame.charCodeAt(start + i); } - end_iteration(); - }); - rfb._display.flush(); - } else { - next_iteration(); - } -}; - -queue_next_packet = function () { - var frame, foffset, toffset, delay; - if (test_state !== 'running') { return; } - - frame = VNC_frame_data[frame_idx]; - while ((frame_idx < frame_length) && (frame.charAt(0) === "}")) { - //Util.Debug("Send frame " + frame_idx); - frame_idx += 1; - frame = VNC_frame_data[frame_idx]; - } - - if (frame === 'EOF') { - Util.Debug("Finished, found EOF"); - end_iteration(); - return; - } - if (frame_idx >= frame_length) { - Util.Debug("Finished, no more frames"); - end_iteration(); - return; - } - - if (mode === 'realtime') { - foffset = frame.slice(1, frame.indexOf('{', 1)); - toffset = (new Date()).getTime() - istart_time; - delay = foffset - toffset; - if (delay < 1) { - delay = 1; } - setTimeout(do_packet, delay); - } else { - window.setImmediate(do_packet); - } -}; + this._rfb._sock._recv_message({'data': u8}); + this._frame_index++; -var bytes_processed = 0; + this._queueNextPacket(); + }, -do_packet = function () { - // Avoid having an excessive queue buildup - if (rfb._flushing && (mode !== 'realtime')) { - rfb._display.set_onFlush(function () { - rfb._display.set_onFlush(rfb._onFlush.bind(rfb)); - rfb._onFlush(); - do_packet(); - }); - return; - } - - //Util.Debug("Processing frame: " + frame_idx); - var frame = VNC_frame_data[frame_idx], - start = frame.indexOf('{', 1) + 1; - var u8; - if (encoding === 'base64') { - u8 = Base64.decode(frame.slice(start)); - start = 0; - } else { - u8 = new Uint8Array(frame.length - start); - for (var i = 0; i < frame.length - start; i++) { - u8[i] = frame.charCodeAt(start + i); + _finish() { + if (this._rfb._display.pending()) { + var player = this; + this._rfb._display.set_onFlush(function () { + if (player._rfb._flushing) { + player._rfb._onFlush(); + } + player._finish(); + }); + this._rfb._display.flush(); + } else { + this._running = false; + this.onfinish((new Date()).getTime() - this._start_time); } + }, + + _handleDisconnect(rfb, reason) { + this._running = false; + this._disconnected(rfb, reason, this._frame_index); } - bytes_processed += u8.length; - rfb._sock._recv_message({'data' : u8}); - frame_idx += 1; - - queue_next_packet(); }; - diff --git a/tests/run_from_console.casper.js b/tests/run_from_console.casper.js deleted file mode 100644 index ba8546b9..00000000 --- a/tests/run_from_console.casper.js +++ /dev/null @@ -1,114 +0,0 @@ -var Spooky = require('spooky'); -var path = require('path'); - -var phantom_path = require('phantomjs-prebuilt').path; -var casper_path = path.resolve(__dirname, '../node_modules/casperjs/bin/casperjs'); -process.env.PHANTOMJS_EXECUTABLE = phantom_path; -var casper_opts = { - child: { - transport: 'http', - command: casper_path - }, - casper: { - logLevel: 'debug', - verbose: true - } -}; - -var provide_emitter = function(file_paths, debug_port) { - if (debug_port) { - casper_opts.child['remote-debugger-port'] = debug_port; - var debug_url = ('https://localhost:' + debug_port + - '/webkit/inspector/inspector.html?page='); - console.info('[remote-debugger] Navigate to ' + debug_url + '1 and ' + - 'run `__run();` in the console to continue loading.' + - '\n[remote-debugger] Navigate to ' + debug_url + '2 to ' + - 'view the actual page source.\n' + - '[remote-debugger] Use the `debugger;` statement to ' + - 'trigger an initial breakpoint.'); - } - - var spooky = new Spooky(casper_opts, function(err) { - if (err) { - if (err.stack) console.warn(err.stack); - else console.warn(err); - return; - } - spooky.start('about:blank'); - - file_paths.forEach(function(file_path, path_ind) { - spooky.thenOpen('file://'+file_path); - spooky.waitFor(function() { - return this.getGlobal('__mocha_done') === true; - }, - [{ path_ind: path_ind }, function() { - var res_json = { - file_ind: path_ind - }; - - res_json.num_tests = this.evaluate(function() { return document.querySelectorAll('li.test').length; }); - res_json.num_passes = this.evaluate(function() { return document.querySelectorAll('li.test.pass').length; }); - res_json.num_fails = this.evaluate(function() { return document.querySelectorAll('li.test.fail').length; }); - res_json.num_slow = this.evaluate(function() { return document.querySelectorAll('li.test.pass:not(.fast):not(.pending)').length; }); - res_json.num_skipped = this.evaluate(function () { return document.querySelectorAll('li.test.pending').length; }); - res_json.duration = this.evaluate(function() { return document.querySelector('li.duration em').textContent; }); - - res_json.suites = this.evaluate(function() { - var traverse_node = function(elem) { - var res; - if (elem.classList.contains('suite')) { - res = { - type: 'suite', - name: elem.querySelector('h1').textContent, - has_subfailures: elem.querySelectorAll('li.test.fail').length > 0, - }; - - var child_elems = elem.querySelector('ul').children; - res.children = Array.prototype.map.call(child_elems, traverse_node); - return res; - } - else { - var h2_content = elem.querySelector('h2').childNodes; - res = { - type: 'test', - text: h2_content[0].textContent, - }; - - if (elem.classList.contains('pass')) { - res.pass = true; - if (elem.classList.contains('pending')) { - res.slow = false; - res.skipped = true; - } - else { - res.slow = !elem.classList.contains('fast'); - res.skipped = false; - res.duration = h2_content[1].textContent; - } - } - else { - res.error = elem.querySelector('pre.error').textContent; - } - - return res; - } - }; - var top_suites = document.querySelectorAll('#mocha-report > li.suite'); - return Array.prototype.map.call(top_suites, traverse_node); - }); - - res_json.replay = this.evaluate(function() { return document.querySelector('a.replay').textContent; }); - - this.emit('test_ready', res_json); - }]); - }); - spooky.run(); - }); - - return spooky; -}; - -module.exports = { - provide_emitter: provide_emitter, - name: 'SpookyJS (CapserJS on PhantomJS)' -}; diff --git a/tests/run_from_console.js b/tests/run_from_console.js deleted file mode 100755 index a743d47a..00000000 --- a/tests/run_from_console.js +++ /dev/null @@ -1,360 +0,0 @@ -#!/usr/bin/env node -var ansi = require('ansi'); -var program = require('commander'); -var path = require('path'); -var fs = require('fs'); - -var make_list = function(val) { - return val.split(','); -}; - -program - .option('-t, --tests ', 'Run the specified html-file-based test(s). \'testlist\' should be a comma-separated list', make_list, []) - .option('-a, --print-all', 'Print all tests, not just the failures') - .option('--disable-color', 'Explicitly disable color') - .option('-c, --color', 'Explicitly enable color (default is to use color when not outputting to a pipe)') - .option('-i, --auto-inject ', 'Treat the test list as a set of mocha JS files, and automatically generate HTML files with which to test test. \'includefiles\' should be a comma-separated list of paths to javascript files to include in each of the generated HTML files', make_list, null) - .option('-p, --provider ', 'Use the given provider (defaults to "casper"). Currently, may be "casper" or "zombie"', 'casper') - .option('-g, --generate-html', 'Instead of running the tests, just return the path to the generated HTML file, then wait for user interaction to exit (should be used with .js tests).') - .option('-o, --open-in-browser', 'Open the generated HTML files in a web browser using the "open" module (must be used with the "-g"/"--generate-html" option).') - .option('--output-html', 'Instead of running the tests, just output the generated HTML source to STDOUT (should be used with .js tests)') - .option('-d, --debug', 'Show debug output (the "console" event) from the provider') - .option('-r, --relative', 'Use relative paths in the generated HTML file') - .option('--debugger ', 'Enable the remote debugger for CasperJS') - .parse(process.argv); - -if (program.tests.length === 0) { - program.tests = fs.readdirSync(__dirname).filter(function(f) { return (/^test\.(\w|\.|-)+\.js$/).test(f); }); - program.tests = program.tests.map(function (f) { return path.resolve(__dirname, f); }); // add full paths in - console.log('using files %s', program.tests); -} - -var file_paths = []; - -var all_js = program.tests.reduce(function(a,e) { return a && e.slice(-3) == '.js'; }, true); - -var get_path = function (/* arguments */) { - if (program.relative) { - return path.join.apply(null, arguments); - } else { - var args = Array.prototype.slice.call(arguments); - args.unshift(__dirname, '..'); - return path.resolve.apply(null, args); - } -}; - -var get_path_cwd = function (/* arguments */) { - if (program.relative) { - var part_path = path.join.apply(null, arguments); - return path.relative(path.join(__dirname, '..'), path.resolve(process.cwd(), part_path)); - } else { - var args = Array.prototype.slice.call(arguments); - args.unshift(process.cwd()); - return path.resolve.apply(null, args); - } -}; - -if (all_js && !program.autoInject) { - var all_modules = {}; - - // uses the first instance of the string 'requires local modules: ' - program.tests.forEach(function (testname) { - var full_path = path.resolve(process.cwd(), testname); - var content = fs.readFileSync(full_path).toString(); - var ind = content.indexOf('requires local modules: '); - if (ind > -1) { - ind += 'requires local modules: '.length; - var eol = content.indexOf('\n', ind); - var modules = content.slice(ind, eol).split(/,\s*/); - modules.forEach(function (mod) { - all_modules[get_path('core/', mod) + '.js'] = 1; - }); - } - - var fakes_ind = content.indexOf('requires test modules: '); - if (fakes_ind > -1) { - fakes_ind += 'requires test modules: '.length; - var fakes_eol = content.indexOf('\n', fakes_ind); - var fakes_modules = content.slice(fakes_ind, fakes_eol).split(/,\s*/); - fakes_modules.forEach(function (mod) { - all_modules[get_path('tests/', mod) + '.js'] = 1; - }); - } - }); - - program.autoInject = Object.keys(all_modules); -} - -if (program.autoInject) { - var temp = require('temp'); - temp.track(); - - var template = { - header: "\n\n\n\n\n
", - script_tag: function(p) { return ""; }, - footer: "\n\n" - }; - - template.header += "\n" + template.script_tag(get_path('node_modules/chai/chai.js')); - template.header += "\n" + template.script_tag(get_path('node_modules/mocha/mocha.js')); - template.header += "\n" + template.script_tag(get_path('node_modules/sinon/pkg/sinon.js')); - template.header += "\n" + template.script_tag(get_path('node_modules/sinon-chai/lib/sinon-chai.js')); - template.header += "\n"; - - - template.header = program.autoInject.reduce(function(acc, sn) { - return acc + "\n" + template.script_tag(get_path_cwd(sn)); - }, template.header); - - file_paths = program.tests.map(function(jsn, ind) { - var templ = template.header; - templ += "\n"; - templ += template.script_tag(get_path_cwd(jsn)); - templ += template.footer; - - var tempfile = temp.openSync({ prefix: 'novnc-zombie-inject-', suffix: '-file_num-'+ind+'.html' }); - fs.writeSync(tempfile.fd, templ); - fs.closeSync(tempfile.fd); - return tempfile.path; - }); - -} -else { - file_paths = program.tests.map(function(fn) { - return path.resolve(process.cwd(), fn); - }); -} - -var use_ansi = false; -if (program.color) use_ansi = true; -else if (program.disableColor) use_ansi = false; -else if (process.stdout.isTTY) use_ansi = true; - -var cursor = ansi(process.stdout, { enabled: use_ansi }); - -if (program.outputHtml) { - file_paths.forEach(function(path, path_ind) { - fs.readFile(path, function(err, data) { - if (err) { - console.warn(error.stack); - return; - } - - if (use_ansi) { - cursor - .bold() - .write(program.tests[path_ind]) - .reset() - .write("\n") - .write(Array(program.tests[path_ind].length+1).join('=')) - .write("\n\n"); - } - - cursor - .write(data) - .write("\n\n"); - }); - }); -} - -if (program.generateHtml) { - var open_browser; - if (program.openInBrowser) { - open_browser = require('open'); - } - - file_paths.forEach(function(path, path_ind) { - cursor - .bold() - .write(program.tests[path_ind]) - .write(": ") - .reset() - .write(path) - .write("\n"); - - if (program.openInBrowser) { - open_browser(path); - } - }); - console.log(''); -} - -if (program.generateHtml) { - process.stdin.resume(); // pause until C-c - process.on('SIGINT', function() { - process.stdin.pause(); // exit - }); -} - -if (!program.outputHtml && !program.generateHtml) { - var failure_count = 0; - - var prov = require(path.resolve(__dirname, 'run_from_console.'+program.provider+'.js')); - - cursor - .write("Running tests ") - .bold() - .write(program.tests.join(', ')) - .reset() - .grey() - .write(' using provider '+prov.name) - .reset() - .write("\n"); - //console.log("Running tests %s using provider %s", program.tests.join(', '), prov.name); - - var provider = prov.provide_emitter(file_paths, program.debugger); - provider.on('test_ready', function(test_json) { - console.log(''); - - filename = program.tests[test_json.file_ind]; - - cursor.bold(); - console.log('Results for %s:', filename); - console.log(Array('Results for :'.length+filename.length+1).join('=')); - cursor.reset(); - - console.log(''); - - cursor - .write(''+test_json.num_tests+' tests run, ') - .green() - .write(''+test_json.num_passes+' passed'); - if (test_json.num_slow > 0) { - cursor - .reset() - .write(' ('); - cursor - .yellow() - .write(''+test_json.num_slow+' slow') - .reset() - .write(')'); - } - cursor - .reset() - .write(', '); - cursor - .red() - .write(''+test_json.num_fails+' failed'); - if (test_json.num_skipped > 0) { - cursor - .reset() - .write(', ') - .grey() - .write(''+test_json.num_skipped+' skipped'); - } - cursor - .reset() - .write(' -- duration: '+test_json.duration+"s\n"); - - console.log(''); - - if (test_json.num_fails > 0 || program.printAll) { - var extract_error_lines = function (err) { - // the split is to avoid a weird thing where in PhantomJS where we get a stack trace too - var err_lines = err.split('\n'); - if (err_lines.length == 1) { - return err_lines[0]; - } else { - var ind; - for (ind = 0; ind < err_lines.length; ind++) { - var at_ind = err_lines[ind].trim().indexOf('at '); - if (at_ind === 0) { - break; - } - } - - return err_lines.slice(0, ind).join('\n'); - } - }; - - var traverse_tree = function(indentation, node) { - if (node.type == 'suite') { - if (!node.has_subfailures && !program.printAll) return; - - if (indentation === 0) { - cursor.bold(); - console.log(node.name); - console.log(Array(node.name.length+1).join('-')); - cursor.reset(); - } - else { - cursor - .write(Array(indentation+3).join('#')) - .bold() - .write(' '+node.name+' ') - .reset() - .write(Array(indentation+3).join('#')) - .write("\n"); - } - - console.log(''); - - for (var i = 0; i < node.children.length; i++) { - traverse_tree(indentation+1, node.children[i]); - } - } - else { - if (!node.pass) { - cursor.magenta(); - console.log('- failed: '+node.text+test_json.replay); - cursor.red(); - console.log(' '+extract_error_lines(node.error)); - cursor.reset(); - console.log(''); - } - else if (program.printAll) { - if (node.skipped) { - cursor - .grey() - .write('- skipped: '+node.text); - } - else { - if (node.slow) cursor.yellow(); - else cursor.green(); - - cursor - .write('- pass: '+node.text) - .grey() - .write(' ('+node.duration+') '); - } - /*if (node.slow) cursor.yellow(); - else cursor.green();*/ - cursor - //.write(test_json.replay) - .reset() - .write("\n"); - console.log(''); - } - } - }; - - for (var i = 0; i < test_json.suites.length; i++) { - traverse_tree(0, test_json.suites[i]); - } - } - - if (test_json.num_fails === 0) { - cursor.fg.green(); - console.log('all tests passed :-)'); - cursor.reset(); - } - }); - - if (program.debug) { - provider.on('console', function(line) { - // log to stderr - console.error(line); - }); - } - - provider.on('error', function(line) { - // log to stderr - console.error('ERROR: ' + line); - }); - - /*gprom.finally(function(ph) { - ph.exit(); - // exit with a status code that actually gives information - if (program.exitWithFailureCount) process.exit(failure_count); - });*/ -} diff --git a/tests/run_from_console.zombie.js b/tests/run_from_console.zombie.js deleted file mode 100644 index 7280f75d..00000000 --- a/tests/run_from_console.zombie.js +++ /dev/null @@ -1,82 +0,0 @@ -var Browser = require('zombie'); -var path = require('path'); -var EventEmitter = require('events').EventEmitter; -var Q = require('q'); - -var provide_emitter = function(file_paths) { - var emitter = new EventEmitter(); - - file_paths.reduce(function(prom, file_path, path_ind) { - return prom.then(function(browser) { - browser.visit('file://'+file_path, function() { - if (browser.error) throw new Error(browser.errors); - - var res_json = {}; - res_json.file_ind = path_ind; - - res_json.num_tests = browser.querySelectorAll('li.test').length; - res_json.num_fails = browser.querySelectorAll('li.test.fail').length; - res_json.num_passes = browser.querySelectorAll('li.test.pass').length; - res_json.num_slow = browser.querySelectorAll('li.test.pass:not(.fast)').length; - res_json.num_skipped = browser.querySelectorAll('li.test.pending').length; - res_json.duration = browser.text('li.duration em'); - - var traverse_node = function(elem) { - var classList = elem.className.split(' '); - var res; - if (classList.indexOf('suite') > -1) { - res = { - type: 'suite', - name: elem.querySelector('h1').textContent, - has_subfailures: elem.querySelectorAll('li.test.fail').length > 0 - }; - - var child_elems = elem.querySelector('ul').children; - res.children = Array.prototype.map.call(child_elems, traverse_node); - return res; - } - else { - var h2_content = elem.querySelector('h2').childNodes; - res = { - type: 'test', - text: h2_content[0].textContent - }; - - if (classList.indexOf('pass') > -1) { - res.pass = true; - if (classList.indexOf('pending') > -1) { - res.slow = false; - res.skipped = true; - } - else { - res.slow = classList.indexOf('fast') < 0; - res.skipped = false; - res.duration = h2_content[1].textContent; - } - } - else { - res.error = elem.querySelector('pre.error').textContent; - } - - return res; - } - }; - - var top_suites = browser.querySelectorAll('#mocha-report > li.suite'); - res_json.suites = Array.prototype.map.call(top_suites, traverse_node); - res_json.replay = browser.querySelector('a.replay').textContent; - - emitter.emit('test_ready', res_json); - }); - - return new Browser(); - }); - }, Q(new Browser())); - - return emitter; -}; - -module.exports = { - provide_emitter: provide_emitter, - name: 'ZombieJS' -}; diff --git a/tests/test.base64.js b/tests/test.base64.js index b2646a0f..7aae7eff 100644 --- a/tests/test.base64.js +++ b/tests/test.base64.js @@ -1,7 +1,8 @@ -// requires local modules: base64 var assert = chai.assert; var expect = chai.expect; +import Base64 from '../core/base64.js'; + describe('Base64 Tools', function() { "use strict"; diff --git a/tests/test.display.js b/tests/test.display.js index e4e33489..4eb771ec 100644 --- a/tests/test.display.js +++ b/tests/test.display.js @@ -1,8 +1,15 @@ -// requires local modules: util, base64, display -// requires test modules: assertions /* jshint expr: true */ var expect = chai.expect; +import Base64 from '../core/base64.js'; +import Display from '../core/display.js'; +import { _forceCursorURIs, browserSupportsCursorURIs } from '../core/util/browsers.js'; + +import './assertions.js'; +import 'sinon'; +import sinonChai from '../node_modules/sinon-chai/lib/sinon-chai.js' +chai.use(sinonChai); + describe('Display/Canvas Helper', function () { var checked_data = [ 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, @@ -34,31 +41,23 @@ describe('Display/Canvas Helper', function () { } describe('checking for cursor uri support', function () { - beforeEach(function () { - this._old_browser_supports_cursor_uris = Util.browserSupportsCursorURIs; - }); - it('should disable cursor URIs if there is no support', function () { - Util.browserSupportsCursorURIs = function () { return false; }; + _forceCursorURIs(false); var display = new Display({ target: document.createElement('canvas'), prefer_js: true, viewport: false }); expect(display._cursor_uri).to.be.false; }); it('should enable cursor URIs if there is support', function () { - Util.browserSupportsCursorURIs = function () { return true; }; + _forceCursorURIs(true); var display = new Display({ target: document.createElement('canvas'), prefer_js: true, viewport: false }); expect(display._cursor_uri).to.be.true; }); it('respect the cursor_uri option if there is support', function () { - Util.browserSupportsCursorURIs = function () { return false; }; + _forceCursorURIs(false); var display = new Display({ target: document.createElement('canvas'), prefer_js: true, viewport: false, cursor_uri: false }); expect(display._cursor_uri).to.be.false; }); - - afterEach(function () { - Util.browserSupportsCursorURIs = this._old_browser_supports_cursor_uris; - }); }); describe('viewport handling', function () { diff --git a/tests/test.helper.js b/tests/test.helper.js index 4a1c65f3..12232d82 100644 --- a/tests/test.helper.js +++ b/tests/test.helper.js @@ -1,8 +1,9 @@ -// requires local modules: input/keysym, input/keysymdef, input/util - -var assert = chai.assert; +var assert = chai.assert; var expect = chai.expect; +import keysyms from '../core/input/keysymdef.js'; +import * as KeyboardUtil from "../core/input/util.js"; + describe('Helpers', function() { "use strict"; describe('keysymFromKeyCode', function() { diff --git a/tests/test.keyboard.js b/tests/test.keyboard.js index 0019be9a..b68c96d9 100644 --- a/tests/test.keyboard.js +++ b/tests/test.keyboard.js @@ -1,7 +1,9 @@ -// requires local modules: input/devices, input/util, input/keysymdef, input/keysym var assert = chai.assert; var expect = chai.expect; +import keysyms from '../core/input/keysymdef.js'; +import * as KeyboardUtil from '../core/input/util.js'; + /* jshint newcap: false, expr: true */ describe('Key Event Pipeline Stages', function() { "use strict"; diff --git a/tests/test.rfb.js b/tests/test.rfb.js index f903d052..dd658e04 100644 --- a/tests/test.rfb.js +++ b/tests/test.rfb.js @@ -1,9 +1,16 @@ -// requires local modules: util, websock, rfb, input/util, input/keysym, input/keysymdef, input/devices, inflator, des, display -// requires test modules: fake.websocket, assertions /* jshint expr: true */ var assert = chai.assert; var expect = chai.expect; +import RFB from '../core/rfb.js'; +import Websock from '../core/websock.js'; + +import FakeWebSocket from './fake.websocket.js'; +import './assertions'; +import 'sinon'; +import sinonChai from '../node_modules/sinon-chai/lib/sinon-chai.js' +chai.use(sinonChai); + function make_rfb (extra_opts) { if (!extra_opts) { extra_opts = {}; diff --git a/tests/test.util.js b/tests/test.util.js index e6a79bb6..8bd93765 100644 --- a/tests/test.util.js +++ b/tests/test.util.js @@ -1,9 +1,15 @@ -// requires local modules: util /* jshint expr: true */ var assert = chai.assert; var expect = chai.expect; +import * as Log from '../core/util/logging.js'; +import l10nGet, { l10n } from '../core/util/localization.js'; + +import 'sinon'; +import sinonChai from '../node_modules/sinon-chai/lib/sinon-chai.js' +chai.use(sinonChai); + describe('Utils', function() { "use strict"; @@ -25,34 +31,34 @@ describe('Utils', function() { }); it('should use noop for levels lower than the min level', function () { - Util.init_logging('warn'); - Util.Debug('hi'); - Util.Info('hello'); + Log.init_logging('warn'); + Log.Debug('hi'); + Log.Info('hello'); expect(console.log).to.not.have.been.called; }); it('should use console.debug for Debug', function () { - Util.init_logging('debug'); - Util.Debug('dbg'); + Log.init_logging('debug'); + Log.Debug('dbg'); expect(console.debug).to.have.been.calledWith('dbg'); }); it('should use console.info for Info', function () { - Util.init_logging('debug'); - Util.Info('inf'); + Log.init_logging('debug'); + Log.Info('inf'); expect(console.info).to.have.been.calledWith('inf'); }); it('should use console.warn for Warn', function () { - Util.init_logging('warn'); - Util.Warn('wrn'); + Log.init_logging('warn'); + Log.Warn('wrn'); expect(console.warn).to.have.been.called; expect(console.warn).to.have.been.calledWith('wrn'); }); it('should use console.error for Error', function () { - Util.init_logging('error'); - Util.Error('err'); + Log.init_logging('error'); + Log.Error('err'); expect(console.error).to.have.been.called; expect(console.error).to.have.been.calledWith('err'); }); @@ -85,42 +91,42 @@ describe('Utils', function() { }); it('should use English by default', function() { - expect(Util.Localisation.language).to.equal('en'); + expect(l10n.language).to.equal('en'); }); it('should use English if no user language matches', function() { window.navigator.languages = ["nl", "de"]; - Util.Localisation.setup(["es", "fr"]); - expect(Util.Localisation.language).to.equal('en'); + l10n.setup(["es", "fr"]); + expect(l10n.language).to.equal('en'); }); it('should use the most preferred user language', function() { window.navigator.languages = ["nl", "de", "fr"]; - Util.Localisation.setup(["es", "fr", "de"]); - expect(Util.Localisation.language).to.equal('de'); + l10n.setup(["es", "fr", "de"]); + expect(l10n.language).to.equal('de'); }); it('should prefer sub-languages languages', function() { window.navigator.languages = ["pt-BR"]; - Util.Localisation.setup(["pt", "pt-BR"]); - expect(Util.Localisation.language).to.equal('pt-BR'); + l10n.setup(["pt", "pt-BR"]); + expect(l10n.language).to.equal('pt-BR'); }); it('should fall back to language "parents"', function() { window.navigator.languages = ["pt-BR"]; - Util.Localisation.setup(["fr", "pt", "de"]); - expect(Util.Localisation.language).to.equal('pt'); + l10n.setup(["fr", "pt", "de"]); + expect(l10n.language).to.equal('pt'); }); it('should not use specific language when user asks for a generic language', function() { window.navigator.languages = ["pt", "de"]; - Util.Localisation.setup(["fr", "pt-BR", "de"]); - expect(Util.Localisation.language).to.equal('de'); + l10n.setup(["fr", "pt-BR", "de"]); + expect(l10n.language).to.equal('de'); }); it('should handle underscore as a separator', function() { window.navigator.languages = ["pt-BR"]; - Util.Localisation.setup(["pt_BR"]); - expect(Util.Localisation.language).to.equal('pt_BR'); + l10n.setup(["pt_BR"]); + expect(l10n.language).to.equal('pt_BR'); }); it('should handle difference in case', function() { window.navigator.languages = ["pt-br"]; - Util.Localisation.setup(["pt-BR"]); - expect(Util.Localisation.language).to.equal('pt-BR'); + l10n.setup(["pt-BR"]); + expect(l10n.language).to.equal('pt-BR'); }); }); diff --git a/tests/test.websock.js b/tests/test.websock.js index 023c7726..b4835901 100644 --- a/tests/test.websock.js +++ b/tests/test.websock.js @@ -1,9 +1,15 @@ -// requires local modules: websock, util -// requires test modules: fake.websocket, assertions /* jshint expr: true */ var assert = chai.assert; var expect = chai.expect; +import Websock from '../core/websock.js'; +import FakeWebSocket from './fake.websocket.js'; + +import './assertions'; +import 'sinon'; +import sinonChai from '../node_modules/sinon-chai/lib/sinon-chai.js' +chai.use(sinonChai); + describe('Websock', function() { "use strict"; diff --git a/tests/vnc_playback.html b/tests/vnc_playback.html index 65b735e7..66f40576 100644 --- a/tests/vnc_playback.html +++ b/tests/vnc_playback.html @@ -2,6 +2,8 @@ VNC Playback + + @@ -9,8 +11,7 @@ Perftest:  Realtime:   -   +  

@@ -37,98 +38,5 @@ src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'> --> - - - - - + \n' + contents.slice(end_ind); + contents = contents.slice(0, start_ind) + `${new_script}\n` + contents.slice(end_ind); + console.log(`Writing ${out_html_path}`); fs.writeFile(out_html_path, contents, function (err) { if (err) { throw err; } - console.log("Wrote " + out_html_path); }); }); -}; - -var make_lib_files = function (use_require) { - // make sure the output directory exists - fse.ensureDir(lib_dir_base); - - var through = require('through2'); - - var deps = {}; - var rfb_file = path.join(core_path, 'rfb.js'); - var b = make_browserify(rfb_file, {}); - b.on('transform', function (tr, file) { - if (tr._is_make_module) { - var new_path = path.join(lib_dir_base, path.relative(core_path, file)); - fse.ensureDir(path.dirname(new_path)); - console.log("Writing " + new_path) - var fileStream = fs.createWriteStream(new_path); - - if (use_require) { - var babelificate = babelify(file, - { plugins: ["add-module-exports", "transform-es2015-modules-commonjs"] }); - tr.pipe(babelificate); - tr = babelificate; - } - tr.pipe(fileStream); - } - }); - - b.bundle(); -}; - -if (program.browserify) { - make_full_app(); -} else { - make_lib_files(program.asRequire); } + +var make_lib_files = function (import_format, source_maps, with_app_dir) { + if (!import_format) { + throw new Error("you must specify an import format to generate compiled noVNC libraries"); + } else if (!SUPPORTED_FORMATS.has(import_format)) { + throw new Error(`unsupported output format "${import_format}" for import/export -- only ${Array.from(SUPPORTED_FORMATS)} are supported`); + } + + // NB: we need to make a copy of babel_opts, since babel sets some defaults on it + const babel_opts = () => ({ + plugins: [`transform-es2015-modules-${import_format}`], + ast: false, + sourceMaps: source_maps, + }); + const babel = require('babel-core'); + + var in_path; + if (with_app_dir) { + var out_path_base = paths.out_dir_base; + in_path = paths.main; + } else { + var out_path_base = paths.lib_dir_base; + } + + fse.ensureDirSync(out_path_base); + + const helpers = require('./use_require_helpers'); + const helper = helpers[import_format]; + + var handleDir = (js_only, in_path_base, filename) => { + if (no_copy_files.has(filename)) return; + + const out_path = path.join(out_path_base, path.relative(in_path_base, filename)); + if(path.extname(filename) !== '.js') { + if (!js_only) { + console.log(`Writing ${out_path}`); + fse.copy(filename, out_path, (err) => { if (err) throw err; }); + } + return; // skip non-javascript files + } + + fse.ensureDir(path.dirname(out_path), () => { + if (no_transform_files.has(filename)) { + console.log(`Writing ${out_path}`); + fse.copy(filename, out_path, (err) => { if (err) throw err; }); + return; + } + + const opts = babel_opts(); + if (helper && helpers.optionsOverride) { + helper.optionsOverride(opts); + } + + babel.transformFile(filename, babel_opts(), (err, res) => { + console.log(`Writing ${out_path}`); + if (err) throw err; + var {code, map, ast} = res; + if (source_maps === true) { + // append URL for external source map + code += `\n//# sourceMappingURL=${path.basename(out_path)}.map\n`; + } + fs.writeFile(out_path, code, (err) => { if (err) throw err; }); + if (source_maps === true || source_maps === 'both') { + console.log(` and ${out_path}.map`); + fs.writeFile(`${out_path}.map`, JSON.stringify(map), (err) => { if (err) throw err; }); + } + }); + }); + }; + + if (with_app_dir && helper && helper.noCopyOverride) { + helper.noCopyOverride(paths, no_copy_files); + } + + walkDir(paths.core, handleDir.bind(null, true, in_path || paths.core), (filename, stats) => !no_copy_files.has(filename)); + walkDir(paths.vendor, handleDir.bind(null, true, in_path || paths.main), (filename, stats) => !no_copy_files.has(filename)); + + if (with_app_dir) { + walkDir(paths.app, handleDir.bind(null, false, in_path || paths.app), (filename, stats) => !no_copy_files.has(filename)); + + const out_app_path = path.join(out_path_base, 'app.js'); + if (helper && helper.appWriter) { + console.log(`Writing ${out_app_path}`); + let out_script = helper.appWriter(out_path_base, out_app_path); + transform_html(out_script); + } else { + console.error(`Unable to generate app for the ${import_format} format!`); + } + } +}; + +make_lib_files(program.as, program.withSourceMaps, program.withApp); diff --git a/utils/use_require_helpers.js b/utils/use_require_helpers.js new file mode 100644 index 00000000..990fb4df --- /dev/null +++ b/utils/use_require_helpers.js @@ -0,0 +1,46 @@ +// writes helpers require for vnc.html (they should output app.js) +var fs = require('fs'); +var fse = require('fs-extra'); +var path = require('path'); + +module.exports = { + 'amd': { + appWriter: (base_out_path, out_path) => { + // setup for requirejs + fs.writeFile(out_path, 'requirejs(["app/ui"], function (ui) {});', (err) => { if (err) throw err; }); + console.log(`Please place RequireJS in ${path.join(base_out_path, 'require.js')}`); + return ``; + }, + noCopyOverride: () => {}, + }, + 'commonjs': { + optionsOverride: (opts) => { + // CommonJS supports properly shifting the default export to work as normal + opts.plugins.unshift("add-module-exports"); + }, + appWriter: (base_out_path, out_path) => { + var browserify = require('browserify'); + var b = browserify(path.join(base_out_path, 'app/ui.js'), {}); + b.bundle().pipe(fs.createWriteStream(out_path)); + return ``; + }, + noCopyOverride: () => {}, + }, + 'systemjs': { + appWriter: (base_out_path, out_path) => { + fs.writeFile(out_path, 'SystemJS.import("./app/ui.js");', (err) => { if (err) throw err; }); + console.log(`Please place SystemJS in ${path.join(base_out_path, 'system-production.js')}`); + return ` +\n`; + }, + noCopyOverride: (paths, no_copy_files) => { + no_copy_files.delete(path.join(paths.vendor, 'promise.js')); + }, + }, + 'umd': { + optionsOverride: (opts) => { + // umd supports properly shifting the default export to work as normal + opts.plugins.unshift("add-module-exports"); + }, + }, +} diff --git a/vendor/browser-es-module-loader/.npmignore b/vendor/browser-es-module-loader/.npmignore new file mode 100644 index 00000000..e69de29b diff --git a/vendor/browser-es-module-loader/README.md b/vendor/browser-es-module-loader/README.md new file mode 100644 index 00000000..c26867f9 --- /dev/null +++ b/vendor/browser-es-module-loader/README.md @@ -0,0 +1,15 @@ +Custom Browser ES Module Loader +=============================== + +This is a module loader using babel and the ES Module Loader polyfill. +It's based heavily on +https://github.com/ModuleLoader/browser-es-module-loader, but uses +WebWorkers to compile the modules in the background. + +To generate, run `rollup -c` in this directory, and then run `browserify +src/babel-worker.js > dist/babel-worker.js`. + +LICENSE +------- + +MIT diff --git a/vendor/browser-es-module-loader/dist/babel-worker.js b/vendor/browser-es-module-loader/dist/babel-worker.js new file mode 100644 index 00000000..6c40dccf --- /dev/null +++ b/vendor/browser-es-module-loader/dist/babel-worker.js @@ -0,0 +1,44024 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<]/g; +}; + +},{}],2:[function(require,module,exports){ +'use strict'; + +function assembleStyles () { + var styles = { + modifiers: { + reset: [0, 0], + bold: [1, 22], // 21 isn't widely supported and 22 does the same thing + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29] + }, + colors: { + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], + gray: [90, 39] + }, + bgColors: { + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49] + } + }; + + // fix humans + styles.colors.grey = styles.colors.gray; + + Object.keys(styles).forEach(function (groupName) { + var group = styles[groupName]; + + Object.keys(group).forEach(function (styleName) { + var style = group[styleName]; + + styles[styleName] = group[styleName] = { + open: '\u001b[' + style[0] + 'm', + close: '\u001b[' + style[1] + 'm' + }; + }); + + Object.defineProperty(styles, groupName, { + value: group, + enumerable: false + }); + }); + + return styles; +} + +Object.defineProperty(module, 'exports', { + enumerable: true, + get: assembleStyles +}); + +},{}],3:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +exports.default = function (rawLines, lineNumber, colNumber) { + var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + colNumber = Math.max(colNumber, 0); + + var highlighted = opts.highlightCode && _chalk2.default.supportsColor || opts.forceColor; + var chalk = _chalk2.default; + if (opts.forceColor) { + chalk = new _chalk2.default.constructor({ enabled: true }); + } + var maybeHighlight = function maybeHighlight(chalkFn, string) { + return highlighted ? chalkFn(string) : string; + }; + var defs = getDefs(chalk); + if (highlighted) rawLines = highlight(defs, rawLines); + + var linesAbove = opts.linesAbove || 2; + var linesBelow = opts.linesBelow || 3; + + var lines = rawLines.split(NEWLINE); + var start = Math.max(lineNumber - (linesAbove + 1), 0); + var end = Math.min(lines.length, lineNumber + linesBelow); + + if (!lineNumber && !colNumber) { + start = 0; + end = lines.length; + } + + var numberMaxWidth = String(end).length; + + var frame = lines.slice(start, end).map(function (line, index) { + var number = start + 1 + index; + var paddedNumber = (" " + number).slice(-numberMaxWidth); + var gutter = " " + paddedNumber + " | "; + if (number === lineNumber) { + var markerLine = ""; + if (colNumber) { + var markerSpacing = line.slice(0, colNumber - 1).replace(/[^\t]/g, " "); + markerLine = ["\n ", maybeHighlight(defs.gutter, gutter.replace(/\d/g, " ")), markerSpacing, maybeHighlight(defs.marker, "^")].join(""); + } + return [maybeHighlight(defs.marker, ">"), maybeHighlight(defs.gutter, gutter), line, markerLine].join(""); + } else { + return " " + maybeHighlight(defs.gutter, gutter) + line; + } + }).join("\n"); + + if (highlighted) { + return chalk.reset(frame); + } else { + return frame; + } +}; + +var _jsTokens = require("js-tokens"); + +var _jsTokens2 = _interopRequireDefault(_jsTokens); + +var _esutils = require("esutils"); + +var _esutils2 = _interopRequireDefault(_esutils); + +var _chalk = require("chalk"); + +var _chalk2 = _interopRequireDefault(_chalk); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getDefs(chalk) { + return { + keyword: chalk.cyan, + capitalized: chalk.yellow, + jsx_tag: chalk.yellow, + punctuator: chalk.yellow, + + number: chalk.magenta, + string: chalk.green, + regex: chalk.magenta, + comment: chalk.grey, + invalid: chalk.white.bgRed.bold, + gutter: chalk.grey, + marker: chalk.red.bold + }; +} + +var NEWLINE = /\r\n|[\n\r\u2028\u2029]/; + +var JSX_TAG = /^[a-z][\w-]*$/i; + +var BRACKET = /^[()\[\]{}]$/; + +function getTokenType(match) { + var _match$slice = match.slice(-2), + offset = _match$slice[0], + text = _match$slice[1]; + + var token = (0, _jsTokens.matchToToken)(match); + + if (token.type === "name") { + if (_esutils2.default.keyword.isReservedWordES6(token.value)) { + return "keyword"; + } + + if (JSX_TAG.test(token.value) && (text[offset - 1] === "<" || text.substr(offset - 2, 2) == " 1 && arguments[1] !== undefined ? arguments[1] : {}; + + opts.filename = filename; + return transform(_fs2.default.readFileSync(filename, "utf8"), opts); +} +},{"../../package":31,"../helpers/resolve-plugin":11,"../helpers/resolve-preset":12,"../tools/build-external-helpers":15,"../transformation/file":16,"../transformation/file/options/config":20,"../transformation/file/options/option-manager":22,"../transformation/pipeline":27,"../util":30,"babel-messages":53,"babel-template":75,"babel-traverse":79,"babel-types":112,"fs":120}],6:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.default = getPossiblePluginNames; +function getPossiblePluginNames(pluginName) { + return ["babel-plugin-" + pluginName, pluginName]; +} +module.exports = exports["default"]; +},{}],7:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.default = getPossiblePresetNames; +function getPossiblePresetNames(presetName) { + var possibleNames = ["babel-preset-" + presetName, presetName]; + + var matches = presetName.match(/^(@[^/]+)\/(.+)$/); + if (matches) { + var orgName = matches[1], + presetPath = matches[2]; + + possibleNames.push(orgName + "/babel-preset-" + presetPath); + } + + return possibleNames; +} +module.exports = exports["default"]; +},{}],8:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.default = function (dest, src) { + if (!dest || !src) return; + + return (0, _mergeWith2.default)(dest, src, function (a, b) { + if (b && Array.isArray(a)) { + var newArray = b.slice(0); + + for (var _iterator = a, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var item = _ref; + + if (newArray.indexOf(item) < 0) { + newArray.push(item); + } + } + + return newArray; + } + }); +}; + +var _mergeWith = require("lodash/mergeWith"); + +var _mergeWith2 = _interopRequireDefault(_mergeWith); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +module.exports = exports["default"]; +},{"babel-runtime/core-js/get-iterator":56,"lodash/mergeWith":451}],9:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +exports.default = function (ast, comments, tokens) { + if (ast) { + if (ast.type === "Program") { + return t.file(ast, comments || [], tokens || []); + } else if (ast.type === "File") { + return ast; + } + } + + throw new Error("Not a valid ast?"); +}; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +module.exports = exports["default"]; +},{"babel-types":112}],10:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.default = resolveFromPossibleNames; + +var _resolve = require("./resolve"); + +var _resolve2 = _interopRequireDefault(_resolve); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function resolveFromPossibleNames(possibleNames, dirname) { + return possibleNames.reduce(function (accum, curr) { + return accum || (0, _resolve2.default)(curr, dirname); + }, null); +} +module.exports = exports["default"]; +},{"./resolve":13}],11:[function(require,module,exports){ +(function (process){ +"use strict"; + +exports.__esModule = true; +exports.default = resolvePlugin; + +var _resolveFromPossibleNames = require("./resolve-from-possible-names"); + +var _resolveFromPossibleNames2 = _interopRequireDefault(_resolveFromPossibleNames); + +var _getPossiblePluginNames = require("./get-possible-plugin-names"); + +var _getPossiblePluginNames2 = _interopRequireDefault(_getPossiblePluginNames); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function resolvePlugin(pluginName) { + var dirname = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : process.cwd(); + + return (0, _resolveFromPossibleNames2.default)((0, _getPossiblePluginNames2.default)(pluginName), dirname); +} +module.exports = exports["default"]; +}).call(this,require('_process')) +},{"./get-possible-plugin-names":6,"./resolve-from-possible-names":10,"_process":471}],12:[function(require,module,exports){ +(function (process){ +"use strict"; + +exports.__esModule = true; +exports.default = resolvePreset; + +var _resolveFromPossibleNames = require("./resolve-from-possible-names"); + +var _resolveFromPossibleNames2 = _interopRequireDefault(_resolveFromPossibleNames); + +var _getPossiblePresetNames = require("./get-possible-preset-names"); + +var _getPossiblePresetNames2 = _interopRequireDefault(_getPossiblePresetNames); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function resolvePreset(presetName) { + var dirname = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : process.cwd(); + + return (0, _resolveFromPossibleNames2.default)((0, _getPossiblePresetNames2.default)(presetName), dirname); +} +module.exports = exports["default"]; +}).call(this,require('_process')) +},{"./get-possible-preset-names":7,"./resolve-from-possible-names":10,"_process":471}],13:[function(require,module,exports){ +(function (process){ +"use strict"; + +exports.__esModule = true; + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +exports.default = function (loc) { + var relative = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : process.cwd(); + + if ((typeof _module2.default === "undefined" ? "undefined" : (0, _typeof3.default)(_module2.default)) === "object") return null; + + var relativeMod = relativeModules[relative]; + + if (!relativeMod) { + relativeMod = new _module2.default(); + + var filename = _path2.default.join(relative, ".babelrc"); + relativeMod.id = filename; + relativeMod.filename = filename; + + relativeMod.paths = _module2.default._nodeModulePaths(relative); + relativeModules[relative] = relativeMod; + } + + try { + return _module2.default._resolveFilename(loc, relativeMod); + } catch (err) { + return null; + } +}; + +var _module = require("module"); + +var _module2 = _interopRequireDefault(_module); + +var _path = require("path"); + +var _path2 = _interopRequireDefault(_path); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var relativeModules = {}; + +module.exports = exports["default"]; +}).call(this,require('_process')) +},{"_process":471,"babel-runtime/helpers/typeof":74,"module":120,"path":469}],14:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _map = require("babel-runtime/core-js/map"); + +var _map2 = _interopRequireDefault(_map); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _possibleConstructorReturn2 = require("babel-runtime/helpers/possibleConstructorReturn"); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require("babel-runtime/helpers/inherits"); + +var _inherits3 = _interopRequireDefault(_inherits2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var Store = function (_Map) { + (0, _inherits3.default)(Store, _Map); + + function Store() { + (0, _classCallCheck3.default)(this, Store); + + var _this = (0, _possibleConstructorReturn3.default)(this, _Map.call(this)); + + _this.dynamicData = {}; + return _this; + } + + Store.prototype.setDynamic = function setDynamic(key, fn) { + this.dynamicData[key] = fn; + }; + + Store.prototype.get = function get(key) { + if (this.has(key)) { + return _Map.prototype.get.call(this, key); + } else { + if (Object.prototype.hasOwnProperty.call(this.dynamicData, key)) { + var val = this.dynamicData[key](); + this.set(key, val); + return val; + } + } + }; + + return Store; +}(_map2.default); + +exports.default = Store; +module.exports = exports["default"]; +},{"babel-runtime/core-js/map":58,"babel-runtime/helpers/classCallCheck":70,"babel-runtime/helpers/inherits":71,"babel-runtime/helpers/possibleConstructorReturn":73}],15:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +exports.default = function (whitelist) { + var outputType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "global"; + + var namespace = t.identifier("babelHelpers"); + + var builder = function builder(body) { + return buildHelpers(body, namespace, whitelist); + }; + + var tree = void 0; + + var build = { + global: buildGlobal, + umd: buildUmd, + var: buildVar + }[outputType]; + + if (build) { + tree = build(namespace, builder); + } else { + throw new Error(messages.get("unsupportedOutputType", outputType)); + } + + return (0, _babelGenerator2.default)(tree).code; +}; + +var _babelHelpers = require("babel-helpers"); + +var helpers = _interopRequireWildcard(_babelHelpers); + +var _babelGenerator = require("babel-generator"); + +var _babelGenerator2 = _interopRequireDefault(_babelGenerator); + +var _babelMessages = require("babel-messages"); + +var messages = _interopRequireWildcard(_babelMessages); + +var _babelTemplate = require("babel-template"); + +var _babelTemplate2 = _interopRequireDefault(_babelTemplate); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var buildUmdWrapper = (0, _babelTemplate2.default)("\n (function (root, factory) {\n if (typeof define === \"function\" && define.amd) {\n define(AMD_ARGUMENTS, factory);\n } else if (typeof exports === \"object\") {\n factory(COMMON_ARGUMENTS);\n } else {\n factory(BROWSER_ARGUMENTS);\n }\n })(UMD_ROOT, function (FACTORY_PARAMETERS) {\n FACTORY_BODY\n });\n"); + +function buildGlobal(namespace, builder) { + var body = []; + var container = t.functionExpression(null, [t.identifier("global")], t.blockStatement(body)); + var tree = t.program([t.expressionStatement(t.callExpression(container, [helpers.get("selfGlobal")]))]); + + body.push(t.variableDeclaration("var", [t.variableDeclarator(namespace, t.assignmentExpression("=", t.memberExpression(t.identifier("global"), namespace), t.objectExpression([])))])); + + builder(body); + + return tree; +} + +function buildUmd(namespace, builder) { + var body = []; + body.push(t.variableDeclaration("var", [t.variableDeclarator(namespace, t.identifier("global"))])); + + builder(body); + + return t.program([buildUmdWrapper({ + FACTORY_PARAMETERS: t.identifier("global"), + BROWSER_ARGUMENTS: t.assignmentExpression("=", t.memberExpression(t.identifier("root"), namespace), t.objectExpression([])), + COMMON_ARGUMENTS: t.identifier("exports"), + AMD_ARGUMENTS: t.arrayExpression([t.stringLiteral("exports")]), + FACTORY_BODY: body, + UMD_ROOT: t.identifier("this") + })]); +} + +function buildVar(namespace, builder) { + var body = []; + body.push(t.variableDeclaration("var", [t.variableDeclarator(namespace, t.objectExpression([]))])); + builder(body); + body.push(t.expressionStatement(namespace)); + return t.program(body); +} + +function buildHelpers(body, namespace, whitelist) { + helpers.list.forEach(function (name) { + if (whitelist && whitelist.indexOf(name) < 0) return; + + var key = t.identifier(name); + body.push(t.expressionStatement(t.assignmentExpression("=", t.memberExpression(namespace, key), helpers.get(name)))); + }); +} +module.exports = exports["default"]; +},{"babel-generator":43,"babel-helpers":52,"babel-messages":53,"babel-template":75,"babel-types":112}],16:[function(require,module,exports){ +(function (process){ +"use strict"; + +exports.__esModule = true; +exports.File = undefined; + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _create = require("babel-runtime/core-js/object/create"); + +var _create2 = _interopRequireDefault(_create); + +var _assign = require("babel-runtime/core-js/object/assign"); + +var _assign2 = _interopRequireDefault(_assign); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _possibleConstructorReturn2 = require("babel-runtime/helpers/possibleConstructorReturn"); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require("babel-runtime/helpers/inherits"); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _babelHelpers = require("babel-helpers"); + +var _babelHelpers2 = _interopRequireDefault(_babelHelpers); + +var _metadata = require("./metadata"); + +var metadataVisitor = _interopRequireWildcard(_metadata); + +var _convertSourceMap = require("convert-source-map"); + +var _convertSourceMap2 = _interopRequireDefault(_convertSourceMap); + +var _optionManager = require("./options/option-manager"); + +var _optionManager2 = _interopRequireDefault(_optionManager); + +var _pluginPass = require("../plugin-pass"); + +var _pluginPass2 = _interopRequireDefault(_pluginPass); + +var _babelTraverse = require("babel-traverse"); + +var _babelTraverse2 = _interopRequireDefault(_babelTraverse); + +var _sourceMap = require("source-map"); + +var _sourceMap2 = _interopRequireDefault(_sourceMap); + +var _babelGenerator = require("babel-generator"); + +var _babelGenerator2 = _interopRequireDefault(_babelGenerator); + +var _babelCodeFrame = require("babel-code-frame"); + +var _babelCodeFrame2 = _interopRequireDefault(_babelCodeFrame); + +var _defaults = require("lodash/defaults"); + +var _defaults2 = _interopRequireDefault(_defaults); + +var _logger = require("./logger"); + +var _logger2 = _interopRequireDefault(_logger); + +var _store = require("../../store"); + +var _store2 = _interopRequireDefault(_store); + +var _babylon = require("babylon"); + +var _util = require("../../util"); + +var util = _interopRequireWildcard(_util); + +var _path = require("path"); + +var _path2 = _interopRequireDefault(_path); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +var _resolve = require("../../helpers/resolve"); + +var _resolve2 = _interopRequireDefault(_resolve); + +var _blockHoist = require("../internal-plugins/block-hoist"); + +var _blockHoist2 = _interopRequireDefault(_blockHoist); + +var _shadowFunctions = require("../internal-plugins/shadow-functions"); + +var _shadowFunctions2 = _interopRequireDefault(_shadowFunctions); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var shebangRegex = /^#!.*/; + +var INTERNAL_PLUGINS = [[_blockHoist2.default], [_shadowFunctions2.default]]; + +var errorVisitor = { + enter: function enter(path, state) { + var loc = path.node.loc; + if (loc) { + state.loc = loc; + path.stop(); + } + } +}; + +var File = function (_Store) { + (0, _inherits3.default)(File, _Store); + + function File() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var pipeline = arguments[1]; + (0, _classCallCheck3.default)(this, File); + + var _this = (0, _possibleConstructorReturn3.default)(this, _Store.call(this)); + + _this.pipeline = pipeline; + + _this.log = new _logger2.default(_this, opts.filename || "unknown"); + _this.opts = _this.initOptions(opts); + + _this.parserOpts = { + sourceType: _this.opts.sourceType, + sourceFileName: _this.opts.filename, + plugins: [] + }; + + _this.pluginVisitors = []; + _this.pluginPasses = []; + + _this.buildPluginsForOptions(_this.opts); + + if (_this.opts.passPerPreset) { + _this.perPresetOpts = []; + _this.opts.presets.forEach(function (presetOpts) { + var perPresetOpts = (0, _assign2.default)((0, _create2.default)(_this.opts), presetOpts); + _this.perPresetOpts.push(perPresetOpts); + _this.buildPluginsForOptions(perPresetOpts); + }); + } + + _this.metadata = { + usedHelpers: [], + marked: [], + modules: { + imports: [], + exports: { + exported: [], + specifiers: [] + } + } + }; + + _this.dynamicImportTypes = {}; + _this.dynamicImportIds = {}; + _this.dynamicImports = []; + _this.declarations = {}; + _this.usedHelpers = {}; + + _this.path = null; + _this.ast = {}; + + _this.code = ""; + _this.shebang = ""; + + _this.hub = new _babelTraverse.Hub(_this); + return _this; + } + + File.prototype.getMetadata = function getMetadata() { + var has = false; + for (var _iterator = this.ast.program.body, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var node = _ref; + + if (t.isModuleDeclaration(node)) { + has = true; + break; + } + } + if (has) { + this.path.traverse(metadataVisitor, this); + } + }; + + File.prototype.initOptions = function initOptions(opts) { + opts = new _optionManager2.default(this.log, this.pipeline).init(opts); + + if (opts.inputSourceMap) { + opts.sourceMaps = true; + } + + if (opts.moduleId) { + opts.moduleIds = true; + } + + opts.basename = _path2.default.basename(opts.filename, _path2.default.extname(opts.filename)); + + opts.ignore = util.arrayify(opts.ignore, util.regexify); + + if (opts.only) opts.only = util.arrayify(opts.only, util.regexify); + + (0, _defaults2.default)(opts, { + moduleRoot: opts.sourceRoot + }); + + (0, _defaults2.default)(opts, { + sourceRoot: opts.moduleRoot + }); + + (0, _defaults2.default)(opts, { + filenameRelative: opts.filename + }); + + var basenameRelative = _path2.default.basename(opts.filenameRelative); + + (0, _defaults2.default)(opts, { + sourceFileName: basenameRelative, + sourceMapTarget: basenameRelative + }); + + return opts; + }; + + File.prototype.buildPluginsForOptions = function buildPluginsForOptions(opts) { + if (!Array.isArray(opts.plugins)) { + return; + } + + var plugins = opts.plugins.concat(INTERNAL_PLUGINS); + var currentPluginVisitors = []; + var currentPluginPasses = []; + + for (var _iterator2 = plugins, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var ref = _ref2; + var plugin = ref[0], + pluginOpts = ref[1]; + + + currentPluginVisitors.push(plugin.visitor); + currentPluginPasses.push(new _pluginPass2.default(this, plugin, pluginOpts)); + + if (plugin.manipulateOptions) { + plugin.manipulateOptions(opts, this.parserOpts, this); + } + } + + this.pluginVisitors.push(currentPluginVisitors); + this.pluginPasses.push(currentPluginPasses); + }; + + File.prototype.getModuleName = function getModuleName() { + var opts = this.opts; + if (!opts.moduleIds) { + return null; + } + + if (opts.moduleId != null && !opts.getModuleId) { + return opts.moduleId; + } + + var filenameRelative = opts.filenameRelative; + var moduleName = ""; + + if (opts.moduleRoot != null) { + moduleName = opts.moduleRoot + "/"; + } + + if (!opts.filenameRelative) { + return moduleName + opts.filename.replace(/^\//, ""); + } + + if (opts.sourceRoot != null) { + var sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "\/?"); + filenameRelative = filenameRelative.replace(sourceRootRegEx, ""); + } + + filenameRelative = filenameRelative.replace(/\.(\w*?)$/, ""); + + moduleName += filenameRelative; + + moduleName = moduleName.replace(/\\/g, "/"); + + if (opts.getModuleId) { + return opts.getModuleId(moduleName) || moduleName; + } else { + return moduleName; + } + }; + + File.prototype.resolveModuleSource = function resolveModuleSource(source) { + var resolveModuleSource = this.opts.resolveModuleSource; + if (resolveModuleSource) source = resolveModuleSource(source, this.opts.filename); + return source; + }; + + File.prototype.addImport = function addImport(source, imported) { + var name = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : imported; + + var alias = source + ":" + imported; + var id = this.dynamicImportIds[alias]; + + if (!id) { + source = this.resolveModuleSource(source); + id = this.dynamicImportIds[alias] = this.scope.generateUidIdentifier(name); + + var specifiers = []; + + if (imported === "*") { + specifiers.push(t.importNamespaceSpecifier(id)); + } else if (imported === "default") { + specifiers.push(t.importDefaultSpecifier(id)); + } else { + specifiers.push(t.importSpecifier(id, t.identifier(imported))); + } + + var declar = t.importDeclaration(specifiers, t.stringLiteral(source)); + declar._blockHoist = 3; + + this.path.unshiftContainer("body", declar); + } + + return id; + }; + + File.prototype.addHelper = function addHelper(name) { + var declar = this.declarations[name]; + if (declar) return declar; + + if (!this.usedHelpers[name]) { + this.metadata.usedHelpers.push(name); + this.usedHelpers[name] = true; + } + + var generator = this.get("helperGenerator"); + var runtime = this.get("helpersNamespace"); + if (generator) { + var res = generator(name); + if (res) return res; + } else if (runtime) { + return t.memberExpression(runtime, t.identifier(name)); + } + + var ref = (0, _babelHelpers2.default)(name); + var uid = this.declarations[name] = this.scope.generateUidIdentifier(name); + + if (t.isFunctionExpression(ref) && !ref.id) { + ref.body._compact = true; + ref._generated = true; + ref.id = uid; + ref.type = "FunctionDeclaration"; + this.path.unshiftContainer("body", ref); + } else { + ref._compact = true; + this.scope.push({ + id: uid, + init: ref, + unique: true + }); + } + + return uid; + }; + + File.prototype.addTemplateObject = function addTemplateObject(helperName, strings, raw) { + var stringIds = raw.elements.map(function (string) { + return string.value; + }); + var name = helperName + "_" + raw.elements.length + "_" + stringIds.join(","); + + var declar = this.declarations[name]; + if (declar) return declar; + + var uid = this.declarations[name] = this.scope.generateUidIdentifier("templateObject"); + + var helperId = this.addHelper(helperName); + var init = t.callExpression(helperId, [strings, raw]); + init._compact = true; + this.scope.push({ + id: uid, + init: init, + _blockHoist: 1.9 }); + return uid; + }; + + File.prototype.buildCodeFrameError = function buildCodeFrameError(node, msg) { + var Error = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : SyntaxError; + + var loc = node && (node.loc || node._loc); + + var err = new Error(msg); + + if (loc) { + err.loc = loc.start; + } else { + (0, _babelTraverse2.default)(node, errorVisitor, this.scope, err); + + err.message += " (This is an error on an internal node. Probably an internal error"; + + if (err.loc) { + err.message += ". Location has been estimated."; + } + + err.message += ")"; + } + + return err; + }; + + File.prototype.mergeSourceMap = function mergeSourceMap(map) { + var inputMap = this.opts.inputSourceMap; + + if (inputMap) { + var _ret = function () { + var inputMapConsumer = new _sourceMap2.default.SourceMapConsumer(inputMap); + var outputMapConsumer = new _sourceMap2.default.SourceMapConsumer(map); + + var mergedGenerator = new _sourceMap2.default.SourceMapGenerator({ + file: inputMapConsumer.file, + sourceRoot: inputMapConsumer.sourceRoot + }); + + var source = outputMapConsumer.sources[0]; + + inputMapConsumer.eachMapping(function (mapping) { + var generatedPosition = outputMapConsumer.generatedPositionFor({ + line: mapping.generatedLine, + column: mapping.generatedColumn, + source: source + }); + if (generatedPosition.column != null) { + mergedGenerator.addMapping({ + source: mapping.source, + + original: mapping.source == null ? null : { + line: mapping.originalLine, + column: mapping.originalColumn + }, + + generated: generatedPosition + }); + } + }); + + var mergedMap = mergedGenerator.toJSON(); + inputMap.mappings = mergedMap.mappings; + return { + v: inputMap + }; + }(); + + if ((typeof _ret === "undefined" ? "undefined" : (0, _typeof3.default)(_ret)) === "object") return _ret.v; + } else { + return map; + } + }; + + File.prototype.parse = function parse(code) { + var parseCode = _babylon.parse; + var parserOpts = this.opts.parserOpts; + + if (parserOpts) { + parserOpts = (0, _assign2.default)({}, this.parserOpts, parserOpts); + + if (parserOpts.parser) { + if (typeof parserOpts.parser === "string") { + var dirname = _path2.default.dirname(this.opts.filename) || process.cwd(); + var parser = (0, _resolve2.default)(parserOpts.parser, dirname); + if (parser) { + parseCode = require(parser).parse; + } else { + throw new Error("Couldn't find parser " + parserOpts.parser + " with \"parse\" method " + ("relative to directory " + dirname)); + } + } else { + parseCode = parserOpts.parser; + } + + parserOpts.parser = { + parse: function parse(source) { + return (0, _babylon.parse)(source, parserOpts); + } + }; + } + } + + this.log.debug("Parse start"); + var ast = parseCode(code, parserOpts || this.parserOpts); + this.log.debug("Parse stop"); + return ast; + }; + + File.prototype._addAst = function _addAst(ast) { + this.path = _babelTraverse.NodePath.get({ + hub: this.hub, + parentPath: null, + parent: ast, + container: ast, + key: "program" + }).setContext(); + this.scope = this.path.scope; + this.ast = ast; + this.getMetadata(); + }; + + File.prototype.addAst = function addAst(ast) { + this.log.debug("Start set AST"); + this._addAst(ast); + this.log.debug("End set AST"); + }; + + File.prototype.transform = function transform() { + for (var i = 0; i < this.pluginPasses.length; i++) { + var pluginPasses = this.pluginPasses[i]; + this.call("pre", pluginPasses); + this.log.debug("Start transform traverse"); + + var visitor = _babelTraverse2.default.visitors.merge(this.pluginVisitors[i], pluginPasses, this.opts.wrapPluginVisitorMethod); + (0, _babelTraverse2.default)(this.ast, visitor, this.scope); + + this.log.debug("End transform traverse"); + this.call("post", pluginPasses); + } + + return this.generate(); + }; + + File.prototype.wrap = function wrap(code, callback) { + code = code + ""; + + try { + if (this.shouldIgnore()) { + return this.makeResult({ code: code, ignored: true }); + } else { + return callback(); + } + } catch (err) { + if (err._babel) { + throw err; + } else { + err._babel = true; + } + + var message = err.message = this.opts.filename + ": " + err.message; + + var loc = err.loc; + if (loc) { + err.codeFrame = (0, _babelCodeFrame2.default)(code, loc.line, loc.column + 1, this.opts); + message += "\n" + err.codeFrame; + } + + if (process.browser) { + err.message = message; + } + + if (err.stack) { + var newStack = err.stack.replace(err.message, message); + err.stack = newStack; + } + + throw err; + } + }; + + File.prototype.addCode = function addCode(code) { + code = (code || "") + ""; + code = this.parseInputSourceMap(code); + this.code = code; + }; + + File.prototype.parseCode = function parseCode() { + this.parseShebang(); + var ast = this.parse(this.code); + this.addAst(ast); + }; + + File.prototype.shouldIgnore = function shouldIgnore() { + var opts = this.opts; + return util.shouldIgnore(opts.filename, opts.ignore, opts.only); + }; + + File.prototype.call = function call(key, pluginPasses) { + for (var _iterator3 = pluginPasses, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var pass = _ref3; + + var plugin = pass.plugin; + var fn = plugin[key]; + if (fn) fn.call(pass, this); + } + }; + + File.prototype.parseInputSourceMap = function parseInputSourceMap(code) { + var opts = this.opts; + + if (opts.inputSourceMap !== false) { + var inputMap = _convertSourceMap2.default.fromSource(code); + if (inputMap) { + opts.inputSourceMap = inputMap.toObject(); + code = _convertSourceMap2.default.removeComments(code); + } + } + + return code; + }; + + File.prototype.parseShebang = function parseShebang() { + var shebangMatch = shebangRegex.exec(this.code); + if (shebangMatch) { + this.shebang = shebangMatch[0]; + this.code = this.code.replace(shebangRegex, ""); + } + }; + + File.prototype.makeResult = function makeResult(_ref4) { + var code = _ref4.code, + map = _ref4.map, + ast = _ref4.ast, + ignored = _ref4.ignored; + + var result = { + metadata: null, + options: this.opts, + ignored: !!ignored, + code: null, + ast: null, + map: map || null + }; + + if (this.opts.code) { + result.code = code; + } + + if (this.opts.ast) { + result.ast = ast; + } + + if (this.opts.metadata) { + result.metadata = this.metadata; + } + + return result; + }; + + File.prototype.generate = function generate() { + var opts = this.opts; + var ast = this.ast; + + var result = { ast: ast }; + if (!opts.code) return this.makeResult(result); + + var gen = _babelGenerator2.default; + if (opts.generatorOpts.generator) { + gen = opts.generatorOpts.generator; + + if (typeof gen === "string") { + var dirname = _path2.default.dirname(this.opts.filename) || process.cwd(); + var generator = (0, _resolve2.default)(gen, dirname); + if (generator) { + gen = require(generator).print; + } else { + throw new Error("Couldn't find generator " + gen + " with \"print\" method relative " + ("to directory " + dirname)); + } + } + } + + this.log.debug("Generation start"); + + var _result = gen(ast, opts.generatorOpts ? (0, _assign2.default)(opts, opts.generatorOpts) : opts, this.code); + result.code = _result.code; + result.map = _result.map; + + this.log.debug("Generation end"); + + if (this.shebang) { + result.code = this.shebang + "\n" + result.code; + } + + if (result.map) { + result.map = this.mergeSourceMap(result.map); + } + + if (opts.sourceMaps === "inline" || opts.sourceMaps === "both") { + result.code += "\n" + _convertSourceMap2.default.fromObject(result.map).toComment(); + } + + if (opts.sourceMaps === "inline") { + result.map = null; + } + + return this.makeResult(result); + }; + + return File; +}(_store2.default); + +exports.default = File; +exports.File = File; +}).call(this,require('_process')) +},{"../../helpers/resolve":13,"../../store":14,"../../util":30,"../internal-plugins/block-hoist":25,"../internal-plugins/shadow-functions":26,"../plugin-pass":28,"./logger":17,"./metadata":18,"./options/option-manager":22,"_process":471,"babel-code-frame":3,"babel-generator":43,"babel-helpers":52,"babel-runtime/core-js/get-iterator":56,"babel-runtime/core-js/object/assign":60,"babel-runtime/core-js/object/create":61,"babel-runtime/helpers/classCallCheck":70,"babel-runtime/helpers/inherits":71,"babel-runtime/helpers/possibleConstructorReturn":73,"babel-runtime/helpers/typeof":74,"babel-traverse":79,"babel-types":112,"babylon":116,"convert-source-map":124,"lodash/defaults":420,"path":469,"source-map":484}],17:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _node = require("debug/node"); + +var _node2 = _interopRequireDefault(_node); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var verboseDebug = (0, _node2.default)("babel:verbose"); +var generalDebug = (0, _node2.default)("babel"); + +var seenDeprecatedMessages = []; + +var Logger = function () { + function Logger(file, filename) { + (0, _classCallCheck3.default)(this, Logger); + + this.filename = filename; + this.file = file; + } + + Logger.prototype._buildMessage = function _buildMessage(msg) { + var parts = "[BABEL] " + this.filename; + if (msg) parts += ": " + msg; + return parts; + }; + + Logger.prototype.warn = function warn(msg) { + console.warn(this._buildMessage(msg)); + }; + + Logger.prototype.error = function error(msg) { + var Constructor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Error; + + throw new Constructor(this._buildMessage(msg)); + }; + + Logger.prototype.deprecate = function deprecate(msg) { + if (this.file.opts && this.file.opts.suppressDeprecationMessages) return; + + msg = this._buildMessage(msg); + + if (seenDeprecatedMessages.indexOf(msg) >= 0) return; + + seenDeprecatedMessages.push(msg); + + console.error(msg); + }; + + Logger.prototype.verbose = function verbose(msg) { + if (verboseDebug.enabled) verboseDebug(this._buildMessage(msg)); + }; + + Logger.prototype.debug = function debug(msg) { + if (generalDebug.enabled) generalDebug(this._buildMessage(msg)); + }; + + Logger.prototype.deopt = function deopt(node, msg) { + this.debug(msg); + }; + + return Logger; +}(); + +exports.default = Logger; +module.exports = exports["default"]; +},{"babel-runtime/helpers/classCallCheck":70,"debug/node":231}],18:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.ImportDeclaration = exports.ModuleDeclaration = undefined; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.ExportDeclaration = ExportDeclaration; +exports.Scope = Scope; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var ModuleDeclaration = exports.ModuleDeclaration = { + enter: function enter(path, file) { + var node = path.node; + + if (node.source) { + node.source.value = file.resolveModuleSource(node.source.value); + } + } +}; + +var ImportDeclaration = exports.ImportDeclaration = { + exit: function exit(path, file) { + var node = path.node; + + + var specifiers = []; + var imported = []; + file.metadata.modules.imports.push({ + source: node.source.value, + imported: imported, + specifiers: specifiers + }); + + for (var _iterator = path.get("specifiers"), _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var specifier = _ref; + + var local = specifier.node.local.name; + + if (specifier.isImportDefaultSpecifier()) { + imported.push("default"); + specifiers.push({ + kind: "named", + imported: "default", + local: local + }); + } + + if (specifier.isImportSpecifier()) { + var importedName = specifier.node.imported.name; + imported.push(importedName); + specifiers.push({ + kind: "named", + imported: importedName, + local: local + }); + } + + if (specifier.isImportNamespaceSpecifier()) { + imported.push("*"); + specifiers.push({ + kind: "namespace", + local: local + }); + } + } + } +}; + +function ExportDeclaration(path, file) { + var node = path.node; + + + var source = node.source ? node.source.value : null; + var exports = file.metadata.modules.exports; + + var declar = path.get("declaration"); + if (declar.isStatement()) { + var bindings = declar.getBindingIdentifiers(); + + for (var name in bindings) { + exports.exported.push(name); + exports.specifiers.push({ + kind: "local", + local: name, + exported: path.isExportDefaultDeclaration() ? "default" : name + }); + } + } + + if (path.isExportNamedDeclaration() && node.specifiers) { + for (var _iterator2 = node.specifiers, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var specifier = _ref2; + + var exported = specifier.exported.name; + exports.exported.push(exported); + + if (t.isExportDefaultSpecifier(specifier)) { + exports.specifiers.push({ + kind: "external", + local: exported, + exported: exported, + source: source + }); + } + + if (t.isExportNamespaceSpecifier(specifier)) { + exports.specifiers.push({ + kind: "external-namespace", + exported: exported, + source: source + }); + } + + var local = specifier.local; + if (!local) continue; + + if (source) { + exports.specifiers.push({ + kind: "external", + local: local.name, + exported: exported, + source: source + }); + } + + if (!source) { + exports.specifiers.push({ + kind: "local", + local: local.name, + exported: exported + }); + } + } + } + + if (path.isExportAllDeclaration()) { + exports.specifiers.push({ + kind: "external-all", + source: source + }); + } +} + +function Scope(path) { + path.skip(); +} +},{"babel-runtime/core-js/get-iterator":56,"babel-types":112}],19:[function(require,module,exports){ +(function (process){ +"use strict"; + +exports.__esModule = true; + +var _assign = require("babel-runtime/core-js/object/assign"); + +var _assign2 = _interopRequireDefault(_assign); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +exports.default = buildConfigChain; + +var _resolve = require("../../../helpers/resolve"); + +var _resolve2 = _interopRequireDefault(_resolve); + +var _json = require("json5"); + +var _json2 = _interopRequireDefault(_json); + +var _pathIsAbsolute = require("path-is-absolute"); + +var _pathIsAbsolute2 = _interopRequireDefault(_pathIsAbsolute); + +var _path = require("path"); + +var _path2 = _interopRequireDefault(_path); + +var _fs = require("fs"); + +var _fs2 = _interopRequireDefault(_fs); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var existsCache = {}; +var jsonCache = {}; + +var BABELIGNORE_FILENAME = ".babelignore"; +var BABELRC_FILENAME = ".babelrc"; +var PACKAGE_FILENAME = "package.json"; + +function exists(filename) { + var cached = existsCache[filename]; + if (cached == null) { + return existsCache[filename] = _fs2.default.existsSync(filename); + } else { + return cached; + } +} + +function buildConfigChain() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var log = arguments[1]; + + var filename = opts.filename; + var builder = new ConfigChainBuilder(log); + + if (opts.babelrc !== false) { + builder.findConfigs(filename); + } + + builder.mergeConfig({ + options: opts, + alias: "base", + dirname: filename && _path2.default.dirname(filename) + }); + + return builder.configs; +} + +var ConfigChainBuilder = function () { + function ConfigChainBuilder(log) { + (0, _classCallCheck3.default)(this, ConfigChainBuilder); + + this.resolvedConfigs = []; + this.configs = []; + this.log = log; + } + + ConfigChainBuilder.prototype.findConfigs = function findConfigs(loc) { + if (!loc) return; + + if (!(0, _pathIsAbsolute2.default)(loc)) { + loc = _path2.default.join(process.cwd(), loc); + } + + var foundConfig = false; + var foundIgnore = false; + + while (loc !== (loc = _path2.default.dirname(loc))) { + if (!foundConfig) { + var configLoc = _path2.default.join(loc, BABELRC_FILENAME); + if (exists(configLoc)) { + this.addConfig(configLoc); + foundConfig = true; + } + + var pkgLoc = _path2.default.join(loc, PACKAGE_FILENAME); + if (!foundConfig && exists(pkgLoc)) { + foundConfig = this.addConfig(pkgLoc, "babel", JSON); + } + } + + if (!foundIgnore) { + var ignoreLoc = _path2.default.join(loc, BABELIGNORE_FILENAME); + if (exists(ignoreLoc)) { + this.addIgnoreConfig(ignoreLoc); + foundIgnore = true; + } + } + + if (foundIgnore && foundConfig) return; + } + }; + + ConfigChainBuilder.prototype.addIgnoreConfig = function addIgnoreConfig(loc) { + var file = _fs2.default.readFileSync(loc, "utf8"); + var lines = file.split("\n"); + + lines = lines.map(function (line) { + return line.replace(/#(.*?)$/, "").trim(); + }).filter(function (line) { + return !!line; + }); + + if (lines.length) { + this.mergeConfig({ + options: { ignore: lines }, + alias: loc, + dirname: _path2.default.dirname(loc) + }); + } + }; + + ConfigChainBuilder.prototype.addConfig = function addConfig(loc, key) { + var json = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _json2.default; + + if (this.resolvedConfigs.indexOf(loc) >= 0) { + return false; + } + + this.resolvedConfigs.push(loc); + + var content = _fs2.default.readFileSync(loc, "utf8"); + var options = void 0; + + try { + options = jsonCache[content] = jsonCache[content] || json.parse(content); + if (key) options = options[key]; + } catch (err) { + err.message = loc + ": Error while parsing JSON - " + err.message; + throw err; + } + + this.mergeConfig({ + options: options, + alias: loc, + dirname: _path2.default.dirname(loc) + }); + + return !!options; + }; + + ConfigChainBuilder.prototype.mergeConfig = function mergeConfig(_ref) { + var options = _ref.options, + alias = _ref.alias, + loc = _ref.loc, + dirname = _ref.dirname; + + if (!options) { + return false; + } + + options = (0, _assign2.default)({}, options); + + dirname = dirname || process.cwd(); + loc = loc || alias; + + if (options.extends) { + var extendsLoc = (0, _resolve2.default)(options.extends, dirname); + if (extendsLoc) { + this.addConfig(extendsLoc); + } else { + if (this.log) this.log.error("Couldn't resolve extends clause of " + options.extends + " in " + alias); + } + delete options.extends; + } + + this.configs.push({ + options: options, + alias: alias, + loc: loc, + dirname: dirname + }); + + var envOpts = void 0; + var envKey = process.env.BABEL_ENV || process.env.NODE_ENV || "development"; + if (options.env) { + envOpts = options.env[envKey]; + delete options.env; + } + + this.mergeConfig({ + options: envOpts, + alias: alias + ".env." + envKey, + dirname: dirname + }); + }; + + return ConfigChainBuilder; +}(); + +module.exports = exports["default"]; +}).call(this,require('_process')) +},{"../../../helpers/resolve":13,"_process":471,"babel-runtime/core-js/object/assign":60,"babel-runtime/helpers/classCallCheck":70,"fs":120,"json5":250,"path":469,"path-is-absolute":470}],20:[function(require,module,exports){ +"use strict"; + +module.exports = { + filename: { + type: "filename", + description: "filename to use when reading from stdin - this will be used in source-maps, errors etc", + default: "unknown", + shorthand: "f" + }, + + filenameRelative: { + hidden: true, + type: "string" + }, + + inputSourceMap: { + hidden: true + }, + + env: { + hidden: true, + default: {} + }, + + mode: { + description: "", + hidden: true + }, + + retainLines: { + type: "boolean", + default: false, + description: "retain line numbers - will result in really ugly code" + }, + + highlightCode: { + description: "enable/disable ANSI syntax highlighting of code frames (on by default)", + type: "boolean", + default: true + }, + + suppressDeprecationMessages: { + type: "boolean", + default: false, + hidden: true + }, + + presets: { + type: "list", + description: "", + default: [] + }, + + plugins: { + type: "list", + default: [], + description: "" + }, + + ignore: { + type: "list", + description: "list of glob paths to **not** compile", + default: [] + }, + + only: { + type: "list", + description: "list of glob paths to **only** compile" + }, + + code: { + hidden: true, + default: true, + type: "boolean" + }, + + metadata: { + hidden: true, + default: true, + type: "boolean" + }, + + ast: { + hidden: true, + default: true, + type: "boolean" + }, + + extends: { + type: "string", + hidden: true + }, + + comments: { + type: "boolean", + default: true, + description: "write comments to generated output (true by default)" + }, + + shouldPrintComment: { + hidden: true, + description: "optional callback to control whether a comment should be inserted, when this is used the comments option is ignored" + }, + + wrapPluginVisitorMethod: { + hidden: true, + description: "optional callback to wrap all visitor methods" + }, + + compact: { + type: "booleanString", + default: "auto", + description: "do not include superfluous whitespace characters and line terminators [true|false|auto]" + }, + + minified: { + type: "boolean", + default: false, + description: "save as much bytes when printing [true|false]" + }, + + sourceMap: { + alias: "sourceMaps", + hidden: true + }, + + sourceMaps: { + type: "booleanString", + description: "[true|false|inline]", + default: false, + shorthand: "s" + }, + + sourceMapTarget: { + type: "string", + description: "set `file` on returned source map" + }, + + sourceFileName: { + type: "string", + description: "set `sources[0]` on returned source map" + }, + + sourceRoot: { + type: "filename", + description: "the root from which all sources are relative" + }, + + babelrc: { + description: "Whether or not to look up .babelrc and .babelignore files", + type: "boolean", + default: true + }, + + sourceType: { + description: "", + default: "module" + }, + + auxiliaryCommentBefore: { + type: "string", + description: "print a comment before any injected non-user code" + }, + + auxiliaryCommentAfter: { + type: "string", + description: "print a comment after any injected non-user code" + }, + + resolveModuleSource: { + hidden: true + }, + + getModuleId: { + hidden: true + }, + + moduleRoot: { + type: "filename", + description: "optional prefix for the AMD module formatter that will be prepend to the filename on module definitions" + }, + + moduleIds: { + type: "boolean", + default: false, + shorthand: "M", + description: "insert an explicit id for modules" + }, + + moduleId: { + description: "specify a custom name for module ids", + type: "string" + }, + + passPerPreset: { + description: "Whether to spawn a traversal pass per a preset. By default all presets are merged.", + type: "boolean", + default: false, + hidden: true + }, + + parserOpts: { + description: "Options to pass into the parser, or to change parsers (parserOpts.parser)", + default: false + }, + + generatorOpts: { + description: "Options to pass into the generator, or to change generators (generatorOpts.generator)", + default: false + } +}; +},{}],21:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.config = undefined; +exports.normaliseOptions = normaliseOptions; + +var _parsers = require("./parsers"); + +var parsers = _interopRequireWildcard(_parsers); + +var _config = require("./config"); + +var _config2 = _interopRequireDefault(_config); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +exports.config = _config2.default; +function normaliseOptions() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + for (var key in options) { + var val = options[key]; + if (val == null) continue; + + var opt = _config2.default[key]; + if (opt && opt.alias) opt = _config2.default[opt.alias]; + if (!opt) continue; + + var parser = parsers[opt.type]; + if (parser) val = parser(val); + + options[key] = val; + } + + return options; +} +},{"./config":20,"./parsers":23}],22:[function(require,module,exports){ +(function (process){ +"use strict"; + +exports.__esModule = true; + +var _objectWithoutProperties2 = require("babel-runtime/helpers/objectWithoutProperties"); + +var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2); + +var _stringify = require("babel-runtime/core-js/json/stringify"); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _assign = require("babel-runtime/core-js/object/assign"); + +var _assign2 = _interopRequireDefault(_assign); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _node = require("../../../api/node"); + +var context = _interopRequireWildcard(_node); + +var _plugin2 = require("../../plugin"); + +var _plugin3 = _interopRequireDefault(_plugin2); + +var _babelMessages = require("babel-messages"); + +var messages = _interopRequireWildcard(_babelMessages); + +var _index = require("./index"); + +var _resolvePlugin = require("../../../helpers/resolve-plugin"); + +var _resolvePlugin2 = _interopRequireDefault(_resolvePlugin); + +var _resolvePreset = require("../../../helpers/resolve-preset"); + +var _resolvePreset2 = _interopRequireDefault(_resolvePreset); + +var _cloneDeepWith = require("lodash/cloneDeepWith"); + +var _cloneDeepWith2 = _interopRequireDefault(_cloneDeepWith); + +var _clone = require("lodash/clone"); + +var _clone2 = _interopRequireDefault(_clone); + +var _merge = require("../../../helpers/merge"); + +var _merge2 = _interopRequireDefault(_merge); + +var _config2 = require("./config"); + +var _config3 = _interopRequireDefault(_config2); + +var _removed = require("./removed"); + +var _removed2 = _interopRequireDefault(_removed); + +var _buildConfigChain = require("./build-config-chain"); + +var _buildConfigChain2 = _interopRequireDefault(_buildConfigChain); + +var _path = require("path"); + +var _path2 = _interopRequireDefault(_path); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var OptionManager = function () { + function OptionManager(log) { + (0, _classCallCheck3.default)(this, OptionManager); + + this.resolvedConfigs = []; + this.options = OptionManager.createBareOptions(); + this.log = log; + } + + OptionManager.memoisePluginContainer = function memoisePluginContainer(fn, loc, i, alias) { + for (var _iterator = OptionManager.memoisedPlugins, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var cache = _ref; + + if (cache.container === fn) return cache.plugin; + } + + var obj = void 0; + + if (typeof fn === "function") { + obj = fn(context); + } else { + obj = fn; + } + + if ((typeof obj === "undefined" ? "undefined" : (0, _typeof3.default)(obj)) === "object") { + var _plugin = new _plugin3.default(obj, alias); + OptionManager.memoisedPlugins.push({ + container: fn, + plugin: _plugin + }); + return _plugin; + } else { + throw new TypeError(messages.get("pluginNotObject", loc, i, typeof obj === "undefined" ? "undefined" : (0, _typeof3.default)(obj)) + loc + i); + } + }; + + OptionManager.createBareOptions = function createBareOptions() { + var opts = {}; + + for (var _key in _config3.default) { + var opt = _config3.default[_key]; + opts[_key] = (0, _clone2.default)(opt.default); + } + + return opts; + }; + + OptionManager.normalisePlugin = function normalisePlugin(plugin, loc, i, alias) { + plugin = plugin.__esModule ? plugin.default : plugin; + + if (!(plugin instanceof _plugin3.default)) { + if (typeof plugin === "function" || (typeof plugin === "undefined" ? "undefined" : (0, _typeof3.default)(plugin)) === "object") { + plugin = OptionManager.memoisePluginContainer(plugin, loc, i, alias); + } else { + throw new TypeError(messages.get("pluginNotFunction", loc, i, typeof plugin === "undefined" ? "undefined" : (0, _typeof3.default)(plugin))); + } + } + + plugin.init(loc, i); + + return plugin; + }; + + OptionManager.normalisePlugins = function normalisePlugins(loc, dirname, plugins) { + return plugins.map(function (val, i) { + var plugin = void 0, + options = void 0; + + if (!val) { + throw new TypeError("Falsy value found in plugins"); + } + + if (Array.isArray(val)) { + plugin = val[0]; + options = val[1]; + } else { + plugin = val; + } + + var alias = typeof plugin === "string" ? plugin : loc + "$" + i; + + if (typeof plugin === "string") { + var pluginLoc = (0, _resolvePlugin2.default)(plugin, dirname); + if (pluginLoc) { + plugin = require(pluginLoc); + } else { + throw new ReferenceError(messages.get("pluginUnknown", plugin, loc, i, dirname)); + } + } + + plugin = OptionManager.normalisePlugin(plugin, loc, i, alias); + + return [plugin, options]; + }); + }; + + OptionManager.prototype.mergeOptions = function mergeOptions(_ref2) { + var _this = this; + + var rawOpts = _ref2.options, + extendingOpts = _ref2.extending, + alias = _ref2.alias, + loc = _ref2.loc, + dirname = _ref2.dirname; + + alias = alias || "foreign"; + if (!rawOpts) return; + + if ((typeof rawOpts === "undefined" ? "undefined" : (0, _typeof3.default)(rawOpts)) !== "object" || Array.isArray(rawOpts)) { + this.log.error("Invalid options type for " + alias, TypeError); + } + + var opts = (0, _cloneDeepWith2.default)(rawOpts, function (val) { + if (val instanceof _plugin3.default) { + return val; + } + }); + + dirname = dirname || process.cwd(); + loc = loc || alias; + + for (var _key2 in opts) { + var option = _config3.default[_key2]; + + if (!option && this.log) { + if (_removed2.default[_key2]) { + this.log.error("Using removed Babel 5 option: " + alias + "." + _key2 + " - " + _removed2.default[_key2].message, ReferenceError); + } else { + var unknownOptErr = "Unknown option: " + alias + "." + _key2 + ". Check out http://babeljs.io/docs/usage/options/ for more information about options."; + var presetConfigErr = "A common cause of this error is the presence of a configuration options object without the corresponding preset name. Example:\n\nInvalid:\n `{ presets: [{option: value}] }`\nValid:\n `{ presets: [['presetName', {option: value}]] }`\n\nFor more detailed information on preset configuration, please see http://babeljs.io/docs/plugins/#pluginpresets-options."; + + + this.log.error(unknownOptErr + "\n\n" + presetConfigErr, ReferenceError); + } + } + } + + (0, _index.normaliseOptions)(opts); + + if (opts.plugins) { + opts.plugins = OptionManager.normalisePlugins(loc, dirname, opts.plugins); + } + + if (opts.presets) { + if (opts.passPerPreset) { + opts.presets = this.resolvePresets(opts.presets, dirname, function (preset, presetLoc) { + _this.mergeOptions({ + options: preset, + extending: preset, + alias: presetLoc, + loc: presetLoc, + dirname: dirname + }); + }); + } else { + this.mergePresets(opts.presets, dirname); + delete opts.presets; + } + } + + if (rawOpts === extendingOpts) { + (0, _assign2.default)(extendingOpts, opts); + } else { + (0, _merge2.default)(extendingOpts || this.options, opts); + } + }; + + OptionManager.prototype.mergePresets = function mergePresets(presets, dirname) { + var _this2 = this; + + this.resolvePresets(presets, dirname, function (presetOpts, presetLoc) { + _this2.mergeOptions({ + options: presetOpts, + alias: presetLoc, + loc: presetLoc, + dirname: _path2.default.dirname(presetLoc || "") + }); + }); + }; + + OptionManager.prototype.resolvePresets = function resolvePresets(presets, dirname, onResolve) { + return presets.map(function (val) { + var options = void 0; + if (Array.isArray(val)) { + if (val.length > 2) { + throw new Error("Unexpected extra options " + (0, _stringify2.default)(val.slice(2)) + " passed to preset."); + } + + var _val = val; + val = _val[0]; + options = _val[1]; + } + + var presetLoc = void 0; + try { + if (typeof val === "string") { + presetLoc = (0, _resolvePreset2.default)(val, dirname); + + if (!presetLoc) { + throw new Error("Couldn't find preset " + (0, _stringify2.default)(val) + " relative to directory " + (0, _stringify2.default)(dirname)); + } + + val = require(presetLoc); + } + + if ((typeof val === "undefined" ? "undefined" : (0, _typeof3.default)(val)) === "object" && val.__esModule) { + if (val.default) { + val = val.default; + } else { + var _val2 = val, + __esModule = _val2.__esModule, + rest = (0, _objectWithoutProperties3.default)(_val2, ["__esModule"]); + + val = rest; + } + } + + if ((typeof val === "undefined" ? "undefined" : (0, _typeof3.default)(val)) === "object" && val.buildPreset) val = val.buildPreset; + + if (typeof val !== "function" && options !== undefined) { + throw new Error("Options " + (0, _stringify2.default)(options) + " passed to " + (presetLoc || "a preset") + " which does not accept options."); + } + + if (typeof val === "function") val = val(context, options); + + if ((typeof val === "undefined" ? "undefined" : (0, _typeof3.default)(val)) !== "object") { + throw new Error("Unsupported preset format: " + val + "."); + } + + onResolve && onResolve(val, presetLoc); + } catch (e) { + if (presetLoc) { + e.message += " (While processing preset: " + (0, _stringify2.default)(presetLoc) + ")"; + } + throw e; + } + return val; + }); + }; + + OptionManager.prototype.normaliseOptions = function normaliseOptions() { + var opts = this.options; + + for (var _key3 in _config3.default) { + var option = _config3.default[_key3]; + var val = opts[_key3]; + + if (!val && option.optional) continue; + + if (option.alias) { + opts[option.alias] = opts[option.alias] || val; + } else { + opts[_key3] = val; + } + } + }; + + OptionManager.prototype.init = function init() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + for (var _iterator2 = (0, _buildConfigChain2.default)(opts, this.log), _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref3; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref3 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref3 = _i2.value; + } + + var _config = _ref3; + + this.mergeOptions(_config); + } + + this.normaliseOptions(opts); + + return this.options; + }; + + return OptionManager; +}(); + +exports.default = OptionManager; + + +OptionManager.memoisedPlugins = []; +module.exports = exports["default"]; +}).call(this,require('_process')) +},{"../../../api/node":5,"../../../helpers/merge":8,"../../../helpers/resolve-plugin":11,"../../../helpers/resolve-preset":12,"../../plugin":29,"./build-config-chain":19,"./config":20,"./index":21,"./removed":24,"_process":471,"babel-messages":53,"babel-runtime/core-js/get-iterator":56,"babel-runtime/core-js/json/stringify":57,"babel-runtime/core-js/object/assign":60,"babel-runtime/helpers/classCallCheck":70,"babel-runtime/helpers/objectWithoutProperties":72,"babel-runtime/helpers/typeof":74,"lodash/clone":416,"lodash/cloneDeepWith":418,"path":469}],23:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.filename = undefined; +exports.boolean = boolean; +exports.booleanString = booleanString; +exports.list = list; + +var _slash = require("slash"); + +var _slash2 = _interopRequireDefault(_slash); + +var _util = require("../../../util"); + +var util = _interopRequireWildcard(_util); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var filename = exports.filename = _slash2.default; + +function boolean(val) { + return !!val; +} + +function booleanString(val) { + return util.booleanify(val); +} + +function list(val) { + return util.list(val); +} +},{"../../../util":30,"slash":473}],24:[function(require,module,exports){ +"use strict"; + +module.exports = { + "auxiliaryComment": { + "message": "Use `auxiliaryCommentBefore` or `auxiliaryCommentAfter`" + }, + "blacklist": { + "message": "Put the specific transforms you want in the `plugins` option" + }, + "breakConfig": { + "message": "This is not a necessary option in Babel 6" + }, + "experimental": { + "message": "Put the specific transforms you want in the `plugins` option" + }, + "externalHelpers": { + "message": "Use the `external-helpers` plugin instead. Check out http://babeljs.io/docs/plugins/external-helpers/" + }, + "extra": { + "message": "" + }, + "jsxPragma": { + "message": "use the `pragma` option in the `react-jsx` plugin . Check out http://babeljs.io/docs/plugins/transform-react-jsx/" + }, + + "loose": { + "message": "Specify the `loose` option for the relevant plugin you are using or use a preset that sets the option." + }, + "metadataUsedHelpers": { + "message": "Not required anymore as this is enabled by default" + }, + "modules": { + "message": "Use the corresponding module transform plugin in the `plugins` option. Check out http://babeljs.io/docs/plugins/#modules" + }, + "nonStandard": { + "message": "Use the `react-jsx` and `flow-strip-types` plugins to support JSX and Flow. Also check out the react preset http://babeljs.io/docs/plugins/preset-react/" + }, + "optional": { + "message": "Put the specific transforms you want in the `plugins` option" + }, + "sourceMapName": { + "message": "Use the `sourceMapTarget` option" + }, + "stage": { + "message": "Check out the corresponding stage-x presets http://babeljs.io/docs/plugins/#presets" + }, + "whitelist": { + "message": "Put the specific transforms you want in the `plugins` option" + } +}; +},{}],25:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _plugin = require("../plugin"); + +var _plugin2 = _interopRequireDefault(_plugin); + +var _sortBy = require("lodash/sortBy"); + +var _sortBy2 = _interopRequireDefault(_sortBy); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = new _plugin2.default({ + + name: "internal.blockHoist", + + visitor: { + Block: { + exit: function exit(_ref) { + var node = _ref.node; + + var hasChange = false; + for (var i = 0; i < node.body.length; i++) { + var bodyNode = node.body[i]; + if (bodyNode && bodyNode._blockHoist != null) { + hasChange = true; + break; + } + } + if (!hasChange) return; + + node.body = (0, _sortBy2.default)(node.body, function (bodyNode) { + var priority = bodyNode && bodyNode._blockHoist; + if (priority == null) priority = 1; + if (priority === true) priority = 2; + + return -1 * priority; + }); + } + } + } +}); +module.exports = exports["default"]; +},{"../plugin":29,"lodash/sortBy":455}],26:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _symbol = require("babel-runtime/core-js/symbol"); + +var _symbol2 = _interopRequireDefault(_symbol); + +var _plugin = require("../plugin"); + +var _plugin2 = _interopRequireDefault(_plugin); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var SUPER_THIS_BOUND = (0, _symbol2.default)("super this bound"); + +var superVisitor = { + CallExpression: function CallExpression(path) { + if (!path.get("callee").isSuper()) return; + + var node = path.node; + + if (node[SUPER_THIS_BOUND]) return; + node[SUPER_THIS_BOUND] = true; + + path.replaceWith(t.assignmentExpression("=", this.id, node)); + } +}; + +exports.default = new _plugin2.default({ + name: "internal.shadowFunctions", + + visitor: { + ThisExpression: function ThisExpression(path) { + remap(path, "this"); + }, + ReferencedIdentifier: function ReferencedIdentifier(path) { + if (path.node.name === "arguments") { + remap(path, "arguments"); + } + } + } +}); + + +function shouldShadow(path, shadowPath) { + if (path.is("_forceShadow")) { + return true; + } else { + return shadowPath; + } +} + +function remap(path, key) { + var shadowPath = path.inShadow(key); + if (!shouldShadow(path, shadowPath)) return; + + var shadowFunction = path.node._shadowedFunctionLiteral; + + var currentFunction = void 0; + var passedShadowFunction = false; + + var fnPath = path.find(function (innerPath) { + if (innerPath.parentPath && innerPath.parentPath.isClassProperty() && innerPath.key === "value") { + return true; + } + if (path === innerPath) return false; + if (innerPath.isProgram() || innerPath.isFunction()) { + currentFunction = currentFunction || innerPath; + } + + if (innerPath.isProgram()) { + passedShadowFunction = true; + + return true; + } else if (innerPath.isFunction() && !innerPath.isArrowFunctionExpression()) { + if (shadowFunction) { + if (innerPath === shadowFunction || innerPath.node === shadowFunction.node) return true; + } else { + if (!innerPath.is("shadow")) return true; + } + + passedShadowFunction = true; + return false; + } + + return false; + }); + + if (shadowFunction && fnPath.isProgram() && !shadowFunction.isProgram()) { + fnPath = path.findParent(function (p) { + return p.isProgram() || p.isFunction(); + }); + } + + if (fnPath === currentFunction) return; + + if (!passedShadowFunction) return; + + var cached = fnPath.getData(key); + if (cached) return path.replaceWith(cached); + + var id = path.scope.generateUidIdentifier(key); + + fnPath.setData(key, id); + + var classPath = fnPath.findParent(function (p) { + return p.isClass(); + }); + var hasSuperClass = !!(classPath && classPath.node && classPath.node.superClass); + + if (key === "this" && fnPath.isMethod({ kind: "constructor" }) && hasSuperClass) { + fnPath.scope.push({ id: id }); + + fnPath.traverse(superVisitor, { id: id }); + } else { + var init = key === "this" ? t.thisExpression() : t.identifier(key); + + if (shadowFunction) init._shadowedFunctionLiteral = shadowFunction; + + fnPath.scope.push({ id: id, init: init }); + } + + return path.replaceWith(id); +} +module.exports = exports["default"]; +},{"../plugin":29,"babel-runtime/core-js/symbol":65,"babel-types":112}],27:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _normalizeAst = require("../helpers/normalize-ast"); + +var _normalizeAst2 = _interopRequireDefault(_normalizeAst); + +var _plugin = require("./plugin"); + +var _plugin2 = _interopRequireDefault(_plugin); + +var _file = require("./file"); + +var _file2 = _interopRequireDefault(_file); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var Pipeline = function () { + function Pipeline() { + (0, _classCallCheck3.default)(this, Pipeline); + } + + Pipeline.prototype.lint = function lint(code) { + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + opts.code = false; + opts.mode = "lint"; + return this.transform(code, opts); + }; + + Pipeline.prototype.pretransform = function pretransform(code, opts) { + var file = new _file2.default(opts, this); + return file.wrap(code, function () { + file.addCode(code); + file.parseCode(code); + return file; + }); + }; + + Pipeline.prototype.transform = function transform(code, opts) { + var file = new _file2.default(opts, this); + return file.wrap(code, function () { + file.addCode(code); + file.parseCode(code); + return file.transform(); + }); + }; + + Pipeline.prototype.analyse = function analyse(code) { + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var visitor = arguments[2]; + + opts.code = false; + if (visitor) { + opts.plugins = opts.plugins || []; + opts.plugins.push(new _plugin2.default({ visitor: visitor })); + } + return this.transform(code, opts).metadata; + }; + + Pipeline.prototype.transformFromAst = function transformFromAst(ast, code, opts) { + ast = (0, _normalizeAst2.default)(ast); + + var file = new _file2.default(opts, this); + return file.wrap(code, function () { + file.addCode(code); + file.addAst(ast); + return file.transform(); + }); + }; + + return Pipeline; +}(); + +exports.default = Pipeline; +module.exports = exports["default"]; +},{"../helpers/normalize-ast":9,"./file":16,"./plugin":29,"babel-runtime/helpers/classCallCheck":70}],28:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _possibleConstructorReturn2 = require("babel-runtime/helpers/possibleConstructorReturn"); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require("babel-runtime/helpers/inherits"); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _store = require("../store"); + +var _store2 = _interopRequireDefault(_store); + +var _file5 = require("./file"); + +var _file6 = _interopRequireDefault(_file5); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var PluginPass = function (_Store) { + (0, _inherits3.default)(PluginPass, _Store); + + function PluginPass(file, plugin) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + (0, _classCallCheck3.default)(this, PluginPass); + + var _this = (0, _possibleConstructorReturn3.default)(this, _Store.call(this)); + + _this.plugin = plugin; + _this.key = plugin.key; + _this.file = file; + _this.opts = options; + return _this; + } + + PluginPass.prototype.addHelper = function addHelper() { + var _file; + + return (_file = this.file).addHelper.apply(_file, arguments); + }; + + PluginPass.prototype.addImport = function addImport() { + var _file2; + + return (_file2 = this.file).addImport.apply(_file2, arguments); + }; + + PluginPass.prototype.getModuleName = function getModuleName() { + var _file3; + + return (_file3 = this.file).getModuleName.apply(_file3, arguments); + }; + + PluginPass.prototype.buildCodeFrameError = function buildCodeFrameError() { + var _file4; + + return (_file4 = this.file).buildCodeFrameError.apply(_file4, arguments); + }; + + return PluginPass; +}(_store2.default); + +exports.default = PluginPass; +module.exports = exports["default"]; +},{"../store":14,"./file":16,"babel-runtime/helpers/classCallCheck":70,"babel-runtime/helpers/inherits":71,"babel-runtime/helpers/possibleConstructorReturn":73}],29:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _possibleConstructorReturn2 = require("babel-runtime/helpers/possibleConstructorReturn"); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require("babel-runtime/helpers/inherits"); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _optionManager = require("./file/options/option-manager"); + +var _optionManager2 = _interopRequireDefault(_optionManager); + +var _babelMessages = require("babel-messages"); + +var messages = _interopRequireWildcard(_babelMessages); + +var _store = require("../store"); + +var _store2 = _interopRequireDefault(_store); + +var _babelTraverse = require("babel-traverse"); + +var _babelTraverse2 = _interopRequireDefault(_babelTraverse); + +var _assign = require("lodash/assign"); + +var _assign2 = _interopRequireDefault(_assign); + +var _clone = require("lodash/clone"); + +var _clone2 = _interopRequireDefault(_clone); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var GLOBAL_VISITOR_PROPS = ["enter", "exit"]; + +var Plugin = function (_Store) { + (0, _inherits3.default)(Plugin, _Store); + + function Plugin(plugin, key) { + (0, _classCallCheck3.default)(this, Plugin); + + var _this = (0, _possibleConstructorReturn3.default)(this, _Store.call(this)); + + _this.initialized = false; + _this.raw = (0, _assign2.default)({}, plugin); + _this.key = _this.take("name") || key; + + _this.manipulateOptions = _this.take("manipulateOptions"); + _this.post = _this.take("post"); + _this.pre = _this.take("pre"); + _this.visitor = _this.normaliseVisitor((0, _clone2.default)(_this.take("visitor")) || {}); + return _this; + } + + Plugin.prototype.take = function take(key) { + var val = this.raw[key]; + delete this.raw[key]; + return val; + }; + + Plugin.prototype.chain = function chain(target, key) { + if (!target[key]) return this[key]; + if (!this[key]) return target[key]; + + var fns = [target[key], this[key]]; + + return function () { + var val = void 0; + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + for (var _iterator = fns, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var fn = _ref; + + if (fn) { + var ret = fn.apply(this, args); + if (ret != null) val = ret; + } + } + return val; + }; + }; + + Plugin.prototype.maybeInherit = function maybeInherit(loc) { + var inherits = this.take("inherits"); + if (!inherits) return; + + inherits = _optionManager2.default.normalisePlugin(inherits, loc, "inherits"); + + this.manipulateOptions = this.chain(inherits, "manipulateOptions"); + this.post = this.chain(inherits, "post"); + this.pre = this.chain(inherits, "pre"); + this.visitor = _babelTraverse2.default.visitors.merge([inherits.visitor, this.visitor]); + }; + + Plugin.prototype.init = function init(loc, i) { + if (this.initialized) return; + this.initialized = true; + + this.maybeInherit(loc); + + for (var key in this.raw) { + throw new Error(messages.get("pluginInvalidProperty", loc, i, key)); + } + }; + + Plugin.prototype.normaliseVisitor = function normaliseVisitor(visitor) { + for (var _iterator2 = GLOBAL_VISITOR_PROPS, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var key = _ref2; + + if (visitor[key]) { + throw new Error("Plugins aren't allowed to specify catch-all enter/exit handlers. " + "Please target individual nodes."); + } + } + + _babelTraverse2.default.explode(visitor); + return visitor; + }; + + return Plugin; +}(_store2.default); + +exports.default = Plugin; +module.exports = exports["default"]; +},{"../store":14,"./file/options/option-manager":22,"babel-messages":53,"babel-runtime/core-js/get-iterator":56,"babel-runtime/helpers/classCallCheck":70,"babel-runtime/helpers/inherits":71,"babel-runtime/helpers/possibleConstructorReturn":73,"babel-traverse":79,"lodash/assign":414,"lodash/clone":416}],30:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.inspect = exports.inherits = undefined; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _util = require("util"); + +Object.defineProperty(exports, "inherits", { + enumerable: true, + get: function get() { + return _util.inherits; + } +}); +Object.defineProperty(exports, "inspect", { + enumerable: true, + get: function get() { + return _util.inspect; + } +}); +exports.canCompile = canCompile; +exports.list = list; +exports.regexify = regexify; +exports.arrayify = arrayify; +exports.booleanify = booleanify; +exports.shouldIgnore = shouldIgnore; + +var _escapeRegExp = require("lodash/escapeRegExp"); + +var _escapeRegExp2 = _interopRequireDefault(_escapeRegExp); + +var _startsWith = require("lodash/startsWith"); + +var _startsWith2 = _interopRequireDefault(_startsWith); + +var _minimatch = require("minimatch"); + +var _minimatch2 = _interopRequireDefault(_minimatch); + +var _includes = require("lodash/includes"); + +var _includes2 = _interopRequireDefault(_includes); + +var _isRegExp = require("lodash/isRegExp"); + +var _isRegExp2 = _interopRequireDefault(_isRegExp); + +var _path = require("path"); + +var _path2 = _interopRequireDefault(_path); + +var _slash = require("slash"); + +var _slash2 = _interopRequireDefault(_slash); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function canCompile(filename, altExts) { + var exts = altExts || canCompile.EXTENSIONS; + var ext = _path2.default.extname(filename); + return (0, _includes2.default)(exts, ext); +} + +canCompile.EXTENSIONS = [".js", ".jsx", ".es6", ".es"]; + +function list(val) { + if (!val) { + return []; + } else if (Array.isArray(val)) { + return val; + } else if (typeof val === "string") { + return val.split(","); + } else { + return [val]; + } +} + +function regexify(val) { + if (!val) { + return new RegExp(/.^/); + } + + if (Array.isArray(val)) { + val = new RegExp(val.map(_escapeRegExp2.default).join("|"), "i"); + } + + if (typeof val === "string") { + val = (0, _slash2.default)(val); + + if ((0, _startsWith2.default)(val, "./") || (0, _startsWith2.default)(val, "*/")) val = val.slice(2); + if ((0, _startsWith2.default)(val, "**/")) val = val.slice(3); + + var regex = _minimatch2.default.makeRe(val, { nocase: true }); + return new RegExp(regex.source.slice(1, -1), "i"); + } + + if ((0, _isRegExp2.default)(val)) { + return val; + } + + throw new TypeError("illegal type for regexify"); +} + +function arrayify(val, mapFn) { + if (!val) return []; + if (typeof val === "boolean") return arrayify([val], mapFn); + if (typeof val === "string") return arrayify(list(val), mapFn); + + if (Array.isArray(val)) { + if (mapFn) val = val.map(mapFn); + return val; + } + + return [val]; +} + +function booleanify(val) { + if (val === "true" || val == 1) { + return true; + } + + if (val === "false" || val == 0 || !val) { + return false; + } + + return val; +} + +function shouldIgnore(filename) { + var ignore = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + var only = arguments[2]; + + filename = filename.replace(/\\/g, "/"); + + if (only) { + for (var _iterator = only, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var pattern = _ref; + + if (_shouldIgnore(pattern, filename)) return false; + } + return true; + } else if (ignore.length) { + for (var _iterator2 = ignore, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var _pattern = _ref2; + + if (_shouldIgnore(_pattern, filename)) return true; + } + } + + return false; +} + +function _shouldIgnore(pattern, filename) { + if (typeof pattern === "function") { + return pattern(filename); + } else { + return pattern.test(filename); + } +} +},{"babel-runtime/core-js/get-iterator":56,"lodash/escapeRegExp":422,"lodash/includes":431,"lodash/isRegExp":443,"lodash/startsWith":456,"minimatch":466,"path":469,"slash":473,"util":492}],31:[function(require,module,exports){ +module.exports={ + "_args": [ + [ + { + "raw": "babel-core@^6.22.1", + "scope": null, + "escapedName": "babel-core", + "name": "babel-core", + "rawSpec": "^6.22.1", + "spec": ">=6.22.1 <7.0.0", + "type": "range" + }, + "/home/directxman12/dev/noVNC" + ] + ], + "_from": "babel-core@>=6.22.1 <7.0.0", + "_id": "babel-core@6.23.1", + "_inCache": true, + "_location": "/babel-core", + "_nodeVersion": "6.9.1", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/babel-core-6.23.1.tgz_1487038699717_0.8698694983031601" + }, + "_npmUser": { + "name": "loganfsmyth", + "email": "loganfsmyth@gmail.com" + }, + "_npmVersion": "3.10.8", + "_phantomChildren": {}, + "_requested": { + "raw": "babel-core@^6.22.1", + "scope": null, + "escapedName": "babel-core", + "name": "babel-core", + "rawSpec": "^6.22.1", + "spec": ">=6.22.1 <7.0.0", + "type": "range" + }, + "_requiredBy": [ + "#DEV:/", + "/babel-register", + "/babelify", + "/karma-babel-preprocessor" + ], + "_resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.23.1.tgz", + "_shasum": "c143cb621bb2f621710c220c5d579d15b8a442df", + "_shrinkwrap": null, + "_spec": "babel-core@^6.22.1", + "_where": "/home/directxman12/dev/noVNC", + "author": { + "name": "Sebastian McKenzie", + "email": "sebmck@gmail.com" + }, + "dependencies": { + "babel-code-frame": "^6.22.0", + "babel-generator": "^6.23.0", + "babel-helpers": "^6.23.0", + "babel-messages": "^6.23.0", + "babel-register": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.23.0", + "babel-traverse": "^6.23.1", + "babel-types": "^6.23.0", + "babylon": "^6.11.0", + "convert-source-map": "^1.1.0", + "debug": "^2.1.1", + "json5": "^0.5.0", + "lodash": "^4.2.0", + "minimatch": "^3.0.2", + "path-is-absolute": "^1.0.0", + "private": "^0.1.6", + "slash": "^1.0.0", + "source-map": "^0.5.0" + }, + "description": "Babel compiler core.", + "devDependencies": { + "babel-helper-fixtures": "^6.22.0", + "babel-helper-transform-fixture-test-runner": "^6.23.0", + "babel-polyfill": "^6.23.0" + }, + "directories": {}, + "dist": { + "shasum": "c143cb621bb2f621710c220c5d579d15b8a442df", + "tarball": "https://registry.npmjs.org/babel-core/-/babel-core-6.23.1.tgz" + }, + "homepage": "https://babeljs.io/", + "keywords": [ + "6to5", + "babel", + "classes", + "const", + "es6", + "harmony", + "let", + "modules", + "transpile", + "transpiler", + "var", + "babel-core", + "compiler" + ], + "license": "MIT", + "maintainers": [ + { + "name": "amasad", + "email": "amjad.masad@gmail.com" + }, + { + "name": "hzoo", + "email": "hi@henryzoo.com" + }, + { + "name": "jmm", + "email": "npm-public@jessemccarthy.net" + }, + { + "name": "loganfsmyth", + "email": "loganfsmyth@gmail.com" + }, + { + "name": "sebmck", + "email": "sebmck@gmail.com" + }, + { + "name": "thejameskyle", + "email": "me@thejameskyle.com" + } + ], + "name": "babel-core", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "https://github.com/babel/babel/tree/master/packages/babel-core" + }, + "scripts": { + "bench": "make bench", + "test": "make test" + }, + "version": "6.23.1" +} + +},{}],32:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _trimRight = require("trim-right"); + +var _trimRight2 = _interopRequireDefault(_trimRight); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var SPACES_RE = /^[ \t]+$/; + +var Buffer = function () { + function Buffer(map) { + (0, _classCallCheck3.default)(this, Buffer); + this._map = null; + this._buf = []; + this._last = ""; + this._queue = []; + this._position = { + line: 1, + column: 0 + }; + this._sourcePosition = { + identifierName: null, + line: null, + column: null, + filename: null + }; + + this._map = map; + } + + Buffer.prototype.get = function get() { + this._flush(); + + var map = this._map; + var result = { + code: (0, _trimRight2.default)(this._buf.join("")), + map: null, + rawMappings: map && map.getRawMappings() + }; + + if (map) { + Object.defineProperty(result, "map", { + configurable: true, + enumerable: true, + get: function get() { + return this.map = map.get(); + }, + set: function set(value) { + Object.defineProperty(this, "map", { value: value, writable: true }); + } + }); + } + + return result; + }; + + Buffer.prototype.append = function append(str) { + this._flush(); + var _sourcePosition = this._sourcePosition, + line = _sourcePosition.line, + column = _sourcePosition.column, + filename = _sourcePosition.filename, + identifierName = _sourcePosition.identifierName; + + this._append(str, line, column, identifierName, filename); + }; + + Buffer.prototype.queue = function queue(str) { + if (str === "\n") while (this._queue.length > 0 && SPACES_RE.test(this._queue[0][0])) { + this._queue.shift(); + }var _sourcePosition2 = this._sourcePosition, + line = _sourcePosition2.line, + column = _sourcePosition2.column, + filename = _sourcePosition2.filename, + identifierName = _sourcePosition2.identifierName; + + this._queue.unshift([str, line, column, identifierName, filename]); + }; + + Buffer.prototype._flush = function _flush() { + var item = void 0; + while (item = this._queue.pop()) { + this._append.apply(this, item); + } + }; + + Buffer.prototype._append = function _append(str, line, column, identifierName, filename) { + if (this._map && str[0] !== "\n") { + this._map.mark(this._position.line, this._position.column, line, column, identifierName, filename); + } + + this._buf.push(str); + this._last = str[str.length - 1]; + + for (var i = 0; i < str.length; i++) { + if (str[i] === "\n") { + this._position.line++; + this._position.column = 0; + } else { + this._position.column++; + } + } + }; + + Buffer.prototype.removeTrailingNewline = function removeTrailingNewline() { + if (this._queue.length > 0 && this._queue[0][0] === "\n") this._queue.shift(); + }; + + Buffer.prototype.removeLastSemicolon = function removeLastSemicolon() { + if (this._queue.length > 0 && this._queue[0][0] === ";") this._queue.shift(); + }; + + Buffer.prototype.endsWith = function endsWith(suffix) { + if (suffix.length === 1) { + var last = void 0; + if (this._queue.length > 0) { + var str = this._queue[0][0]; + last = str[str.length - 1]; + } else { + last = this._last; + } + + return last === suffix; + } + + var end = this._last + this._queue.reduce(function (acc, item) { + return item[0] + acc; + }, ""); + if (suffix.length <= end.length) { + return end.slice(-suffix.length) === suffix; + } + + return false; + }; + + Buffer.prototype.hasContent = function hasContent() { + return this._queue.length > 0 || !!this._last; + }; + + Buffer.prototype.source = function source(prop, loc) { + if (prop && !loc) return; + + var pos = loc ? loc[prop] : null; + + this._sourcePosition.identifierName = loc && loc.identifierName || null; + this._sourcePosition.line = pos ? pos.line : null; + this._sourcePosition.column = pos ? pos.column : null; + this._sourcePosition.filename = loc && loc.filename || null; + }; + + Buffer.prototype.withSource = function withSource(prop, loc, cb) { + if (!this._map) return cb(); + + var originalLine = this._sourcePosition.line; + var originalColumn = this._sourcePosition.column; + var originalFilename = this._sourcePosition.filename; + var originalIdentifierName = this._sourcePosition.identifierName; + + this.source(prop, loc); + + cb(); + + this._sourcePosition.line = originalLine; + this._sourcePosition.column = originalColumn; + this._sourcePosition.filename = originalFilename; + this._sourcePosition.identifierName = originalIdentifierName; + }; + + Buffer.prototype.getCurrentColumn = function getCurrentColumn() { + var extra = this._queue.reduce(function (acc, item) { + return item[0] + acc; + }, ""); + var lastIndex = extra.lastIndexOf("\n"); + + return lastIndex === -1 ? this._position.column + extra.length : extra.length - 1 - lastIndex; + }; + + Buffer.prototype.getCurrentLine = function getCurrentLine() { + var extra = this._queue.reduce(function (acc, item) { + return item[0] + acc; + }, ""); + + var count = 0; + for (var i = 0; i < extra.length; i++) { + if (extra[i] === "\n") count++; + } + + return this._position.line + count; + }; + + return Buffer; +}(); + +exports.default = Buffer; +module.exports = exports["default"]; +},{"babel-runtime/helpers/classCallCheck":70,"trim-right":488}],33:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.File = File; +exports.Program = Program; +exports.BlockStatement = BlockStatement; +exports.Noop = Noop; +exports.Directive = Directive; + +var _types = require("./types"); + +Object.defineProperty(exports, "DirectiveLiteral", { + enumerable: true, + get: function get() { + return _types.StringLiteral; + } +}); +function File(node) { + this.print(node.program, node); +} + +function Program(node) { + this.printInnerComments(node, false); + + this.printSequence(node.directives, node); + if (node.directives && node.directives.length) this.newline(); + + this.printSequence(node.body, node); +} + +function BlockStatement(node) { + this.token("{"); + this.printInnerComments(node); + + var hasDirectives = node.directives && node.directives.length; + + if (node.body.length || hasDirectives) { + this.newline(); + + this.printSequence(node.directives, node, { indent: true }); + if (hasDirectives) this.newline(); + + this.printSequence(node.body, node, { indent: true }); + this.removeTrailingNewline(); + + this.source("end", node.loc); + + if (!this.endsWith("\n")) this.newline(); + + this.rightBrace(); + } else { + this.source("end", node.loc); + this.token("}"); + } +} + +function Noop() {} + +function Directive(node) { + this.print(node.value, node); + this.semicolon(); +} +},{"./types":42}],34:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.ClassDeclaration = ClassDeclaration; +exports.ClassBody = ClassBody; +exports.ClassProperty = ClassProperty; +exports.ClassMethod = ClassMethod; +function ClassDeclaration(node) { + this.printJoin(node.decorators, node); + this.word("class"); + + if (node.id) { + this.space(); + this.print(node.id, node); + } + + this.print(node.typeParameters, node); + + if (node.superClass) { + this.space(); + this.word("extends"); + this.space(); + this.print(node.superClass, node); + this.print(node.superTypeParameters, node); + } + + if (node.implements) { + this.space(); + this.word("implements"); + this.space(); + this.printList(node.implements, node); + } + + this.space(); + this.print(node.body, node); +} + +exports.ClassExpression = ClassDeclaration; +function ClassBody(node) { + this.token("{"); + this.printInnerComments(node); + if (node.body.length === 0) { + this.token("}"); + } else { + this.newline(); + + this.indent(); + this.printSequence(node.body, node); + this.dedent(); + + if (!this.endsWith("\n")) this.newline(); + + this.rightBrace(); + } +} + +function ClassProperty(node) { + this.printJoin(node.decorators, node); + + if (node.static) { + this.word("static"); + this.space(); + } + if (node.computed) { + this.token("["); + this.print(node.key, node); + this.token("]"); + } else { + this._variance(node); + this.print(node.key, node); + } + this.print(node.typeAnnotation, node); + if (node.value) { + this.space(); + this.token("="); + this.space(); + this.print(node.value, node); + } + this.semicolon(); +} + +function ClassMethod(node) { + this.printJoin(node.decorators, node); + + if (node.static) { + this.word("static"); + this.space(); + } + + if (node.kind === "constructorCall") { + this.word("call"); + this.space(); + } + + this._method(node); +} +},{}],35:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.LogicalExpression = exports.BinaryExpression = exports.AwaitExpression = exports.YieldExpression = undefined; +exports.UnaryExpression = UnaryExpression; +exports.DoExpression = DoExpression; +exports.ParenthesizedExpression = ParenthesizedExpression; +exports.UpdateExpression = UpdateExpression; +exports.ConditionalExpression = ConditionalExpression; +exports.NewExpression = NewExpression; +exports.SequenceExpression = SequenceExpression; +exports.ThisExpression = ThisExpression; +exports.Super = Super; +exports.Decorator = Decorator; +exports.CallExpression = CallExpression; +exports.Import = Import; +exports.EmptyStatement = EmptyStatement; +exports.ExpressionStatement = ExpressionStatement; +exports.AssignmentPattern = AssignmentPattern; +exports.AssignmentExpression = AssignmentExpression; +exports.BindExpression = BindExpression; +exports.MemberExpression = MemberExpression; +exports.MetaProperty = MetaProperty; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +var _node = require("../node"); + +var n = _interopRequireWildcard(_node); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function UnaryExpression(node) { + if (node.operator === "void" || node.operator === "delete" || node.operator === "typeof") { + this.word(node.operator); + this.space(); + } else { + this.token(node.operator); + } + + this.print(node.argument, node); +} + +function DoExpression(node) { + this.word("do"); + this.space(); + this.print(node.body, node); +} + +function ParenthesizedExpression(node) { + this.token("("); + this.print(node.expression, node); + this.token(")"); +} + +function UpdateExpression(node) { + if (node.prefix) { + this.token(node.operator); + this.print(node.argument, node); + } else { + this.print(node.argument, node); + this.token(node.operator); + } +} + +function ConditionalExpression(node) { + this.print(node.test, node); + this.space(); + this.token("?"); + this.space(); + this.print(node.consequent, node); + this.space(); + this.token(":"); + this.space(); + this.print(node.alternate, node); +} + +function NewExpression(node, parent) { + this.word("new"); + this.space(); + this.print(node.callee, node); + if (node.arguments.length === 0 && this.format.minified && !t.isCallExpression(parent, { callee: node }) && !t.isMemberExpression(parent) && !t.isNewExpression(parent)) return; + + this.token("("); + this.printList(node.arguments, node); + this.token(")"); +} + +function SequenceExpression(node) { + this.printList(node.expressions, node); +} + +function ThisExpression() { + this.word("this"); +} + +function Super() { + this.word("super"); +} + +function Decorator(node) { + this.token("@"); + this.print(node.expression, node); + this.newline(); +} + +function commaSeparatorNewline() { + this.token(","); + this.newline(); + + if (!this.endsWith("\n")) this.space(); +} + +function CallExpression(node) { + this.print(node.callee, node); + + this.token("("); + + var isPrettyCall = node._prettyCall; + + var separator = void 0; + if (isPrettyCall) { + separator = commaSeparatorNewline; + this.newline(); + this.indent(); + } + + this.printList(node.arguments, node, { separator: separator }); + + if (isPrettyCall) { + this.newline(); + this.dedent(); + } + + this.token(")"); +} + +function Import() { + this.word("import"); +} + +function buildYieldAwait(keyword) { + return function (node) { + this.word(keyword); + + if (node.delegate) { + this.token("*"); + } + + if (node.argument) { + this.space(); + var terminatorState = this.startTerminatorless(); + this.print(node.argument, node); + this.endTerminatorless(terminatorState); + } + }; +} + +var YieldExpression = exports.YieldExpression = buildYieldAwait("yield"); +var AwaitExpression = exports.AwaitExpression = buildYieldAwait("await"); + +function EmptyStatement() { + this.semicolon(true); +} + +function ExpressionStatement(node) { + this.print(node.expression, node); + this.semicolon(); +} + +function AssignmentPattern(node) { + this.print(node.left, node); + if (node.left.optional) this.token("?"); + this.print(node.left.typeAnnotation, node); + this.space(); + this.token("="); + this.space(); + this.print(node.right, node); +} + +function AssignmentExpression(node, parent) { + var parens = this.inForStatementInitCounter && node.operator === "in" && !n.needsParens(node, parent); + + if (parens) { + this.token("("); + } + + this.print(node.left, node); + + this.space(); + if (node.operator === "in" || node.operator === "instanceof") { + this.word(node.operator); + } else { + this.token(node.operator); + } + this.space(); + + this.print(node.right, node); + + if (parens) { + this.token(")"); + } +} + +function BindExpression(node) { + this.print(node.object, node); + this.token("::"); + this.print(node.callee, node); +} + +exports.BinaryExpression = AssignmentExpression; +exports.LogicalExpression = AssignmentExpression; +function MemberExpression(node) { + this.print(node.object, node); + + if (!node.computed && t.isMemberExpression(node.property)) { + throw new TypeError("Got a MemberExpression for MemberExpression property"); + } + + var computed = node.computed; + if (t.isLiteral(node.property) && typeof node.property.value === "number") { + computed = true; + } + + if (computed) { + this.token("["); + this.print(node.property, node); + this.token("]"); + } else { + this.token("."); + this.print(node.property, node); + } +} + +function MetaProperty(node) { + this.print(node.meta, node); + this.token("."); + this.print(node.property, node); +} +},{"../node":44,"babel-types":112}],36:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.AnyTypeAnnotation = AnyTypeAnnotation; +exports.ArrayTypeAnnotation = ArrayTypeAnnotation; +exports.BooleanTypeAnnotation = BooleanTypeAnnotation; +exports.BooleanLiteralTypeAnnotation = BooleanLiteralTypeAnnotation; +exports.NullLiteralTypeAnnotation = NullLiteralTypeAnnotation; +exports.DeclareClass = DeclareClass; +exports.DeclareFunction = DeclareFunction; +exports.DeclareInterface = DeclareInterface; +exports.DeclareModule = DeclareModule; +exports.DeclareModuleExports = DeclareModuleExports; +exports.DeclareTypeAlias = DeclareTypeAlias; +exports.DeclareVariable = DeclareVariable; +exports.ExistentialTypeParam = ExistentialTypeParam; +exports.FunctionTypeAnnotation = FunctionTypeAnnotation; +exports.FunctionTypeParam = FunctionTypeParam; +exports.InterfaceExtends = InterfaceExtends; +exports._interfaceish = _interfaceish; +exports._variance = _variance; +exports.InterfaceDeclaration = InterfaceDeclaration; +exports.IntersectionTypeAnnotation = IntersectionTypeAnnotation; +exports.MixedTypeAnnotation = MixedTypeAnnotation; +exports.EmptyTypeAnnotation = EmptyTypeAnnotation; +exports.NullableTypeAnnotation = NullableTypeAnnotation; + +var _types = require("./types"); + +Object.defineProperty(exports, "NumericLiteralTypeAnnotation", { + enumerable: true, + get: function get() { + return _types.NumericLiteral; + } +}); +Object.defineProperty(exports, "StringLiteralTypeAnnotation", { + enumerable: true, + get: function get() { + return _types.StringLiteral; + } +}); +exports.NumberTypeAnnotation = NumberTypeAnnotation; +exports.StringTypeAnnotation = StringTypeAnnotation; +exports.ThisTypeAnnotation = ThisTypeAnnotation; +exports.TupleTypeAnnotation = TupleTypeAnnotation; +exports.TypeofTypeAnnotation = TypeofTypeAnnotation; +exports.TypeAlias = TypeAlias; +exports.TypeAnnotation = TypeAnnotation; +exports.TypeParameter = TypeParameter; +exports.TypeParameterInstantiation = TypeParameterInstantiation; +exports.ObjectTypeAnnotation = ObjectTypeAnnotation; +exports.ObjectTypeCallProperty = ObjectTypeCallProperty; +exports.ObjectTypeIndexer = ObjectTypeIndexer; +exports.ObjectTypeProperty = ObjectTypeProperty; +exports.QualifiedTypeIdentifier = QualifiedTypeIdentifier; +exports.UnionTypeAnnotation = UnionTypeAnnotation; +exports.TypeCastExpression = TypeCastExpression; +exports.VoidTypeAnnotation = VoidTypeAnnotation; +function AnyTypeAnnotation() { + this.word("any"); +} + +function ArrayTypeAnnotation(node) { + this.print(node.elementType, node); + this.token("["); + this.token("]"); +} + +function BooleanTypeAnnotation() { + this.word("boolean"); +} + +function BooleanLiteralTypeAnnotation(node) { + this.word(node.value ? "true" : "false"); +} + +function NullLiteralTypeAnnotation() { + this.word("null"); +} + +function DeclareClass(node) { + this.word("declare"); + this.space(); + this.word("class"); + this.space(); + this._interfaceish(node); +} + +function DeclareFunction(node) { + this.word("declare"); + this.space(); + this.word("function"); + this.space(); + this.print(node.id, node); + this.print(node.id.typeAnnotation.typeAnnotation, node); + this.semicolon(); +} + +function DeclareInterface(node) { + this.word("declare"); + this.space(); + this.InterfaceDeclaration(node); +} + +function DeclareModule(node) { + this.word("declare"); + this.space(); + this.word("module"); + this.space(); + this.print(node.id, node); + this.space(); + this.print(node.body, node); +} + +function DeclareModuleExports(node) { + this.word("declare"); + this.space(); + this.word("module"); + this.token("."); + this.word("exports"); + this.print(node.typeAnnotation, node); +} + +function DeclareTypeAlias(node) { + this.word("declare"); + this.space(); + this.TypeAlias(node); +} + +function DeclareVariable(node) { + this.word("declare"); + this.space(); + this.word("var"); + this.space(); + this.print(node.id, node); + this.print(node.id.typeAnnotation, node); + this.semicolon(); +} + +function ExistentialTypeParam() { + this.token("*"); +} + +function FunctionTypeAnnotation(node, parent) { + this.print(node.typeParameters, node); + this.token("("); + this.printList(node.params, node); + + if (node.rest) { + if (node.params.length) { + this.token(","); + this.space(); + } + this.token("..."); + this.print(node.rest, node); + } + + this.token(")"); + + if (parent.type === "ObjectTypeCallProperty" || parent.type === "DeclareFunction") { + this.token(":"); + } else { + this.space(); + this.token("=>"); + } + + this.space(); + this.print(node.returnType, node); +} + +function FunctionTypeParam(node) { + this.print(node.name, node); + if (node.optional) this.token("?"); + this.token(":"); + this.space(); + this.print(node.typeAnnotation, node); +} + +function InterfaceExtends(node) { + this.print(node.id, node); + this.print(node.typeParameters, node); +} + +exports.ClassImplements = InterfaceExtends; +exports.GenericTypeAnnotation = InterfaceExtends; +function _interfaceish(node) { + this.print(node.id, node); + this.print(node.typeParameters, node); + if (node.extends.length) { + this.space(); + this.word("extends"); + this.space(); + this.printList(node.extends, node); + } + if (node.mixins && node.mixins.length) { + this.space(); + this.word("mixins"); + this.space(); + this.printList(node.mixins, node); + } + this.space(); + this.print(node.body, node); +} + +function _variance(node) { + if (node.variance === "plus") { + this.token("+"); + } else if (node.variance === "minus") { + this.token("-"); + } +} + +function InterfaceDeclaration(node) { + this.word("interface"); + this.space(); + this._interfaceish(node); +} + +function andSeparator() { + this.space(); + this.token("&"); + this.space(); +} + +function IntersectionTypeAnnotation(node) { + this.printJoin(node.types, node, { separator: andSeparator }); +} + +function MixedTypeAnnotation() { + this.word("mixed"); +} + +function EmptyTypeAnnotation() { + this.word("empty"); +} + +function NullableTypeAnnotation(node) { + this.token("?"); + this.print(node.typeAnnotation, node); +} + +function NumberTypeAnnotation() { + this.word("number"); +} + +function StringTypeAnnotation() { + this.word("string"); +} + +function ThisTypeAnnotation() { + this.word("this"); +} + +function TupleTypeAnnotation(node) { + this.token("["); + this.printList(node.types, node); + this.token("]"); +} + +function TypeofTypeAnnotation(node) { + this.word("typeof"); + this.space(); + this.print(node.argument, node); +} + +function TypeAlias(node) { + this.word("type"); + this.space(); + this.print(node.id, node); + this.print(node.typeParameters, node); + this.space(); + this.token("="); + this.space(); + this.print(node.right, node); + this.semicolon(); +} + +function TypeAnnotation(node) { + this.token(":"); + this.space(); + if (node.optional) this.token("?"); + this.print(node.typeAnnotation, node); +} + +function TypeParameter(node) { + this._variance(node); + + this.word(node.name); + + if (node.bound) { + this.print(node.bound, node); + } + + if (node.default) { + this.space(); + this.token("="); + this.space(); + this.print(node.default, node); + } +} + +function TypeParameterInstantiation(node) { + this.token("<"); + this.printList(node.params, node, {}); + this.token(">"); +} + +exports.TypeParameterDeclaration = TypeParameterInstantiation; +function ObjectTypeAnnotation(node) { + var _this = this; + + if (node.exact) { + this.token("{|"); + } else { + this.token("{"); + } + + var props = node.properties.concat(node.callProperties, node.indexers); + + if (props.length) { + this.space(); + + this.printJoin(props, node, { + addNewlines: function addNewlines(leading) { + if (leading && !props[0]) return 1; + }, + + indent: true, + statement: true, + iterator: function iterator() { + if (props.length !== 1) { + if (_this.format.flowCommaSeparator) { + _this.token(","); + } else { + _this.semicolon(); + } + _this.space(); + } + } + }); + + this.space(); + } + + if (node.exact) { + this.token("|}"); + } else { + this.token("}"); + } +} + +function ObjectTypeCallProperty(node) { + if (node.static) { + this.word("static"); + this.space(); + } + this.print(node.value, node); +} + +function ObjectTypeIndexer(node) { + if (node.static) { + this.word("static"); + this.space(); + } + this._variance(node); + this.token("["); + this.print(node.id, node); + this.token(":"); + this.space(); + this.print(node.key, node); + this.token("]"); + this.token(":"); + this.space(); + this.print(node.value, node); +} + +function ObjectTypeProperty(node) { + if (node.static) { + this.word("static"); + this.space(); + } + this._variance(node); + this.print(node.key, node); + if (node.optional) this.token("?"); + this.token(":"); + this.space(); + this.print(node.value, node); +} + +function QualifiedTypeIdentifier(node) { + this.print(node.qualification, node); + this.token("."); + this.print(node.id, node); +} + +function orSeparator() { + this.space(); + this.token("|"); + this.space(); +} + +function UnionTypeAnnotation(node) { + this.printJoin(node.types, node, { separator: orSeparator }); +} + +function TypeCastExpression(node) { + this.token("("); + this.print(node.expression, node); + this.print(node.typeAnnotation, node); + this.token(")"); +} + +function VoidTypeAnnotation() { + this.word("void"); +} +},{"./types":42}],37:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.JSXAttribute = JSXAttribute; +exports.JSXIdentifier = JSXIdentifier; +exports.JSXNamespacedName = JSXNamespacedName; +exports.JSXMemberExpression = JSXMemberExpression; +exports.JSXSpreadAttribute = JSXSpreadAttribute; +exports.JSXExpressionContainer = JSXExpressionContainer; +exports.JSXSpreadChild = JSXSpreadChild; +exports.JSXText = JSXText; +exports.JSXElement = JSXElement; +exports.JSXOpeningElement = JSXOpeningElement; +exports.JSXClosingElement = JSXClosingElement; +exports.JSXEmptyExpression = JSXEmptyExpression; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function JSXAttribute(node) { + this.print(node.name, node); + if (node.value) { + this.token("="); + this.print(node.value, node); + } +} + +function JSXIdentifier(node) { + this.word(node.name); +} + +function JSXNamespacedName(node) { + this.print(node.namespace, node); + this.token(":"); + this.print(node.name, node); +} + +function JSXMemberExpression(node) { + this.print(node.object, node); + this.token("."); + this.print(node.property, node); +} + +function JSXSpreadAttribute(node) { + this.token("{"); + this.token("..."); + this.print(node.argument, node); + this.token("}"); +} + +function JSXExpressionContainer(node) { + this.token("{"); + this.print(node.expression, node); + this.token("}"); +} + +function JSXSpreadChild(node) { + this.token("{"); + this.token("..."); + this.print(node.expression, node); + this.token("}"); +} + +function JSXText(node) { + this.token(node.value); +} + +function JSXElement(node) { + var open = node.openingElement; + this.print(open, node); + if (open.selfClosing) return; + + this.indent(); + for (var _iterator = node.children, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var child = _ref; + + this.print(child, node); + } + this.dedent(); + + this.print(node.closingElement, node); +} + +function spaceSeparator() { + this.space(); +} + +function JSXOpeningElement(node) { + this.token("<"); + this.print(node.name, node); + if (node.attributes.length > 0) { + this.space(); + this.printJoin(node.attributes, node, { separator: spaceSeparator }); + } + if (node.selfClosing) { + this.space(); + this.token("/>"); + } else { + this.token(">"); + } +} + +function JSXClosingElement(node) { + this.token(""); +} + +function JSXEmptyExpression() {} +},{"babel-runtime/core-js/get-iterator":56}],38:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.FunctionDeclaration = undefined; +exports._params = _params; +exports._method = _method; +exports.FunctionExpression = FunctionExpression; +exports.ArrowFunctionExpression = ArrowFunctionExpression; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _params(node) { + var _this = this; + + this.print(node.typeParameters, node); + this.token("("); + this.printList(node.params, node, { + iterator: function iterator(node) { + if (node.optional) _this.token("?"); + _this.print(node.typeAnnotation, node); + } + }); + this.token(")"); + + if (node.returnType) { + this.print(node.returnType, node); + } +} + +function _method(node) { + var kind = node.kind; + var key = node.key; + + if (kind === "method" || kind === "init") { + if (node.generator) { + this.token("*"); + } + } + + if (kind === "get" || kind === "set") { + this.word(kind); + this.space(); + } + + if (node.async) { + this.word("async"); + this.space(); + } + + if (node.computed) { + this.token("["); + this.print(key, node); + this.token("]"); + } else { + this.print(key, node); + } + + this._params(node); + this.space(); + this.print(node.body, node); +} + +function FunctionExpression(node) { + if (node.async) { + this.word("async"); + this.space(); + } + this.word("function"); + if (node.generator) this.token("*"); + + if (node.id) { + this.space(); + this.print(node.id, node); + } else { + this.space(); + } + + this._params(node); + this.space(); + this.print(node.body, node); +} + +exports.FunctionDeclaration = FunctionExpression; +function ArrowFunctionExpression(node) { + if (node.async) { + this.word("async"); + this.space(); + } + + var firstParam = node.params[0]; + + if (node.params.length === 1 && t.isIdentifier(firstParam) && !hasTypes(node, firstParam)) { + this.print(firstParam, node); + } else { + this._params(node); + } + + this.space(); + this.token("=>"); + this.space(); + + this.print(node.body, node); +} + +function hasTypes(node, param) { + return node.typeParameters || node.returnType || param.typeAnnotation || param.optional || param.trailingComments; +} +},{"babel-types":112}],39:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.ImportSpecifier = ImportSpecifier; +exports.ImportDefaultSpecifier = ImportDefaultSpecifier; +exports.ExportDefaultSpecifier = ExportDefaultSpecifier; +exports.ExportSpecifier = ExportSpecifier; +exports.ExportNamespaceSpecifier = ExportNamespaceSpecifier; +exports.ExportAllDeclaration = ExportAllDeclaration; +exports.ExportNamedDeclaration = ExportNamedDeclaration; +exports.ExportDefaultDeclaration = ExportDefaultDeclaration; +exports.ImportDeclaration = ImportDeclaration; +exports.ImportNamespaceSpecifier = ImportNamespaceSpecifier; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function ImportSpecifier(node) { + if (node.importKind === "type" || node.importKind === "typeof") { + this.word(node.importKind); + this.space(); + } + + this.print(node.imported, node); + if (node.local && node.local.name !== node.imported.name) { + this.space(); + this.word("as"); + this.space(); + this.print(node.local, node); + } +} + +function ImportDefaultSpecifier(node) { + this.print(node.local, node); +} + +function ExportDefaultSpecifier(node) { + this.print(node.exported, node); +} + +function ExportSpecifier(node) { + this.print(node.local, node); + if (node.exported && node.local.name !== node.exported.name) { + this.space(); + this.word("as"); + this.space(); + this.print(node.exported, node); + } +} + +function ExportNamespaceSpecifier(node) { + this.token("*"); + this.space(); + this.word("as"); + this.space(); + this.print(node.exported, node); +} + +function ExportAllDeclaration(node) { + this.word("export"); + this.space(); + this.token("*"); + if (node.exported) { + this.space(); + this.word("as"); + this.space(); + this.print(node.exported, node); + } + this.space(); + this.word("from"); + this.space(); + this.print(node.source, node); + this.semicolon(); +} + +function ExportNamedDeclaration() { + this.word("export"); + this.space(); + ExportDeclaration.apply(this, arguments); +} + +function ExportDefaultDeclaration() { + this.word("export"); + this.space(); + this.word("default"); + this.space(); + ExportDeclaration.apply(this, arguments); +} + +function ExportDeclaration(node) { + if (node.declaration) { + var declar = node.declaration; + this.print(declar, node); + if (!t.isStatement(declar)) this.semicolon(); + } else { + if (node.exportKind === "type") { + this.word("type"); + this.space(); + } + + var specifiers = node.specifiers.slice(0); + + var hasSpecial = false; + while (true) { + var first = specifiers[0]; + if (t.isExportDefaultSpecifier(first) || t.isExportNamespaceSpecifier(first)) { + hasSpecial = true; + this.print(specifiers.shift(), node); + if (specifiers.length) { + this.token(","); + this.space(); + } + } else { + break; + } + } + + if (specifiers.length || !specifiers.length && !hasSpecial) { + this.token("{"); + if (specifiers.length) { + this.space(); + this.printList(specifiers, node); + this.space(); + } + this.token("}"); + } + + if (node.source) { + this.space(); + this.word("from"); + this.space(); + this.print(node.source, node); + } + + this.semicolon(); + } +} + +function ImportDeclaration(node) { + this.word("import"); + this.space(); + + if (node.importKind === "type" || node.importKind === "typeof") { + this.word(node.importKind); + this.space(); + } + + var specifiers = node.specifiers.slice(0); + if (specifiers && specifiers.length) { + while (true) { + var first = specifiers[0]; + if (t.isImportDefaultSpecifier(first) || t.isImportNamespaceSpecifier(first)) { + this.print(specifiers.shift(), node); + if (specifiers.length) { + this.token(","); + this.space(); + } + } else { + break; + } + } + + if (specifiers.length) { + this.token("{"); + this.space(); + this.printList(specifiers, node); + this.space(); + this.token("}"); + } + + this.space(); + this.word("from"); + this.space(); + } + + this.print(node.source, node); + this.semicolon(); +} + +function ImportNamespaceSpecifier(node) { + this.token("*"); + this.space(); + this.word("as"); + this.space(); + this.print(node.local, node); +} +},{"babel-types":112}],40:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.ThrowStatement = exports.BreakStatement = exports.ReturnStatement = exports.ContinueStatement = exports.ForAwaitStatement = exports.ForOfStatement = exports.ForInStatement = undefined; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.WithStatement = WithStatement; +exports.IfStatement = IfStatement; +exports.ForStatement = ForStatement; +exports.WhileStatement = WhileStatement; +exports.DoWhileStatement = DoWhileStatement; +exports.LabeledStatement = LabeledStatement; +exports.TryStatement = TryStatement; +exports.CatchClause = CatchClause; +exports.SwitchStatement = SwitchStatement; +exports.SwitchCase = SwitchCase; +exports.DebuggerStatement = DebuggerStatement; +exports.VariableDeclaration = VariableDeclaration; +exports.VariableDeclarator = VariableDeclarator; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function WithStatement(node) { + this.word("with"); + this.space(); + this.token("("); + this.print(node.object, node); + this.token(")"); + this.printBlock(node); +} + +function IfStatement(node) { + this.word("if"); + this.space(); + this.token("("); + this.print(node.test, node); + this.token(")"); + this.space(); + + var needsBlock = node.alternate && t.isIfStatement(getLastStatement(node.consequent)); + if (needsBlock) { + this.token("{"); + this.newline(); + this.indent(); + } + + this.printAndIndentOnComments(node.consequent, node); + + if (needsBlock) { + this.dedent(); + this.newline(); + this.token("}"); + } + + if (node.alternate) { + if (this.endsWith("}")) this.space(); + this.word("else"); + this.space(); + this.printAndIndentOnComments(node.alternate, node); + } +} + +function getLastStatement(statement) { + if (!t.isStatement(statement.body)) return statement; + return getLastStatement(statement.body); +} + +function ForStatement(node) { + this.word("for"); + this.space(); + this.token("("); + + this.inForStatementInitCounter++; + this.print(node.init, node); + this.inForStatementInitCounter--; + this.token(";"); + + if (node.test) { + this.space(); + this.print(node.test, node); + } + this.token(";"); + + if (node.update) { + this.space(); + this.print(node.update, node); + } + + this.token(")"); + this.printBlock(node); +} + +function WhileStatement(node) { + this.word("while"); + this.space(); + this.token("("); + this.print(node.test, node); + this.token(")"); + this.printBlock(node); +} + +var buildForXStatement = function buildForXStatement(op) { + return function (node) { + this.word("for"); + this.space(); + if (op === "await") { + this.word("await"); + this.space(); + op = "of"; + } + this.token("("); + + this.print(node.left, node); + this.space(); + this.word(op); + this.space(); + this.print(node.right, node); + this.token(")"); + this.printBlock(node); + }; +}; + +var ForInStatement = exports.ForInStatement = buildForXStatement("in"); +var ForOfStatement = exports.ForOfStatement = buildForXStatement("of"); +var ForAwaitStatement = exports.ForAwaitStatement = buildForXStatement("await"); + +function DoWhileStatement(node) { + this.word("do"); + this.space(); + this.print(node.body, node); + this.space(); + this.word("while"); + this.space(); + this.token("("); + this.print(node.test, node); + this.token(")"); + this.semicolon(); +} + +function buildLabelStatement(prefix) { + var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "label"; + + return function (node) { + this.word(prefix); + + var label = node[key]; + if (label) { + this.space(); + + var terminatorState = this.startTerminatorless(); + this.print(label, node); + this.endTerminatorless(terminatorState); + } + + this.semicolon(); + }; +} + +var ContinueStatement = exports.ContinueStatement = buildLabelStatement("continue"); +var ReturnStatement = exports.ReturnStatement = buildLabelStatement("return", "argument"); +var BreakStatement = exports.BreakStatement = buildLabelStatement("break"); +var ThrowStatement = exports.ThrowStatement = buildLabelStatement("throw", "argument"); + +function LabeledStatement(node) { + this.print(node.label, node); + this.token(":"); + this.space(); + this.print(node.body, node); +} + +function TryStatement(node) { + this.word("try"); + this.space(); + this.print(node.block, node); + this.space(); + + if (node.handlers) { + this.print(node.handlers[0], node); + } else { + this.print(node.handler, node); + } + + if (node.finalizer) { + this.space(); + this.word("finally"); + this.space(); + this.print(node.finalizer, node); + } +} + +function CatchClause(node) { + this.word("catch"); + this.space(); + this.token("("); + this.print(node.param, node); + this.token(")"); + this.space(); + this.print(node.body, node); +} + +function SwitchStatement(node) { + this.word("switch"); + this.space(); + this.token("("); + this.print(node.discriminant, node); + this.token(")"); + this.space(); + this.token("{"); + + this.printSequence(node.cases, node, { + indent: true, + addNewlines: function addNewlines(leading, cas) { + if (!leading && node.cases[node.cases.length - 1] === cas) return -1; + } + }); + + this.token("}"); +} + +function SwitchCase(node) { + if (node.test) { + this.word("case"); + this.space(); + this.print(node.test, node); + this.token(":"); + } else { + this.word("default"); + this.token(":"); + } + + if (node.consequent.length) { + this.newline(); + this.printSequence(node.consequent, node, { indent: true }); + } +} + +function DebuggerStatement() { + this.word("debugger"); + this.semicolon(); +} + +function variableDeclarationIdent() { + this.token(","); + this.newline(); + if (this.endsWith("\n")) for (var i = 0; i < 4; i++) { + this.space(true); + } +} + +function constDeclarationIdent() { + this.token(","); + this.newline(); + if (this.endsWith("\n")) for (var i = 0; i < 6; i++) { + this.space(true); + } +} + +function VariableDeclaration(node, parent) { + this.word(node.kind); + this.space(); + + var hasInits = false; + + if (!t.isFor(parent)) { + for (var _iterator = node.declarations, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var declar = _ref; + + if (declar.init) { + hasInits = true; + } + } + } + + var separator = void 0; + if (hasInits) { + separator = node.kind === "const" ? constDeclarationIdent : variableDeclarationIdent; + } + + this.printList(node.declarations, node, { separator: separator }); + + if (t.isFor(parent)) { + if (parent.left === node || parent.init === node) return; + } + + this.semicolon(); +} + +function VariableDeclarator(node) { + this.print(node.id, node); + this.print(node.id.typeAnnotation, node); + if (node.init) { + this.space(); + this.token("="); + this.space(); + this.print(node.init, node); + } +} +},{"babel-runtime/core-js/get-iterator":56,"babel-types":112}],41:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.TaggedTemplateExpression = TaggedTemplateExpression; +exports.TemplateElement = TemplateElement; +exports.TemplateLiteral = TemplateLiteral; +function TaggedTemplateExpression(node) { + this.print(node.tag, node); + this.print(node.quasi, node); +} + +function TemplateElement(node, parent) { + var isFirst = parent.quasis[0] === node; + var isLast = parent.quasis[parent.quasis.length - 1] === node; + + var value = (isFirst ? "`" : "}") + node.value.raw + (isLast ? "`" : "${"); + + this.token(value); +} + +function TemplateLiteral(node) { + var quasis = node.quasis; + + for (var i = 0; i < quasis.length; i++) { + this.print(quasis[i], node); + + if (i + 1 < quasis.length) { + this.print(node.expressions[i], node); + } + } +} +},{}],42:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.ArrayPattern = exports.ObjectPattern = exports.RestProperty = exports.SpreadProperty = exports.SpreadElement = undefined; +exports.Identifier = Identifier; +exports.RestElement = RestElement; +exports.ObjectExpression = ObjectExpression; +exports.ObjectMethod = ObjectMethod; +exports.ObjectProperty = ObjectProperty; +exports.ArrayExpression = ArrayExpression; +exports.RegExpLiteral = RegExpLiteral; +exports.BooleanLiteral = BooleanLiteral; +exports.NullLiteral = NullLiteral; +exports.NumericLiteral = NumericLiteral; +exports.StringLiteral = StringLiteral; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +var _jsesc = require("jsesc"); + +var _jsesc2 = _interopRequireDefault(_jsesc); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function Identifier(node) { + if (node.variance) { + if (node.variance === "plus") { + this.token("+"); + } else if (node.variance === "minus") { + this.token("-"); + } + } + + this.word(node.name); +} + +function RestElement(node) { + this.token("..."); + this.print(node.argument, node); +} + +exports.SpreadElement = RestElement; +exports.SpreadProperty = RestElement; +exports.RestProperty = RestElement; +function ObjectExpression(node) { + var props = node.properties; + + this.token("{"); + this.printInnerComments(node); + + if (props.length) { + this.space(); + this.printList(props, node, { indent: true, statement: true }); + this.space(); + } + + this.token("}"); +} + +exports.ObjectPattern = ObjectExpression; +function ObjectMethod(node) { + this.printJoin(node.decorators, node); + this._method(node); +} + +function ObjectProperty(node) { + this.printJoin(node.decorators, node); + + if (node.computed) { + this.token("["); + this.print(node.key, node); + this.token("]"); + } else { + if (t.isAssignmentPattern(node.value) && t.isIdentifier(node.key) && node.key.name === node.value.left.name) { + this.print(node.value, node); + return; + } + + this.print(node.key, node); + + if (node.shorthand && t.isIdentifier(node.key) && t.isIdentifier(node.value) && node.key.name === node.value.name) { + return; + } + } + + this.token(":"); + this.space(); + this.print(node.value, node); +} + +function ArrayExpression(node) { + var elems = node.elements; + var len = elems.length; + + this.token("["); + this.printInnerComments(node); + + for (var i = 0; i < elems.length; i++) { + var elem = elems[i]; + if (elem) { + if (i > 0) this.space(); + this.print(elem, node); + if (i < len - 1) this.token(","); + } else { + this.token(","); + } + } + + this.token("]"); +} + +exports.ArrayPattern = ArrayExpression; +function RegExpLiteral(node) { + this.word("/" + node.pattern + "/" + node.flags); +} + +function BooleanLiteral(node) { + this.word(node.value ? "true" : "false"); +} + +function NullLiteral() { + this.word("null"); +} + +function NumericLiteral(node) { + var raw = this.getPossibleRaw(node); + var value = node.value + ""; + if (raw == null) { + this.number(value); + } else if (this.format.minified) { + this.number(raw.length < value.length ? raw : value); + } else { + this.number(raw); + } +} + +function StringLiteral(node, parent) { + var raw = this.getPossibleRaw(node); + if (!this.format.minified && raw != null) { + this.token(raw); + return; + } + + var opts = { + quotes: t.isJSX(parent) ? "double" : this.format.quotes, + wrap: true + }; + if (this.format.jsonCompatibleStrings) { + opts.json = true; + } + var val = (0, _jsesc2.default)(node.value, opts); + + return this.token(val); +} +},{"babel-types":112,"jsesc":249}],43:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.CodeGenerator = undefined; + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _possibleConstructorReturn2 = require("babel-runtime/helpers/possibleConstructorReturn"); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require("babel-runtime/helpers/inherits"); + +var _inherits3 = _interopRequireDefault(_inherits2); + +exports.default = function (ast, opts, code) { + var gen = new Generator(ast, opts, code); + return gen.generate(); +}; + +var _detectIndent = require("detect-indent"); + +var _detectIndent2 = _interopRequireDefault(_detectIndent); + +var _sourceMap = require("./source-map"); + +var _sourceMap2 = _interopRequireDefault(_sourceMap); + +var _babelMessages = require("babel-messages"); + +var messages = _interopRequireWildcard(_babelMessages); + +var _printer = require("./printer"); + +var _printer2 = _interopRequireDefault(_printer); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var Generator = function (_Printer) { + (0, _inherits3.default)(Generator, _Printer); + + function Generator(ast, opts, code) { + (0, _classCallCheck3.default)(this, Generator); + + opts = opts || {}; + + var tokens = ast.tokens || []; + var format = normalizeOptions(code, opts, tokens); + var map = opts.sourceMaps ? new _sourceMap2.default(opts, code) : null; + + var _this = (0, _possibleConstructorReturn3.default)(this, _Printer.call(this, format, map, tokens)); + + _this.ast = ast; + return _this; + } + + Generator.prototype.generate = function generate() { + return _Printer.prototype.generate.call(this, this.ast); + }; + + return Generator; +}(_printer2.default); + +function normalizeOptions(code, opts, tokens) { + var style = " "; + if (code && typeof code === "string") { + var indent = (0, _detectIndent2.default)(code).indent; + if (indent && indent !== " ") style = indent; + } + + var format = { + auxiliaryCommentBefore: opts.auxiliaryCommentBefore, + auxiliaryCommentAfter: opts.auxiliaryCommentAfter, + shouldPrintComment: opts.shouldPrintComment, + retainLines: opts.retainLines, + retainFunctionParens: opts.retainFunctionParens, + comments: opts.comments == null || opts.comments, + compact: opts.compact, + minified: opts.minified, + concise: opts.concise, + quotes: opts.quotes || findCommonStringDelimiter(code, tokens), + jsonCompatibleStrings: opts.jsonCompatibleStrings, + indent: { + adjustMultilineComment: true, + style: style, + base: 0 + }, + flowCommaSeparator: opts.flowCommaSeparator + }; + + if (format.minified) { + format.compact = true; + + format.shouldPrintComment = format.shouldPrintComment || function () { + return format.comments; + }; + } else { + format.shouldPrintComment = format.shouldPrintComment || function (value) { + return format.comments || value.indexOf("@license") >= 0 || value.indexOf("@preserve") >= 0; + }; + } + + if (format.compact === "auto") { + format.compact = code.length > 500000; + + if (format.compact) { + console.error("[BABEL] " + messages.get("codeGeneratorDeopt", opts.filename, "500KB")); + } + } + + if (format.compact) { + format.indent.adjustMultilineComment = false; + } + + return format; +} + +function findCommonStringDelimiter(code, tokens) { + var DEFAULT_STRING_DELIMITER = "double"; + if (!code) { + return DEFAULT_STRING_DELIMITER; + } + + var occurences = { + single: 0, + double: 0 + }; + + var checked = 0; + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (token.type.label !== "string") continue; + + var raw = code.slice(token.start, token.end); + if (raw[0] === "'") { + occurences.single++; + } else { + occurences.double++; + } + + checked++; + if (checked >= 3) break; + } + if (occurences.single > occurences.double) { + return "single"; + } else { + return "double"; + } +} + +var CodeGenerator = exports.CodeGenerator = function () { + function CodeGenerator(ast, opts, code) { + (0, _classCallCheck3.default)(this, CodeGenerator); + + this._generator = new Generator(ast, opts, code); + } + + CodeGenerator.prototype.generate = function generate() { + return this._generator.generate(); + }; + + return CodeGenerator; +}(); +},{"./printer":47,"./source-map":48,"babel-messages":53,"babel-runtime/helpers/classCallCheck":70,"babel-runtime/helpers/inherits":71,"babel-runtime/helpers/possibleConstructorReturn":73,"detect-indent":235}],44:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _keys = require("babel-runtime/core-js/object/keys"); + +var _keys2 = _interopRequireDefault(_keys); + +exports.needsWhitespace = needsWhitespace; +exports.needsWhitespaceBefore = needsWhitespaceBefore; +exports.needsWhitespaceAfter = needsWhitespaceAfter; +exports.needsParens = needsParens; + +var _whitespace = require("./whitespace"); + +var _whitespace2 = _interopRequireDefault(_whitespace); + +var _parentheses = require("./parentheses"); + +var parens = _interopRequireWildcard(_parentheses); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function expandAliases(obj) { + var newObj = {}; + + function add(type, func) { + var fn = newObj[type]; + newObj[type] = fn ? function (node, parent, stack) { + var result = fn(node, parent, stack); + + return result == null ? func(node, parent, stack) : result; + } : func; + } + + for (var _iterator = (0, _keys2.default)(obj), _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var type = _ref; + + + var aliases = t.FLIPPED_ALIAS_KEYS[type]; + if (aliases) { + for (var _iterator2 = aliases, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var alias = _ref2; + + add(alias, obj[type]); + } + } else { + add(type, obj[type]); + } + } + + return newObj; +} + +var expandedParens = expandAliases(parens); +var expandedWhitespaceNodes = expandAliases(_whitespace2.default.nodes); +var expandedWhitespaceList = expandAliases(_whitespace2.default.list); + +function find(obj, node, parent, printStack) { + var fn = obj[node.type]; + return fn ? fn(node, parent, printStack) : null; +} + +function isOrHasCallExpression(node) { + if (t.isCallExpression(node)) { + return true; + } + + if (t.isMemberExpression(node)) { + return isOrHasCallExpression(node.object) || !node.computed && isOrHasCallExpression(node.property); + } else { + return false; + } +} + +function needsWhitespace(node, parent, type) { + if (!node) return 0; + + if (t.isExpressionStatement(node)) { + node = node.expression; + } + + var linesInfo = find(expandedWhitespaceNodes, node, parent); + + if (!linesInfo) { + var items = find(expandedWhitespaceList, node, parent); + if (items) { + for (var i = 0; i < items.length; i++) { + linesInfo = needsWhitespace(items[i], node, type); + if (linesInfo) break; + } + } + } + + return linesInfo && linesInfo[type] || 0; +} + +function needsWhitespaceBefore(node, parent) { + return needsWhitespace(node, parent, "before"); +} + +function needsWhitespaceAfter(node, parent) { + return needsWhitespace(node, parent, "after"); +} + +function needsParens(node, parent, printStack) { + if (!parent) return false; + + if (t.isNewExpression(parent) && parent.callee === node) { + if (isOrHasCallExpression(node)) return true; + } + + return find(expandedParens, node, parent, printStack); +} +},{"./parentheses":45,"./whitespace":46,"babel-runtime/core-js/get-iterator":56,"babel-runtime/core-js/object/keys":63,"babel-types":112}],45:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.AwaitExpression = exports.FunctionTypeAnnotation = undefined; +exports.NullableTypeAnnotation = NullableTypeAnnotation; +exports.UpdateExpression = UpdateExpression; +exports.ObjectExpression = ObjectExpression; +exports.Binary = Binary; +exports.BinaryExpression = BinaryExpression; +exports.SequenceExpression = SequenceExpression; +exports.YieldExpression = YieldExpression; +exports.ClassExpression = ClassExpression; +exports.UnaryLike = UnaryLike; +exports.FunctionExpression = FunctionExpression; +exports.ArrowFunctionExpression = ArrowFunctionExpression; +exports.ConditionalExpression = ConditionalExpression; +exports.AssignmentExpression = AssignmentExpression; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var PRECEDENCE = { + "||": 0, + "&&": 1, + "|": 2, + "^": 3, + "&": 4, + "==": 5, + "===": 5, + "!=": 5, + "!==": 5, + "<": 6, + ">": 6, + "<=": 6, + ">=": 6, + in: 6, + instanceof: 6, + ">>": 7, + "<<": 7, + ">>>": 7, + "+": 8, + "-": 8, + "*": 9, + "/": 9, + "%": 9, + "**": 10 +}; + +function NullableTypeAnnotation(node, parent) { + return t.isArrayTypeAnnotation(parent); +} + +exports.FunctionTypeAnnotation = NullableTypeAnnotation; +function UpdateExpression(node, parent) { + if (t.isMemberExpression(parent) && parent.object === node) { + return true; + } + + return false; +} + +function ObjectExpression(node, parent, printStack) { + return isFirstInStatement(printStack, { considerArrow: true }); +} + +function Binary(node, parent) { + if ((t.isCallExpression(parent) || t.isNewExpression(parent)) && parent.callee === node) { + return true; + } + + if (t.isUnaryLike(parent)) { + return true; + } + + if (t.isMemberExpression(parent) && parent.object === node) { + return true; + } + + if (t.isBinary(parent)) { + var parentOp = parent.operator; + var parentPos = PRECEDENCE[parentOp]; + + var nodeOp = node.operator; + var nodePos = PRECEDENCE[nodeOp]; + + if (parentPos > nodePos) { + return true; + } + + if (parentPos === nodePos && parent.right === node && !t.isLogicalExpression(parent)) { + return true; + } + } + + return false; +} + +function BinaryExpression(node, parent) { + if (node.operator === "in") { + if (t.isVariableDeclarator(parent)) { + return true; + } + + if (t.isFor(parent)) { + return true; + } + } + + return false; +} + +function SequenceExpression(node, parent) { + if (t.isForStatement(parent)) { + return false; + } + + if (t.isExpressionStatement(parent) && parent.expression === node) { + return false; + } + + if (t.isReturnStatement(parent)) { + return false; + } + + if (t.isThrowStatement(parent)) { + return false; + } + + if (t.isSwitchStatement(parent) && parent.discriminant === node) { + return false; + } + + if (t.isWhileStatement(parent) && parent.test === node) { + return false; + } + + if (t.isIfStatement(parent) && parent.test === node) { + return false; + } + + if (t.isForInStatement(parent) && parent.right === node) { + return false; + } + + return true; +} + +function YieldExpression(node, parent) { + return t.isBinary(parent) || t.isUnaryLike(parent) || t.isCallExpression(parent) || t.isMemberExpression(parent) || t.isNewExpression(parent) || t.isConditionalExpression(parent) && node === parent.test; +} + +exports.AwaitExpression = YieldExpression; +function ClassExpression(node, parent, printStack) { + return isFirstInStatement(printStack, { considerDefaultExports: true }); +} + +function UnaryLike(node, parent) { + if (t.isMemberExpression(parent, { object: node })) { + return true; + } + + if (t.isCallExpression(parent, { callee: node }) || t.isNewExpression(parent, { callee: node })) { + return true; + } + + return false; +} + +function FunctionExpression(node, parent, printStack) { + return isFirstInStatement(printStack, { considerDefaultExports: true }); +} + +function ArrowFunctionExpression(node, parent) { + if (t.isExportDeclaration(parent) || t.isBinaryExpression(parent) || t.isLogicalExpression(parent) || t.isUnaryExpression(parent) || t.isTaggedTemplateExpression(parent)) { + return true; + } + + return UnaryLike(node, parent); +} + +function ConditionalExpression(node, parent) { + if (t.isUnaryLike(parent)) { + return true; + } + + if (t.isBinary(parent)) { + return true; + } + + if (t.isConditionalExpression(parent, { test: node })) { + return true; + } + + if (t.isAwaitExpression(parent)) { + return true; + } + + return UnaryLike(node, parent); +} + +function AssignmentExpression(node) { + if (t.isObjectPattern(node.left)) { + return true; + } else { + return ConditionalExpression.apply(undefined, arguments); + } +} + +function isFirstInStatement(printStack) { + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$considerArrow = _ref.considerArrow, + considerArrow = _ref$considerArrow === undefined ? false : _ref$considerArrow, + _ref$considerDefaultE = _ref.considerDefaultExports, + considerDefaultExports = _ref$considerDefaultE === undefined ? false : _ref$considerDefaultE; + + var i = printStack.length - 1; + var node = printStack[i]; + i--; + var parent = printStack[i]; + while (i > 0) { + if (t.isExpressionStatement(parent, { expression: node })) { + return true; + } + + if (t.isTaggedTemplateExpression(parent)) { + return true; + } + + if (considerDefaultExports && t.isExportDefaultDeclaration(parent, { declaration: node })) { + return true; + } + + if (considerArrow && t.isArrowFunctionExpression(parent, { body: node })) { + return true; + } + + if (t.isCallExpression(parent, { callee: node }) || t.isSequenceExpression(parent) && parent.expressions[0] === node || t.isMemberExpression(parent, { object: node }) || t.isConditional(parent, { test: node }) || t.isBinary(parent, { left: node }) || t.isAssignmentExpression(parent, { left: node })) { + node = parent; + i--; + parent = printStack[i]; + } else { + return false; + } + } + + return false; +} +},{"babel-types":112}],46:[function(require,module,exports){ +"use strict"; + +var _map = require("lodash/map"); + +var _map2 = _interopRequireDefault(_map); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function crawl(node) { + var state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (t.isMemberExpression(node)) { + crawl(node.object, state); + if (node.computed) crawl(node.property, state); + } else if (t.isBinary(node) || t.isAssignmentExpression(node)) { + crawl(node.left, state); + crawl(node.right, state); + } else if (t.isCallExpression(node)) { + state.hasCall = true; + crawl(node.callee, state); + } else if (t.isFunction(node)) { + state.hasFunction = true; + } else if (t.isIdentifier(node)) { + state.hasHelper = state.hasHelper || isHelper(node.callee); + } + + return state; +} + +function isHelper(node) { + if (t.isMemberExpression(node)) { + return isHelper(node.object) || isHelper(node.property); + } else if (t.isIdentifier(node)) { + return node.name === "require" || node.name[0] === "_"; + } else if (t.isCallExpression(node)) { + return isHelper(node.callee); + } else if (t.isBinary(node) || t.isAssignmentExpression(node)) { + return t.isIdentifier(node.left) && isHelper(node.left) || isHelper(node.right); + } else { + return false; + } +} + +function isType(node) { + return t.isLiteral(node) || t.isObjectExpression(node) || t.isArrayExpression(node) || t.isIdentifier(node) || t.isMemberExpression(node); +} + +exports.nodes = { + AssignmentExpression: function AssignmentExpression(node) { + var state = crawl(node.right); + if (state.hasCall && state.hasHelper || state.hasFunction) { + return { + before: state.hasFunction, + after: true + }; + } + }, + SwitchCase: function SwitchCase(node, parent) { + return { + before: node.consequent.length || parent.cases[0] === node + }; + }, + LogicalExpression: function LogicalExpression(node) { + if (t.isFunction(node.left) || t.isFunction(node.right)) { + return { + after: true + }; + } + }, + Literal: function Literal(node) { + if (node.value === "use strict") { + return { + after: true + }; + } + }, + CallExpression: function CallExpression(node) { + if (t.isFunction(node.callee) || isHelper(node)) { + return { + before: true, + after: true + }; + } + }, + VariableDeclaration: function VariableDeclaration(node) { + for (var i = 0; i < node.declarations.length; i++) { + var declar = node.declarations[i]; + + var enabled = isHelper(declar.id) && !isType(declar.init); + if (!enabled) { + var state = crawl(declar.init); + enabled = isHelper(declar.init) && state.hasCall || state.hasFunction; + } + + if (enabled) { + return { + before: true, + after: true + }; + } + } + }, + IfStatement: function IfStatement(node) { + if (t.isBlockStatement(node.consequent)) { + return { + before: true, + after: true + }; + } + } +}; + +exports.nodes.ObjectProperty = exports.nodes.ObjectTypeProperty = exports.nodes.ObjectMethod = exports.nodes.SpreadProperty = function (node, parent) { + if (parent.properties[0] === node) { + return { + before: true + }; + } +}; + +exports.list = { + VariableDeclaration: function VariableDeclaration(node) { + return (0, _map2.default)(node.declarations, "init"); + }, + ArrayExpression: function ArrayExpression(node) { + return node.elements; + }, + ObjectExpression: function ObjectExpression(node) { + return node.properties; + } +}; + +[["Function", true], ["Class", true], ["Loop", true], ["LabeledStatement", true], ["SwitchStatement", true], ["TryStatement", true]].forEach(function (_ref) { + var type = _ref[0], + amounts = _ref[1]; + + if (typeof amounts === "boolean") { + amounts = { after: amounts, before: amounts }; + } + [type].concat(t.FLIPPED_ALIAS_KEYS[type] || []).forEach(function (type) { + exports.nodes[type] = function () { + return amounts; + }; + }); +}); +},{"babel-types":112,"lodash/map":449}],47:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _assign = require("babel-runtime/core-js/object/assign"); + +var _assign2 = _interopRequireDefault(_assign); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _stringify = require("babel-runtime/core-js/json/stringify"); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _weakSet = require("babel-runtime/core-js/weak-set"); + +var _weakSet2 = _interopRequireDefault(_weakSet); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _find = require("lodash/find"); + +var _find2 = _interopRequireDefault(_find); + +var _findLast = require("lodash/findLast"); + +var _findLast2 = _interopRequireDefault(_findLast); + +var _isInteger = require("lodash/isInteger"); + +var _isInteger2 = _interopRequireDefault(_isInteger); + +var _repeat = require("lodash/repeat"); + +var _repeat2 = _interopRequireDefault(_repeat); + +var _buffer = require("./buffer"); + +var _buffer2 = _interopRequireDefault(_buffer); + +var _node = require("./node"); + +var n = _interopRequireWildcard(_node); + +var _whitespace = require("./whitespace"); + +var _whitespace2 = _interopRequireDefault(_whitespace); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var SCIENTIFIC_NOTATION = /e/i; +var ZERO_DECIMAL_INTEGER = /\.0+$/; +var NON_DECIMAL_LITERAL = /^0[box]/; + +var Printer = function () { + function Printer(format, map, tokens) { + (0, _classCallCheck3.default)(this, Printer); + this.inForStatementInitCounter = 0; + this._printStack = []; + this._indent = 0; + this._insideAux = false; + this._printedCommentStarts = {}; + this._parenPushNewlineState = null; + this._printAuxAfterOnNextUserNode = false; + this._printedComments = new _weakSet2.default(); + this._endsWithInteger = false; + this._endsWithWord = false; + + this.format = format || {}; + this._buf = new _buffer2.default(map); + this._whitespace = tokens.length > 0 ? new _whitespace2.default(tokens) : null; + } + + Printer.prototype.generate = function generate(ast) { + this.print(ast); + this._maybeAddAuxComment(); + + return this._buf.get(); + }; + + Printer.prototype.indent = function indent() { + if (this.format.compact || this.format.concise) return; + + this._indent++; + }; + + Printer.prototype.dedent = function dedent() { + if (this.format.compact || this.format.concise) return; + + this._indent--; + }; + + Printer.prototype.semicolon = function semicolon() { + var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + this._maybeAddAuxComment(); + this._append(";", !force); + }; + + Printer.prototype.rightBrace = function rightBrace() { + if (this.format.minified) { + this._buf.removeLastSemicolon(); + } + this.token("}"); + }; + + Printer.prototype.space = function space() { + var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + if (this.format.compact) return; + + if (this._buf.hasContent() && !this.endsWith(" ") && !this.endsWith("\n") || force) { + this._space(); + } + }; + + Printer.prototype.word = function word(str) { + if (this._endsWithWord) this._space(); + + this._maybeAddAuxComment(); + this._append(str); + + this._endsWithWord = true; + }; + + Printer.prototype.number = function number(str) { + this.word(str); + + this._endsWithInteger = (0, _isInteger2.default)(+str) && !NON_DECIMAL_LITERAL.test(str) && !SCIENTIFIC_NOTATION.test(str) && !ZERO_DECIMAL_INTEGER.test(str) && str[str.length - 1] !== "."; + }; + + Printer.prototype.token = function token(str) { + if (str === "--" && this.endsWith("!") || str[0] === "+" && this.endsWith("+") || str[0] === "-" && this.endsWith("-") || str[0] === "." && this._endsWithInteger) { + this._space(); + } + + this._maybeAddAuxComment(); + this._append(str); + }; + + Printer.prototype.newline = function newline(i) { + if (this.format.retainLines || this.format.compact) return; + + if (this.format.concise) { + this.space(); + return; + } + + if (this.endsWith("\n\n")) return; + + if (typeof i !== "number") i = 1; + + i = Math.min(2, i); + if (this.endsWith("{\n") || this.endsWith(":\n")) i--; + if (i <= 0) return; + + for (var j = 0; j < i; j++) { + this._newline(); + } + }; + + Printer.prototype.endsWith = function endsWith(str) { + return this._buf.endsWith(str); + }; + + Printer.prototype.removeTrailingNewline = function removeTrailingNewline() { + this._buf.removeTrailingNewline(); + }; + + Printer.prototype.source = function source(prop, loc) { + this._catchUp(prop, loc); + + this._buf.source(prop, loc); + }; + + Printer.prototype.withSource = function withSource(prop, loc, cb) { + this._catchUp(prop, loc); + + this._buf.withSource(prop, loc, cb); + }; + + Printer.prototype._space = function _space() { + this._append(" ", true); + }; + + Printer.prototype._newline = function _newline() { + this._append("\n", true); + }; + + Printer.prototype._append = function _append(str) { + var queue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + this._maybeAddParen(str); + this._maybeIndent(str); + + if (queue) this._buf.queue(str);else this._buf.append(str); + + this._endsWithWord = false; + this._endsWithInteger = false; + }; + + Printer.prototype._maybeIndent = function _maybeIndent(str) { + if (this._indent && this.endsWith("\n") && str[0] !== "\n") { + this._buf.queue(this._getIndent()); + } + }; + + Printer.prototype._maybeAddParen = function _maybeAddParen(str) { + var parenPushNewlineState = this._parenPushNewlineState; + if (!parenPushNewlineState) return; + this._parenPushNewlineState = null; + + var i = void 0; + for (i = 0; i < str.length && str[i] === " "; i++) { + continue; + }if (i === str.length) return; + + var cha = str[i]; + if (cha === "\n" || cha === "/") { + this.token("("); + this.indent(); + parenPushNewlineState.printed = true; + } + }; + + Printer.prototype._catchUp = function _catchUp(prop, loc) { + if (!this.format.retainLines) return; + + var pos = loc ? loc[prop] : null; + if (pos && pos.line !== null) { + var count = pos.line - this._buf.getCurrentLine(); + + for (var i = 0; i < count; i++) { + this._newline(); + } + } + }; + + Printer.prototype._getIndent = function _getIndent() { + return (0, _repeat2.default)(this.format.indent.style, this._indent); + }; + + Printer.prototype.startTerminatorless = function startTerminatorless() { + return this._parenPushNewlineState = { + printed: false + }; + }; + + Printer.prototype.endTerminatorless = function endTerminatorless(state) { + if (state.printed) { + this.dedent(); + this.newline(); + this.token(")"); + } + }; + + Printer.prototype.print = function print(node, parent) { + var _this = this; + + if (!node) return; + + var oldConcise = this.format.concise; + if (node._compact) { + this.format.concise = true; + } + + var printMethod = this[node.type]; + if (!printMethod) { + throw new ReferenceError("unknown node of type " + (0, _stringify2.default)(node.type) + " with constructor " + (0, _stringify2.default)(node && node.constructor.name)); + } + + this._printStack.push(node); + + var oldInAux = this._insideAux; + this._insideAux = !node.loc; + this._maybeAddAuxComment(this._insideAux && !oldInAux); + + var needsParens = n.needsParens(node, parent, this._printStack); + if (this.format.retainFunctionParens && node.type === "FunctionExpression" && node.extra && node.extra.parenthesized) { + needsParens = true; + } + if (needsParens) this.token("("); + + this._printLeadingComments(node, parent); + + var loc = t.isProgram(node) || t.isFile(node) ? null : node.loc; + this.withSource("start", loc, function () { + _this[node.type](node, parent); + }); + + this._printTrailingComments(node, parent); + + if (needsParens) this.token(")"); + + this._printStack.pop(); + + this.format.concise = oldConcise; + this._insideAux = oldInAux; + }; + + Printer.prototype._maybeAddAuxComment = function _maybeAddAuxComment(enteredPositionlessNode) { + if (enteredPositionlessNode) this._printAuxBeforeComment(); + if (!this._insideAux) this._printAuxAfterComment(); + }; + + Printer.prototype._printAuxBeforeComment = function _printAuxBeforeComment() { + if (this._printAuxAfterOnNextUserNode) return; + this._printAuxAfterOnNextUserNode = true; + + var comment = this.format.auxiliaryCommentBefore; + if (comment) { + this._printComment({ + type: "CommentBlock", + value: comment + }); + } + }; + + Printer.prototype._printAuxAfterComment = function _printAuxAfterComment() { + if (!this._printAuxAfterOnNextUserNode) return; + this._printAuxAfterOnNextUserNode = false; + + var comment = this.format.auxiliaryCommentAfter; + if (comment) { + this._printComment({ + type: "CommentBlock", + value: comment + }); + } + }; + + Printer.prototype.getPossibleRaw = function getPossibleRaw(node) { + var extra = node.extra; + if (extra && extra.raw != null && extra.rawValue != null && node.value === extra.rawValue) { + return extra.raw; + } + }; + + Printer.prototype.printJoin = function printJoin(nodes, parent) { + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + if (!nodes || !nodes.length) return; + + if (opts.indent) this.indent(); + + var newlineOpts = { + addNewlines: opts.addNewlines + }; + + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + if (!node) continue; + + if (opts.statement) this._printNewline(true, node, parent, newlineOpts); + + this.print(node, parent); + + if (opts.iterator) { + opts.iterator(node, i); + } + + if (opts.separator && i < nodes.length - 1) { + opts.separator.call(this); + } + + if (opts.statement) this._printNewline(false, node, parent, newlineOpts); + } + + if (opts.indent) this.dedent(); + }; + + Printer.prototype.printAndIndentOnComments = function printAndIndentOnComments(node, parent) { + var indent = !!node.leadingComments; + if (indent) this.indent(); + this.print(node, parent); + if (indent) this.dedent(); + }; + + Printer.prototype.printBlock = function printBlock(parent) { + var node = parent.body; + + if (!t.isEmptyStatement(node)) { + this.space(); + } + + this.print(node, parent); + }; + + Printer.prototype._printTrailingComments = function _printTrailingComments(node, parent) { + this._printComments(this._getComments(false, node, parent)); + }; + + Printer.prototype._printLeadingComments = function _printLeadingComments(node, parent) { + this._printComments(this._getComments(true, node, parent)); + }; + + Printer.prototype.printInnerComments = function printInnerComments(node) { + var indent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + if (!node.innerComments) return; + if (indent) this.indent(); + this._printComments(node.innerComments); + if (indent) this.dedent(); + }; + + Printer.prototype.printSequence = function printSequence(nodes, parent) { + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + opts.statement = true; + return this.printJoin(nodes, parent, opts); + }; + + Printer.prototype.printList = function printList(items, parent) { + var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + if (opts.separator == null) { + opts.separator = commaSeparator; + } + + return this.printJoin(items, parent, opts); + }; + + Printer.prototype._printNewline = function _printNewline(leading, node, parent, opts) { + var _this2 = this; + + if (this.format.retainLines || this.format.compact) return; + + if (this.format.concise) { + this.space(); + return; + } + + var lines = 0; + + if (node.start != null && !node._ignoreUserWhitespace && this._whitespace) { + if (leading) { + var _comments = node.leadingComments; + var _comment = _comments && (0, _find2.default)(_comments, function (comment) { + return !!comment.loc && _this2.format.shouldPrintComment(comment.value); + }); + + lines = this._whitespace.getNewlinesBefore(_comment || node); + } else { + var _comments2 = node.trailingComments; + var _comment2 = _comments2 && (0, _findLast2.default)(_comments2, function (comment) { + return !!comment.loc && _this2.format.shouldPrintComment(comment.value); + }); + + lines = this._whitespace.getNewlinesAfter(_comment2 || node); + } + } else { + if (!leading) lines++; + if (opts.addNewlines) lines += opts.addNewlines(leading, node) || 0; + + var needs = n.needsWhitespaceAfter; + if (leading) needs = n.needsWhitespaceBefore; + if (needs(node, parent)) lines++; + + if (!this._buf.hasContent()) lines = 0; + } + + this.newline(lines); + }; + + Printer.prototype._getComments = function _getComments(leading, node) { + return node && (leading ? node.leadingComments : node.trailingComments) || []; + }; + + Printer.prototype._printComment = function _printComment(comment) { + var _this3 = this; + + if (!this.format.shouldPrintComment(comment.value)) return; + + if (comment.ignore) return; + + if (this._printedComments.has(comment)) return; + this._printedComments.add(comment); + + if (comment.start != null) { + if (this._printedCommentStarts[comment.start]) return; + this._printedCommentStarts[comment.start] = true; + } + + this.newline(this._whitespace ? this._whitespace.getNewlinesBefore(comment) : 0); + + if (!this.endsWith("[") && !this.endsWith("{")) this.space(); + + var val = comment.type === "CommentLine" ? "//" + comment.value + "\n" : "/*" + comment.value + "*/"; + + if (comment.type === "CommentBlock" && this.format.indent.adjustMultilineComment) { + var offset = comment.loc && comment.loc.start.column; + if (offset) { + var newlineRegex = new RegExp("\\n\\s{1," + offset + "}", "g"); + val = val.replace(newlineRegex, "\n"); + } + + var indentSize = Math.max(this._getIndent().length, this._buf.getCurrentColumn()); + val = val.replace(/\n(?!$)/g, "\n" + (0, _repeat2.default)(" ", indentSize)); + } + + this.withSource("start", comment.loc, function () { + _this3._append(val); + }); + + this.newline((this._whitespace ? this._whitespace.getNewlinesAfter(comment) : 0) + (comment.type === "CommentLine" ? -1 : 0)); + }; + + Printer.prototype._printComments = function _printComments(comments) { + if (!comments || !comments.length) return; + + for (var _iterator = comments, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var _comment3 = _ref; + + this._printComment(_comment3); + } + }; + + return Printer; +}(); + +exports.default = Printer; + + +function commaSeparator() { + this.token(","); + this.space(); +} + +var _arr = [require("./generators/template-literals"), require("./generators/expressions"), require("./generators/statements"), require("./generators/classes"), require("./generators/methods"), require("./generators/modules"), require("./generators/types"), require("./generators/flow"), require("./generators/base"), require("./generators/jsx")]; +for (var _i2 = 0; _i2 < _arr.length; _i2++) { + var generator = _arr[_i2]; + (0, _assign2.default)(Printer.prototype, generator); +} +module.exports = exports["default"]; +},{"./buffer":32,"./generators/base":33,"./generators/classes":34,"./generators/expressions":35,"./generators/flow":36,"./generators/jsx":37,"./generators/methods":38,"./generators/modules":39,"./generators/statements":40,"./generators/template-literals":41,"./generators/types":42,"./node":44,"./whitespace":49,"babel-runtime/core-js/get-iterator":56,"babel-runtime/core-js/json/stringify":57,"babel-runtime/core-js/object/assign":60,"babel-runtime/core-js/weak-set":69,"babel-runtime/helpers/classCallCheck":70,"babel-types":112,"lodash/find":423,"lodash/findLast":425,"lodash/isInteger":438,"lodash/repeat":454}],48:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _keys = require("babel-runtime/core-js/object/keys"); + +var _keys2 = _interopRequireDefault(_keys); + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _sourceMap = require("source-map"); + +var _sourceMap2 = _interopRequireDefault(_sourceMap); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var SourceMap = function () { + function SourceMap(opts, code) { + (0, _classCallCheck3.default)(this, SourceMap); + + this._cachedMap = null; + this._code = code; + this._opts = opts; + this._rawMappings = []; + } + + SourceMap.prototype.get = function get() { + var _this = this; + + if (!this._cachedMap) { + (function () { + var map = _this._cachedMap = new _sourceMap2.default.SourceMapGenerator({ + file: _this._opts.sourceMapTarget, + sourceRoot: _this._opts.sourceRoot + }); + + var code = _this._code; + if (typeof code === "string") { + map.setSourceContent(_this._opts.sourceFileName, code); + } else if ((typeof code === "undefined" ? "undefined" : (0, _typeof3.default)(code)) === "object") { + (0, _keys2.default)(code).forEach(function (sourceFileName) { + map.setSourceContent(sourceFileName, code[sourceFileName]); + }); + } + + _this._rawMappings.forEach(map.addMapping, map); + })(); + } + + return this._cachedMap.toJSON(); + }; + + SourceMap.prototype.getRawMappings = function getRawMappings() { + return this._rawMappings.slice(); + }; + + SourceMap.prototype.mark = function mark(generatedLine, generatedColumn, line, column, identifierName, filename) { + if (this._lastGenLine !== generatedLine && line === null) return; + + if (this._lastGenLine === generatedLine && this._lastSourceLine === line && this._lastSourceColumn === column) { + return; + } + + this._cachedMap = null; + this._lastGenLine = generatedLine; + this._lastSourceLine = line; + this._lastSourceColumn = column; + + this._rawMappings.push({ + name: identifierName || undefined, + generated: { + line: generatedLine, + column: generatedColumn + }, + source: line == null ? undefined : filename || this._opts.sourceFileName, + original: line == null ? undefined : { + line: line, + column: column + } + }); + }; + + return SourceMap; +}(); + +exports.default = SourceMap; +module.exports = exports["default"]; +},{"babel-runtime/core-js/object/keys":63,"babel-runtime/helpers/classCallCheck":70,"babel-runtime/helpers/typeof":74,"source-map":484}],49:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var Whitespace = function () { + function Whitespace(tokens) { + (0, _classCallCheck3.default)(this, Whitespace); + + this.tokens = tokens; + this.used = {}; + } + + Whitespace.prototype.getNewlinesBefore = function getNewlinesBefore(node) { + var startToken = void 0; + var endToken = void 0; + var tokens = this.tokens; + + var index = this._findToken(function (token) { + return token.start - node.start; + }, 0, tokens.length); + if (index >= 0) { + while (index && node.start === tokens[index - 1].start) { + --index; + }startToken = tokens[index - 1]; + endToken = tokens[index]; + } + + return this._getNewlinesBetween(startToken, endToken); + }; + + Whitespace.prototype.getNewlinesAfter = function getNewlinesAfter(node) { + var startToken = void 0; + var endToken = void 0; + var tokens = this.tokens; + + var index = this._findToken(function (token) { + return token.end - node.end; + }, 0, tokens.length); + if (index >= 0) { + while (index && node.end === tokens[index - 1].end) { + --index; + }startToken = tokens[index]; + endToken = tokens[index + 1]; + if (endToken.type.label === ",") endToken = tokens[index + 2]; + } + + if (endToken && endToken.type.label === "eof") { + return 1; + } else { + return this._getNewlinesBetween(startToken, endToken); + } + }; + + Whitespace.prototype._getNewlinesBetween = function _getNewlinesBetween(startToken, endToken) { + if (!endToken || !endToken.loc) return 0; + + var start = startToken ? startToken.loc.end.line : 1; + var end = endToken.loc.start.line; + var lines = 0; + + for (var line = start; line < end; line++) { + if (typeof this.used[line] === "undefined") { + this.used[line] = true; + lines++; + } + } + + return lines; + }; + + Whitespace.prototype._findToken = function _findToken(test, start, end) { + if (start >= end) return -1; + var middle = start + end >>> 1; + var match = test(this.tokens[middle]); + if (match < 0) { + return this._findToken(test, middle + 1, end); + } else if (match > 0) { + return this._findToken(test, start, middle); + } else if (match === 0) { + return middle; + } + return -1; + }; + + return Whitespace; +}(); + +exports.default = Whitespace; +module.exports = exports["default"]; +},{"babel-runtime/helpers/classCallCheck":70}],50:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.default = function (path, emit) { + var kind = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "var"; + + path.traverse(visitor, { kind: kind, emit: emit }); +}; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var visitor = { + Scope: function Scope(path, state) { + if (state.kind === "let") path.skip(); + }, + Function: function Function(path) { + path.skip(); + }, + VariableDeclaration: function VariableDeclaration(path, state) { + if (state.kind && path.node.kind !== state.kind) return; + + var nodes = []; + + var declarations = path.get("declarations"); + var firstId = void 0; + + for (var _iterator = declarations, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var declar = _ref; + + firstId = declar.node.id; + + if (declar.node.init) { + nodes.push(t.expressionStatement(t.assignmentExpression("=", declar.node.id, declar.node.init))); + } + + for (var name in declar.getBindingIdentifiers()) { + state.emit(t.identifier(name), name); + } + } + + if (path.parentPath.isFor({ left: path.node })) { + path.replaceWith(firstId); + } else { + path.replaceWithMultiple(nodes); + } + } +}; + +module.exports = exports["default"]; +},{"babel-runtime/core-js/get-iterator":56,"babel-types":112}],51:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _babelTemplate = require("babel-template"); + +var _babelTemplate2 = _interopRequireDefault(_babelTemplate); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var helpers = {}; +exports.default = helpers; + + +helpers.typeof = (0, _babelTemplate2.default)("\n (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\")\n ? function (obj) { return typeof obj; }\n : function (obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype\n ? \"symbol\"\n : typeof obj;\n };\n"); + +helpers.jsx = (0, _babelTemplate2.default)("\n (function () {\n var REACT_ELEMENT_TYPE = (typeof Symbol === \"function\" && Symbol.for && Symbol.for(\"react.element\")) || 0xeac7;\n\n return function createRawReactElement (type, props, key, children) {\n var defaultProps = type && type.defaultProps;\n var childrenLength = arguments.length - 3;\n\n if (!props && childrenLength !== 0) {\n // If we're going to assign props.children, we create a new object now\n // to avoid mutating defaultProps.\n props = {};\n }\n if (props && defaultProps) {\n for (var propName in defaultProps) {\n if (props[propName] === void 0) {\n props[propName] = defaultProps[propName];\n }\n }\n } else if (!props) {\n props = defaultProps || {};\n }\n\n if (childrenLength === 1) {\n props.children = children;\n } else if (childrenLength > 1) {\n var childArray = Array(childrenLength);\n for (var i = 0; i < childrenLength; i++) {\n childArray[i] = arguments[i + 3];\n }\n props.children = childArray;\n }\n\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key === undefined ? null : '' + key,\n ref: null,\n props: props,\n _owner: null,\n };\n };\n\n })()\n"); + +helpers.asyncIterator = (0, _babelTemplate2.default)("\n (function (iterable) {\n if (typeof Symbol === \"function\") {\n if (Symbol.asyncIterator) {\n var method = iterable[Symbol.asyncIterator];\n if (method != null) return method.call(iterable);\n }\n if (Symbol.iterator) {\n return iterable[Symbol.iterator]();\n }\n }\n throw new TypeError(\"Object is not async iterable\");\n })\n"); + +helpers.asyncGenerator = (0, _babelTemplate2.default)("\n (function () {\n function AwaitValue(value) {\n this.value = value;\n }\n\n function AsyncGenerator(gen) {\n var front, back;\n\n function send(key, arg) {\n return new Promise(function (resolve, reject) {\n var request = {\n key: key,\n arg: arg,\n resolve: resolve,\n reject: reject,\n next: null\n };\n\n if (back) {\n back = back.next = request;\n } else {\n front = back = request;\n resume(key, arg);\n }\n });\n }\n\n function resume(key, arg) {\n try {\n var result = gen[key](arg)\n var value = result.value;\n if (value instanceof AwaitValue) {\n Promise.resolve(value.value).then(\n function (arg) { resume(\"next\", arg); },\n function (arg) { resume(\"throw\", arg); });\n } else {\n settle(result.done ? \"return\" : \"normal\", result.value);\n }\n } catch (err) {\n settle(\"throw\", err);\n }\n }\n\n function settle(type, value) {\n switch (type) {\n case \"return\":\n front.resolve({ value: value, done: true });\n break;\n case \"throw\":\n front.reject(value);\n break;\n default:\n front.resolve({ value: value, done: false });\n break;\n }\n\n front = front.next;\n if (front) {\n resume(front.key, front.arg);\n } else {\n back = null;\n }\n }\n\n this._invoke = send;\n\n // Hide \"return\" method if generator return is not supported\n if (typeof gen.return !== \"function\") {\n this.return = undefined;\n }\n }\n\n if (typeof Symbol === \"function\" && Symbol.asyncIterator) {\n AsyncGenerator.prototype[Symbol.asyncIterator] = function () { return this; };\n }\n\n AsyncGenerator.prototype.next = function (arg) { return this._invoke(\"next\", arg); };\n AsyncGenerator.prototype.throw = function (arg) { return this._invoke(\"throw\", arg); };\n AsyncGenerator.prototype.return = function (arg) { return this._invoke(\"return\", arg); };\n\n return {\n wrap: function (fn) {\n return function () {\n return new AsyncGenerator(fn.apply(this, arguments));\n };\n },\n await: function (value) {\n return new AwaitValue(value);\n }\n };\n\n })()\n"); + +helpers.asyncGeneratorDelegate = (0, _babelTemplate2.default)("\n (function (inner, awaitWrap) {\n var iter = {}, waiting = false;\n\n function pump(key, value) {\n waiting = true;\n value = new Promise(function (resolve) { resolve(inner[key](value)); });\n return { done: false, value: awaitWrap(value) };\n };\n\n if (typeof Symbol === \"function\" && Symbol.iterator) {\n iter[Symbol.iterator] = function () { return this; };\n }\n\n iter.next = function (value) {\n if (waiting) {\n waiting = false;\n return value;\n }\n return pump(\"next\", value);\n };\n\n if (typeof inner.throw === \"function\") {\n iter.throw = function (value) {\n if (waiting) {\n waiting = false;\n throw value;\n }\n return pump(\"throw\", value);\n };\n }\n\n if (typeof inner.return === \"function\") {\n iter.return = function (value) {\n return pump(\"return\", value);\n };\n }\n\n return iter;\n })\n"); + +helpers.asyncToGenerator = (0, _babelTemplate2.default)("\n (function (fn) {\n return function () {\n var gen = fn.apply(this, arguments);\n return new Promise(function (resolve, reject) {\n function step(key, arg) {\n try {\n var info = gen[key](arg);\n var value = info.value;\n } catch (error) {\n reject(error);\n return;\n }\n\n if (info.done) {\n resolve(value);\n } else {\n return Promise.resolve(value).then(function (value) {\n step(\"next\", value);\n }, function (err) {\n step(\"throw\", err);\n });\n }\n }\n\n return step(\"next\");\n });\n };\n })\n"); + +helpers.classCallCheck = (0, _babelTemplate2.default)("\n (function (instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n });\n"); + +helpers.createClass = (0, _babelTemplate2.default)("\n (function() {\n function defineProperties(target, props) {\n for (var i = 0; i < props.length; i ++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n }\n\n return function (Constructor, protoProps, staticProps) {\n if (protoProps) defineProperties(Constructor.prototype, protoProps);\n if (staticProps) defineProperties(Constructor, staticProps);\n return Constructor;\n };\n })()\n"); + +helpers.defineEnumerableProperties = (0, _babelTemplate2.default)("\n (function (obj, descs) {\n for (var key in descs) {\n var desc = descs[key];\n desc.configurable = desc.enumerable = true;\n if (\"value\" in desc) desc.writable = true;\n Object.defineProperty(obj, key, desc);\n }\n return obj;\n })\n"); + +helpers.defaults = (0, _babelTemplate2.default)("\n (function (obj, defaults) {\n var keys = Object.getOwnPropertyNames(defaults);\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n var value = Object.getOwnPropertyDescriptor(defaults, key);\n if (value && value.configurable && obj[key] === undefined) {\n Object.defineProperty(obj, key, value);\n }\n }\n return obj;\n })\n"); + +helpers.defineProperty = (0, _babelTemplate2.default)("\n (function (obj, key, value) {\n // Shortcircuit the slow defineProperty path when possible.\n // We are trying to avoid issues where setters defined on the\n // prototype cause side effects under the fast path of simple\n // assignment. By checking for existence of the property with\n // the in operator, we can optimize most of this overhead away.\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n return obj;\n });\n"); + +helpers.extends = (0, _babelTemplate2.default)("\n Object.assign || (function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n return target;\n })\n"); + +helpers.get = (0, _babelTemplate2.default)("\n (function get(object, property, receiver) {\n if (object === null) object = Function.prototype;\n\n var desc = Object.getOwnPropertyDescriptor(object, property);\n\n if (desc === undefined) {\n var parent = Object.getPrototypeOf(object);\n\n if (parent === null) {\n return undefined;\n } else {\n return get(parent, property, receiver);\n }\n } else if (\"value\" in desc) {\n return desc.value;\n } else {\n var getter = desc.get;\n\n if (getter === undefined) {\n return undefined;\n }\n\n return getter.call(receiver);\n }\n });\n"); + +helpers.inherits = (0, _babelTemplate2.default)("\n (function (subClass, superClass) {\n if (typeof superClass !== \"function\" && superClass !== null) {\n throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass);\n }\n subClass.prototype = Object.create(superClass && superClass.prototype, {\n constructor: {\n value: subClass,\n enumerable: false,\n writable: true,\n configurable: true\n }\n });\n if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;\n })\n"); + +helpers.instanceof = (0, _babelTemplate2.default)("\n (function (left, right) {\n if (right != null && typeof Symbol !== \"undefined\" && right[Symbol.hasInstance]) {\n return right[Symbol.hasInstance](left);\n } else {\n return left instanceof right;\n }\n });\n"); + +helpers.interopRequireDefault = (0, _babelTemplate2.default)("\n (function (obj) {\n return obj && obj.__esModule ? obj : { default: obj };\n })\n"); + +helpers.interopRequireWildcard = (0, _babelTemplate2.default)("\n (function (obj) {\n if (obj && obj.__esModule) {\n return obj;\n } else {\n var newObj = {};\n if (obj != null) {\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];\n }\n }\n newObj.default = obj;\n return newObj;\n }\n })\n"); + +helpers.newArrowCheck = (0, _babelTemplate2.default)("\n (function (innerThis, boundThis) {\n if (innerThis !== boundThis) {\n throw new TypeError(\"Cannot instantiate an arrow function\");\n }\n });\n"); + +helpers.objectDestructuringEmpty = (0, _babelTemplate2.default)("\n (function (obj) {\n if (obj == null) throw new TypeError(\"Cannot destructure undefined\");\n });\n"); + +helpers.objectWithoutProperties = (0, _babelTemplate2.default)("\n (function (obj, keys) {\n var target = {};\n for (var i in obj) {\n if (keys.indexOf(i) >= 0) continue;\n if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;\n target[i] = obj[i];\n }\n return target;\n })\n"); + +helpers.possibleConstructorReturn = (0, _babelTemplate2.default)("\n (function (self, call) {\n if (!self) {\n throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");\n }\n return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self;\n });\n"); + +helpers.selfGlobal = (0, _babelTemplate2.default)("\n typeof global === \"undefined\" ? self : global\n"); + +helpers.set = (0, _babelTemplate2.default)("\n (function set(object, property, value, receiver) {\n var desc = Object.getOwnPropertyDescriptor(object, property);\n\n if (desc === undefined) {\n var parent = Object.getPrototypeOf(object);\n\n if (parent !== null) {\n set(parent, property, value, receiver);\n }\n } else if (\"value\" in desc && desc.writable) {\n desc.value = value;\n } else {\n var setter = desc.set;\n\n if (setter !== undefined) {\n setter.call(receiver, value);\n }\n }\n\n return value;\n });\n"); + +helpers.slicedToArray = (0, _babelTemplate2.default)("\n (function () {\n // Broken out into a separate function to avoid deoptimizations due to the try/catch for the\n // array iterator case.\n function sliceIterator(arr, i) {\n // this is an expanded form of `for...of` that properly supports abrupt completions of\n // iterators etc. variable names have been minimised to reduce the size of this massive\n // helper. sometimes spec compliancy is annoying :(\n //\n // _n = _iteratorNormalCompletion\n // _d = _didIteratorError\n // _e = _iteratorError\n // _i = _iterator\n // _s = _step\n\n var _arr = [];\n var _n = true;\n var _d = false;\n var _e = undefined;\n try {\n for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {\n _arr.push(_s.value);\n if (i && _arr.length === i) break;\n }\n } catch (err) {\n _d = true;\n _e = err;\n } finally {\n try {\n if (!_n && _i[\"return\"]) _i[\"return\"]();\n } finally {\n if (_d) throw _e;\n }\n }\n return _arr;\n }\n\n return function (arr, i) {\n if (Array.isArray(arr)) {\n return arr;\n } else if (Symbol.iterator in Object(arr)) {\n return sliceIterator(arr, i);\n } else {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance\");\n }\n };\n })();\n"); + +helpers.slicedToArrayLoose = (0, _babelTemplate2.default)("\n (function (arr, i) {\n if (Array.isArray(arr)) {\n return arr;\n } else if (Symbol.iterator in Object(arr)) {\n var _arr = [];\n for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) {\n _arr.push(_step.value);\n if (i && _arr.length === i) break;\n }\n return _arr;\n } else {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance\");\n }\n });\n"); + +helpers.taggedTemplateLiteral = (0, _babelTemplate2.default)("\n (function (strings, raw) {\n return Object.freeze(Object.defineProperties(strings, {\n raw: { value: Object.freeze(raw) }\n }));\n });\n"); + +helpers.taggedTemplateLiteralLoose = (0, _babelTemplate2.default)("\n (function (strings, raw) {\n strings.raw = raw;\n return strings;\n });\n"); + +helpers.temporalRef = (0, _babelTemplate2.default)("\n (function (val, name, undef) {\n if (val === undef) {\n throw new ReferenceError(name + \" is not defined - temporal dead zone\");\n } else {\n return val;\n }\n })\n"); + +helpers.temporalUndefined = (0, _babelTemplate2.default)("\n ({})\n"); + +helpers.toArray = (0, _babelTemplate2.default)("\n (function (arr) {\n return Array.isArray(arr) ? arr : Array.from(arr);\n });\n"); + +helpers.toConsumableArray = (0, _babelTemplate2.default)("\n (function (arr) {\n if (Array.isArray(arr)) {\n for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];\n return arr2;\n } else {\n return Array.from(arr);\n }\n });\n"); +module.exports = exports["default"]; +},{"babel-template":75}],52:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.list = undefined; + +var _keys = require("babel-runtime/core-js/object/keys"); + +var _keys2 = _interopRequireDefault(_keys); + +exports.get = get; + +var _helpers = require("./helpers"); + +var _helpers2 = _interopRequireDefault(_helpers); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function get(name) { + var fn = _helpers2.default[name]; + if (!fn) throw new ReferenceError("Unknown helper " + name); + + return fn().expression; +} + +var list = exports.list = (0, _keys2.default)(_helpers2.default).map(function (name) { + return name.replace(/^_/, ""); +}).filter(function (name) { + return name !== "__esModule"; +}); + +exports.default = get; +},{"./helpers":51,"babel-runtime/core-js/object/keys":63}],53:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.MESSAGES = undefined; + +var _stringify = require("babel-runtime/core-js/json/stringify"); + +var _stringify2 = _interopRequireDefault(_stringify); + +exports.get = get; +exports.parseArgs = parseArgs; + +var _util = require("util"); + +var util = _interopRequireWildcard(_util); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var MESSAGES = exports.MESSAGES = { + tailCallReassignmentDeopt: "Function reference has been reassigned, so it will probably be dereferenced, therefore we can't optimise this with confidence", + classesIllegalBareSuper: "Illegal use of bare super", + classesIllegalSuperCall: "Direct super call is illegal in non-constructor, use super.$1() instead", + scopeDuplicateDeclaration: "Duplicate declaration $1", + settersNoRest: "Setters aren't allowed to have a rest", + noAssignmentsInForHead: "No assignments allowed in for-in/of head", + expectedMemberExpressionOrIdentifier: "Expected type MemberExpression or Identifier", + invalidParentForThisNode: "We don't know how to handle this node within the current parent - please open an issue", + readOnly: "$1 is read-only", + unknownForHead: "Unknown node type $1 in ForStatement", + didYouMean: "Did you mean $1?", + codeGeneratorDeopt: "Note: The code generator has deoptimised the styling of $1 as it exceeds the max of $2.", + missingTemplatesDirectory: "no templates directory - this is most likely the result of a broken `npm publish`. Please report to https://github.com/babel/babel/issues", + unsupportedOutputType: "Unsupported output type $1", + illegalMethodName: "Illegal method name $1", + lostTrackNodePath: "We lost track of this node's position, likely because the AST was directly manipulated", + + modulesIllegalExportName: "Illegal export $1", + modulesDuplicateDeclarations: "Duplicate module declarations with the same source but in different scopes", + + undeclaredVariable: "Reference to undeclared variable $1", + undeclaredVariableType: "Referencing a type alias outside of a type annotation", + undeclaredVariableSuggestion: "Reference to undeclared variable $1 - did you mean $2?", + + traverseNeedsParent: "You must pass a scope and parentPath unless traversing a Program/File. Instead of that you tried to traverse a $1 node without passing scope and parentPath.", + traverseVerifyRootFunction: "You passed `traverse()` a function when it expected a visitor object, are you sure you didn't mean `{ enter: Function }`?", + traverseVerifyVisitorProperty: "You passed `traverse()` a visitor object with the property $1 that has the invalid property $2", + traverseVerifyNodeType: "You gave us a visitor for the node type $1 but it's not a valid type", + + pluginNotObject: "Plugin $2 specified in $1 was expected to return an object when invoked but returned $3", + pluginNotFunction: "Plugin $2 specified in $1 was expected to return a function but returned $3", + pluginUnknown: "Unknown plugin $1 specified in $2 at $3, attempted to resolve relative to $4", + pluginInvalidProperty: "Plugin $2 specified in $1 provided an invalid property of $3" +}; + +function get(key) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var msg = MESSAGES[key]; + if (!msg) throw new ReferenceError("Unknown message " + (0, _stringify2.default)(key)); + + args = parseArgs(args); + + return msg.replace(/\$(\d+)/g, function (str, i) { + return args[i - 1]; + }); +} + +function parseArgs(args) { + return args.map(function (val) { + if (val != null && val.inspect) { + return val.inspect(); + } else { + try { + return (0, _stringify2.default)(val) || val + ""; + } catch (e) { + return util.inspect(val); + } + } + }); +} +},{"babel-runtime/core-js/json/stringify":57,"util":492}],54:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +exports.default = function () { + return { + manipulateOptions: function manipulateOptions(opts, parserOpts) { + parserOpts.plugins.push("dynamicImport"); + } + }; +}; + +module.exports = exports["default"]; +},{}],55:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _create = require("babel-runtime/core-js/object/create"); + +var _create2 = _interopRequireDefault(_create); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _symbol = require("babel-runtime/core-js/symbol"); + +var _symbol2 = _interopRequireDefault(_symbol); + +exports.default = function (_ref) { + var t = _ref.types; + + var IGNORE_REASSIGNMENT_SYMBOL = (0, _symbol2.default)(); + + var reassignmentVisitor = { + "AssignmentExpression|UpdateExpression": function AssignmentExpressionUpdateExpression(path) { + if (path.node[IGNORE_REASSIGNMENT_SYMBOL]) return; + path.node[IGNORE_REASSIGNMENT_SYMBOL] = true; + + var arg = path.get(path.isAssignmentExpression() ? "left" : "argument"); + if (!arg.isIdentifier()) return; + + var name = arg.node.name; + + if (this.scope.getBinding(name) !== path.scope.getBinding(name)) return; + + var exportedNames = this.exports[name]; + if (!exportedNames) return; + + var node = path.node; + + var isPostUpdateExpression = path.isUpdateExpression() && !node.prefix; + if (isPostUpdateExpression) { + if (node.operator === "++") node = t.binaryExpression("+", node.argument, t.numericLiteral(1));else if (node.operator === "--") node = t.binaryExpression("-", node.argument, t.numericLiteral(1));else isPostUpdateExpression = false; + } + + for (var _iterator = exportedNames, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref2; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref2 = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref2 = _i.value; + } + + var exportedName = _ref2; + + node = this.buildCall(exportedName, node).expression; + } + + if (isPostUpdateExpression) node = t.sequenceExpression([node, path.node]); + + path.replaceWith(node); + } + }; + + return { + visitor: { + CallExpression: function CallExpression(path, state) { + if (path.node.callee.type === TYPE_IMPORT) { + var contextIdent = state.contextIdent; + path.replaceWith(t.callExpression(t.memberExpression(contextIdent, t.identifier("import")), path.node.arguments)); + } + }, + ReferencedIdentifier: function ReferencedIdentifier(path, state) { + if (path.node.name == "__moduleName" && !path.scope.hasBinding("__moduleName")) { + path.replaceWith(t.memberExpression(state.contextIdent, t.identifier("id"))); + } + }, + + + Program: { + enter: function enter(path, state) { + state.contextIdent = path.scope.generateUidIdentifier("context"); + }, + exit: function exit(path, state) { + var exportIdent = path.scope.generateUidIdentifier("export"); + var contextIdent = state.contextIdent; + + var exportNames = (0, _create2.default)(null); + var modules = []; + + var beforeBody = []; + var setters = []; + var sources = []; + var variableIds = []; + var removedPaths = []; + + function addExportName(key, val) { + exportNames[key] = exportNames[key] || []; + exportNames[key].push(val); + } + + function pushModule(source, key, specifiers) { + var module = void 0; + modules.forEach(function (m) { + if (m.key === source) { + module = m; + } + }); + if (!module) { + modules.push(module = { key: source, imports: [], exports: [] }); + } + module[key] = module[key].concat(specifiers); + } + + function buildExportCall(name, val) { + return t.expressionStatement(t.callExpression(exportIdent, [t.stringLiteral(name), val])); + } + + var body = path.get("body"); + + var canHoist = true; + for (var _iterator2 = body, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref3; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref3 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref3 = _i2.value; + } + + var _path = _ref3; + + if (_path.isExportDeclaration()) _path = _path.get("declaration"); + if (_path.isVariableDeclaration() && _path.node.kind !== "var") { + canHoist = false; + break; + } + } + + for (var _iterator3 = body, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref4; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref4 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref4 = _i3.value; + } + + var _path2 = _ref4; + + if (canHoist && _path2.isFunctionDeclaration()) { + beforeBody.push(_path2.node); + removedPaths.push(_path2); + } else if (_path2.isImportDeclaration()) { + var source = _path2.node.source.value; + pushModule(source, "imports", _path2.node.specifiers); + for (var name in _path2.getBindingIdentifiers()) { + _path2.scope.removeBinding(name); + variableIds.push(t.identifier(name)); + } + _path2.remove(); + } else if (_path2.isExportAllDeclaration()) { + pushModule(_path2.node.source.value, "exports", _path2.node); + _path2.remove(); + } else if (_path2.isExportDefaultDeclaration()) { + var declar = _path2.get("declaration"); + if (declar.isClassDeclaration() || declar.isFunctionDeclaration()) { + var id = declar.node.id; + var nodes = []; + + if (id) { + nodes.push(declar.node); + nodes.push(buildExportCall("default", id)); + addExportName(id.name, "default"); + } else { + nodes.push(buildExportCall("default", t.toExpression(declar.node))); + } + + if (!canHoist || declar.isClassDeclaration()) { + _path2.replaceWithMultiple(nodes); + } else { + beforeBody = beforeBody.concat(nodes); + removedPaths.push(_path2); + } + } else { + _path2.replaceWith(buildExportCall("default", declar.node)); + } + } else if (_path2.isExportNamedDeclaration()) { + var _declar = _path2.get("declaration"); + + if (_declar.node) { + _path2.replaceWith(_declar); + + var _nodes = []; + var bindingIdentifiers = void 0; + if (_path2.isFunction()) { + var node = _declar.node; + var _name = node.id.name; + if (canHoist) { + addExportName(_name, _name); + beforeBody.push(node); + beforeBody.push(buildExportCall(_name, node.id)); + removedPaths.push(_path2); + } else { + var _bindingIdentifiers; + + bindingIdentifiers = (_bindingIdentifiers = {}, _bindingIdentifiers[_name] = node.id, _bindingIdentifiers); + } + } else { + bindingIdentifiers = _declar.getBindingIdentifiers(); + } + for (var _name2 in bindingIdentifiers) { + addExportName(_name2, _name2); + _nodes.push(buildExportCall(_name2, t.identifier(_name2))); + } + _path2.insertAfter(_nodes); + } else { + var specifiers = _path2.node.specifiers; + if (specifiers && specifiers.length) { + if (_path2.node.source) { + pushModule(_path2.node.source.value, "exports", specifiers); + _path2.remove(); + } else { + var _nodes2 = []; + + for (var _iterator7 = specifiers, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : (0, _getIterator3.default)(_iterator7);;) { + var _ref8; + + if (_isArray7) { + if (_i7 >= _iterator7.length) break; + _ref8 = _iterator7[_i7++]; + } else { + _i7 = _iterator7.next(); + if (_i7.done) break; + _ref8 = _i7.value; + } + + var specifier = _ref8; + + _nodes2.push(buildExportCall(specifier.exported.name, specifier.local)); + addExportName(specifier.local.name, specifier.exported.name); + } + + _path2.replaceWithMultiple(_nodes2); + } + } + } + } + } + + modules.forEach(function (specifiers) { + var setterBody = []; + var target = path.scope.generateUidIdentifier(specifiers.key); + + for (var _iterator4 = specifiers.imports, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : (0, _getIterator3.default)(_iterator4);;) { + var _ref5; + + if (_isArray4) { + if (_i4 >= _iterator4.length) break; + _ref5 = _iterator4[_i4++]; + } else { + _i4 = _iterator4.next(); + if (_i4.done) break; + _ref5 = _i4.value; + } + + var specifier = _ref5; + + if (t.isImportNamespaceSpecifier(specifier)) { + setterBody.push(t.expressionStatement(t.assignmentExpression("=", specifier.local, target))); + } else if (t.isImportDefaultSpecifier(specifier)) { + specifier = t.importSpecifier(specifier.local, t.identifier("default")); + } + + if (t.isImportSpecifier(specifier)) { + setterBody.push(t.expressionStatement(t.assignmentExpression("=", specifier.local, t.memberExpression(target, specifier.imported)))); + } + } + + if (specifiers.exports.length) { + var exportObjRef = path.scope.generateUidIdentifier("exportObj"); + + setterBody.push(t.variableDeclaration("var", [t.variableDeclarator(exportObjRef, t.objectExpression([]))])); + + for (var _iterator5 = specifiers.exports, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : (0, _getIterator3.default)(_iterator5);;) { + var _ref6; + + if (_isArray5) { + if (_i5 >= _iterator5.length) break; + _ref6 = _iterator5[_i5++]; + } else { + _i5 = _iterator5.next(); + if (_i5.done) break; + _ref6 = _i5.value; + } + + var node = _ref6; + + if (t.isExportAllDeclaration(node)) { + setterBody.push(buildExportAll({ + KEY: path.scope.generateUidIdentifier("key"), + EXPORT_OBJ: exportObjRef, + TARGET: target + })); + } else if (t.isExportSpecifier(node)) { + setterBody.push(t.expressionStatement(t.assignmentExpression("=", t.memberExpression(exportObjRef, node.exported), t.memberExpression(target, node.local)))); + } else {} + } + + setterBody.push(t.expressionStatement(t.callExpression(exportIdent, [exportObjRef]))); + } + + sources.push(t.stringLiteral(specifiers.key)); + setters.push(t.functionExpression(null, [target], t.blockStatement(setterBody))); + }); + + var moduleName = this.getModuleName(); + if (moduleName) moduleName = t.stringLiteral(moduleName); + + if (canHoist) { + (0, _babelHelperHoistVariables2.default)(path, function (id) { + return variableIds.push(id); + }); + } + + if (variableIds.length) { + beforeBody.unshift(t.variableDeclaration("var", variableIds.map(function (id) { + return t.variableDeclarator(id); + }))); + } + + path.traverse(reassignmentVisitor, { + exports: exportNames, + buildCall: buildExportCall, + scope: path.scope + }); + + for (var _iterator6 = removedPaths, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : (0, _getIterator3.default)(_iterator6);;) { + var _ref7; + + if (_isArray6) { + if (_i6 >= _iterator6.length) break; + _ref7 = _iterator6[_i6++]; + } else { + _i6 = _iterator6.next(); + if (_i6.done) break; + _ref7 = _i6.value; + } + + var _path3 = _ref7; + + _path3.remove(); + } + + path.node.body = [buildTemplate({ + SYSTEM_REGISTER: t.memberExpression(t.identifier(state.opts.systemGlobal || "System"), t.identifier("register")), + BEFORE_BODY: beforeBody, + MODULE_NAME: moduleName, + SETTERS: setters, + SOURCES: sources, + BODY: path.node.body, + EXPORT_IDENTIFIER: exportIdent, + CONTEXT_IDENTIFIER: contextIdent + })]; + } + } + } + }; +}; + +var _babelHelperHoistVariables = require("babel-helper-hoist-variables"); + +var _babelHelperHoistVariables2 = _interopRequireDefault(_babelHelperHoistVariables); + +var _babelTemplate = require("babel-template"); + +var _babelTemplate2 = _interopRequireDefault(_babelTemplate); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var buildTemplate = (0, _babelTemplate2.default)("\n SYSTEM_REGISTER(MODULE_NAME, [SOURCES], function (EXPORT_IDENTIFIER, CONTEXT_IDENTIFIER) {\n \"use strict\";\n BEFORE_BODY;\n return {\n setters: [SETTERS],\n execute: function () {\n BODY;\n }\n };\n });\n"); + +var buildExportAll = (0, _babelTemplate2.default)("\n for (var KEY in TARGET) {\n if (KEY !== \"default\" && KEY !== \"__esModule\") EXPORT_OBJ[KEY] = TARGET[KEY];\n }\n"); + +var TYPE_IMPORT = "Import"; + +module.exports = exports["default"]; +},{"babel-helper-hoist-variables":50,"babel-runtime/core-js/get-iterator":56,"babel-runtime/core-js/object/create":61,"babel-runtime/core-js/symbol":65,"babel-template":75}],56:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/get-iterator"), __esModule: true }; +},{"core-js/library/fn/get-iterator":125}],57:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/json/stringify"), __esModule: true }; +},{"core-js/library/fn/json/stringify":126}],58:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/map"), __esModule: true }; +},{"core-js/library/fn/map":127}],59:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/number/max-safe-integer"), __esModule: true }; +},{"core-js/library/fn/number/max-safe-integer":128}],60:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/assign"), __esModule: true }; +},{"core-js/library/fn/object/assign":129}],61:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/create"), __esModule: true }; +},{"core-js/library/fn/object/create":130}],62:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/get-own-property-symbols"), __esModule: true }; +},{"core-js/library/fn/object/get-own-property-symbols":131}],63:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/keys"), __esModule: true }; +},{"core-js/library/fn/object/keys":132}],64:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/set-prototype-of"), __esModule: true }; +},{"core-js/library/fn/object/set-prototype-of":133}],65:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/symbol"), __esModule: true }; +},{"core-js/library/fn/symbol":135}],66:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/symbol/for"), __esModule: true }; +},{"core-js/library/fn/symbol/for":134}],67:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/symbol/iterator"), __esModule: true }; +},{"core-js/library/fn/symbol/iterator":136}],68:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/weak-map"), __esModule: true }; +},{"core-js/library/fn/weak-map":137}],69:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/weak-set"), __esModule: true }; +},{"core-js/library/fn/weak-set":138}],70:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +exports.default = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; +},{}],71:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _setPrototypeOf = require("../core-js/object/set-prototype-of"); + +var _setPrototypeOf2 = _interopRequireDefault(_setPrototypeOf); + +var _create = require("../core-js/object/create"); + +var _create2 = _interopRequireDefault(_create); + +var _typeof2 = require("../helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === "undefined" ? "undefined" : (0, _typeof3.default)(superClass))); + } + + subClass.prototype = (0, _create2.default)(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf2.default ? (0, _setPrototypeOf2.default)(subClass, superClass) : subClass.__proto__ = superClass; +}; +},{"../core-js/object/create":61,"../core-js/object/set-prototype-of":64,"../helpers/typeof":74}],72:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +exports.default = function (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; +}; +},{}],73:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _typeof2 = require("../helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && ((typeof call === "undefined" ? "undefined" : (0, _typeof3.default)(call)) === "object" || typeof call === "function") ? call : self; +}; +},{"../helpers/typeof":74}],74:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _iterator = require("../core-js/symbol/iterator"); + +var _iterator2 = _interopRequireDefault(_iterator); + +var _symbol = require("../core-js/symbol"); + +var _symbol2 = _interopRequireDefault(_symbol); + +var _typeof = typeof _symbol2.default === "function" && typeof _iterator2.default === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj; }; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = typeof _symbol2.default === "function" && _typeof(_iterator2.default) === "symbol" ? function (obj) { + return typeof obj === "undefined" ? "undefined" : _typeof(obj); +} : function (obj) { + return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj === "undefined" ? "undefined" : _typeof(obj); +}; +},{"../core-js/symbol":65,"../core-js/symbol/iterator":67}],75:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _symbol = require("babel-runtime/core-js/symbol"); + +var _symbol2 = _interopRequireDefault(_symbol); + +exports.default = function (code, opts) { + var stack = void 0; + try { + throw new Error(); + } catch (error) { + if (error.stack) { + stack = error.stack.split("\n").slice(1).join("\n"); + } + } + + opts = (0, _assign2.default)({ + allowReturnOutsideFunction: true, + allowSuperOutsideMethod: true, + preserveComments: false + }, opts); + + var _getAst = function getAst() { + var ast = void 0; + + try { + ast = babylon.parse(code, opts); + + ast = _babelTraverse2.default.removeProperties(ast, { preserveComments: opts.preserveComments }); + + _babelTraverse2.default.cheap(ast, function (node) { + node[FROM_TEMPLATE] = true; + }); + } catch (err) { + err.stack = err.stack + "from\n" + stack; + throw err; + } + + _getAst = function getAst() { + return ast; + }; + + return ast; + }; + + return function () { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return useTemplate(_getAst(), args); + }; +}; + +var _cloneDeep = require("lodash/cloneDeep"); + +var _cloneDeep2 = _interopRequireDefault(_cloneDeep); + +var _assign = require("lodash/assign"); + +var _assign2 = _interopRequireDefault(_assign); + +var _has = require("lodash/has"); + +var _has2 = _interopRequireDefault(_has); + +var _babelTraverse = require("babel-traverse"); + +var _babelTraverse2 = _interopRequireDefault(_babelTraverse); + +var _babylon = require("babylon"); + +var babylon = _interopRequireWildcard(_babylon); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var FROM_TEMPLATE = "_fromTemplate"; +var TEMPLATE_SKIP = (0, _symbol2.default)(); + +function useTemplate(ast, nodes) { + ast = (0, _cloneDeep2.default)(ast); + var _ast = ast, + program = _ast.program; + + + if (nodes.length) { + (0, _babelTraverse2.default)(ast, templateVisitor, null, nodes); + } + + if (program.body.length > 1) { + return program.body; + } else { + return program.body[0]; + } +} + +var templateVisitor = { + noScope: true, + + enter: function enter(path, args) { + var node = path.node; + + if (node[TEMPLATE_SKIP]) return path.skip(); + + if (t.isExpressionStatement(node)) { + node = node.expression; + } + + var replacement = void 0; + + if (t.isIdentifier(node) && node[FROM_TEMPLATE]) { + if ((0, _has2.default)(args[0], node.name)) { + replacement = args[0][node.name]; + } else if (node.name[0] === "$") { + var i = +node.name.slice(1); + if (args[i]) replacement = args[i]; + } + } + + if (replacement === null) { + path.remove(); + } + + if (replacement) { + replacement[TEMPLATE_SKIP] = true; + path.replaceInline(replacement); + } + }, + exit: function exit(_ref) { + var node = _ref.node; + + if (!node.loc) _babelTraverse2.default.clearNode(node); + } +}; +module.exports = exports["default"]; +},{"babel-runtime/core-js/symbol":65,"babel-traverse":79,"babel-types":112,"babylon":116,"lodash/assign":414,"lodash/cloneDeep":417,"lodash/has":428}],76:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.scope = exports.path = undefined; + +var _weakMap = require("babel-runtime/core-js/weak-map"); + +var _weakMap2 = _interopRequireDefault(_weakMap); + +exports.clear = clear; +exports.clearPath = clearPath; +exports.clearScope = clearScope; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var path = exports.path = new _weakMap2.default(); +var scope = exports.scope = new _weakMap2.default(); + +function clear() { + clearPath(); + clearScope(); +} + +function clearPath() { + exports.path = path = new _weakMap2.default(); +} + +function clearScope() { + exports.scope = scope = new _weakMap2.default(); +} +},{"babel-runtime/core-js/weak-map":68}],77:[function(require,module,exports){ +(function (process){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _path2 = require("./path"); + +var _path3 = _interopRequireDefault(_path2); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var testing = process.env.NODE_ENV === "test"; + +var TraversalContext = function () { + function TraversalContext(scope, opts, state, parentPath) { + (0, _classCallCheck3.default)(this, TraversalContext); + this.queue = null; + + this.parentPath = parentPath; + this.scope = scope; + this.state = state; + this.opts = opts; + } + + TraversalContext.prototype.shouldVisit = function shouldVisit(node) { + var opts = this.opts; + if (opts.enter || opts.exit) return true; + + if (opts[node.type]) return true; + + var keys = t.VISITOR_KEYS[node.type]; + if (!keys || !keys.length) return false; + + for (var _iterator = keys, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var key = _ref; + + if (node[key]) return true; + } + + return false; + }; + + TraversalContext.prototype.create = function create(node, obj, key, listKey) { + return _path3.default.get({ + parentPath: this.parentPath, + parent: node, + container: obj, + key: key, + listKey: listKey + }); + }; + + TraversalContext.prototype.maybeQueue = function maybeQueue(path, notPriority) { + if (this.trap) { + throw new Error("Infinite cycle detected"); + } + + if (this.queue) { + if (notPriority) { + this.queue.push(path); + } else { + this.priorityQueue.push(path); + } + } + }; + + TraversalContext.prototype.visitMultiple = function visitMultiple(container, parent, listKey) { + if (container.length === 0) return false; + + var queue = []; + + for (var key = 0; key < container.length; key++) { + var node = container[key]; + if (node && this.shouldVisit(node)) { + queue.push(this.create(parent, container, key, listKey)); + } + } + + return this.visitQueue(queue); + }; + + TraversalContext.prototype.visitSingle = function visitSingle(node, key) { + if (this.shouldVisit(node[key])) { + return this.visitQueue([this.create(node, node, key)]); + } else { + return false; + } + }; + + TraversalContext.prototype.visitQueue = function visitQueue(queue) { + this.queue = queue; + this.priorityQueue = []; + + var visited = []; + var stop = false; + + for (var _iterator2 = queue, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var path = _ref2; + + path.resync(); + + if (path.contexts.length === 0 || path.contexts[path.contexts.length - 1] !== this) { + path.pushContext(this); + } + + if (path.key === null) continue; + + if (testing && queue.length >= 10000) { + this.trap = true; + } + + if (visited.indexOf(path.node) >= 0) continue; + visited.push(path.node); + + if (path.visit()) { + stop = true; + break; + } + + if (this.priorityQueue.length) { + stop = this.visitQueue(this.priorityQueue); + this.priorityQueue = []; + this.queue = queue; + if (stop) break; + } + } + + for (var _iterator3 = queue, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var _path = _ref3; + + _path.popContext(); + } + + this.queue = null; + + return stop; + }; + + TraversalContext.prototype.visit = function visit(node, key) { + var nodes = node[key]; + if (!nodes) return false; + + if (Array.isArray(nodes)) { + return this.visitMultiple(nodes, node, key); + } else { + return this.visitSingle(node, key); + } + }; + + return TraversalContext; +}(); + +exports.default = TraversalContext; +module.exports = exports["default"]; +}).call(this,require('_process')) +},{"./path":86,"_process":471,"babel-runtime/core-js/get-iterator":56,"babel-runtime/helpers/classCallCheck":70,"babel-types":112}],78:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var Hub = function Hub(file, options) { + (0, _classCallCheck3.default)(this, Hub); + + this.file = file; + this.options = options; +}; + +exports.default = Hub; +module.exports = exports["default"]; +},{"babel-runtime/helpers/classCallCheck":70}],79:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.visitors = exports.Hub = exports.Scope = exports.NodePath = undefined; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _path = require("./path"); + +Object.defineProperty(exports, "NodePath", { + enumerable: true, + get: function get() { + return _interopRequireDefault(_path).default; + } +}); + +var _scope = require("./scope"); + +Object.defineProperty(exports, "Scope", { + enumerable: true, + get: function get() { + return _interopRequireDefault(_scope).default; + } +}); + +var _hub = require("./hub"); + +Object.defineProperty(exports, "Hub", { + enumerable: true, + get: function get() { + return _interopRequireDefault(_hub).default; + } +}); +exports.default = traverse; + +var _context = require("./context"); + +var _context2 = _interopRequireDefault(_context); + +var _visitors = require("./visitors"); + +var visitors = _interopRequireWildcard(_visitors); + +var _babelMessages = require("babel-messages"); + +var messages = _interopRequireWildcard(_babelMessages); + +var _includes = require("lodash/includes"); + +var _includes2 = _interopRequireDefault(_includes); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +var _cache = require("./cache"); + +var cache = _interopRequireWildcard(_cache); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.visitors = visitors; +function traverse(parent, opts, scope, state, parentPath) { + if (!parent) return; + if (!opts) opts = {}; + + if (!opts.noScope && !scope) { + if (parent.type !== "Program" && parent.type !== "File") { + throw new Error(messages.get("traverseNeedsParent", parent.type)); + } + } + + visitors.explode(opts); + + traverse.node(parent, opts, scope, state, parentPath); +} + +traverse.visitors = visitors; +traverse.verify = visitors.verify; +traverse.explode = visitors.explode; + +traverse.NodePath = require("./path"); +traverse.Scope = require("./scope"); +traverse.Hub = require("./hub"); + +traverse.cheap = function (node, enter) { + return t.traverseFast(node, enter); +}; + +traverse.node = function (node, opts, scope, state, parentPath, skipKeys) { + var keys = t.VISITOR_KEYS[node.type]; + if (!keys) return; + + var context = new _context2.default(scope, opts, state, parentPath); + for (var _iterator = keys, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var key = _ref; + + if (skipKeys && skipKeys[key]) continue; + if (context.visit(node, key)) return; + } +}; + +traverse.clearNode = function (node, opts) { + t.removeProperties(node, opts); + + cache.path.delete(node); +}; + +traverse.removeProperties = function (tree, opts) { + t.traverseFast(tree, traverse.clearNode, opts); + return tree; +}; + +function hasBlacklistedType(path, state) { + if (path.node.type === state.type) { + state.has = true; + path.stop(); + } +} + +traverse.hasType = function (tree, scope, type, blacklistTypes) { + if ((0, _includes2.default)(blacklistTypes, tree.type)) return false; + + if (tree.type === type) return true; + + var state = { + has: false, + type: type + }; + + traverse(tree, { + blacklist: blacklistTypes, + enter: hasBlacklistedType + }, scope, state); + + return state.has; +}; + +traverse.clearCache = function () { + cache.clear(); +}; + +traverse.clearCache.clearPath = cache.clearPath; +traverse.clearCache.clearScope = cache.clearScope; + +traverse.copyCache = function (source, destination) { + if (cache.path.has(source)) { + cache.path.set(destination, cache.path.get(source)); + } +}; +},{"./cache":76,"./context":77,"./hub":78,"./path":86,"./scope":98,"./visitors":100,"babel-messages":53,"babel-runtime/core-js/get-iterator":56,"babel-types":112,"lodash/includes":431}],80:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.findParent = findParent; +exports.find = find; +exports.getFunctionParent = getFunctionParent; +exports.getStatementParent = getStatementParent; +exports.getEarliestCommonAncestorFrom = getEarliestCommonAncestorFrom; +exports.getDeepestCommonAncestorFrom = getDeepestCommonAncestorFrom; +exports.getAncestry = getAncestry; +exports.isAncestor = isAncestor; +exports.isDescendant = isDescendant; +exports.inType = inType; +exports.inShadow = inShadow; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +var _index = require("./index"); + +var _index2 = _interopRequireDefault(_index); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function findParent(callback) { + var path = this; + while (path = path.parentPath) { + if (callback(path)) return path; + } + return null; +} + +function find(callback) { + var path = this; + do { + if (callback(path)) return path; + } while (path = path.parentPath); + return null; +} + +function getFunctionParent() { + return this.findParent(function (path) { + return path.isFunction() || path.isProgram(); + }); +} + +function getStatementParent() { + var path = this; + do { + if (Array.isArray(path.container)) { + return path; + } + } while (path = path.parentPath); +} + +function getEarliestCommonAncestorFrom(paths) { + return this.getDeepestCommonAncestorFrom(paths, function (deepest, i, ancestries) { + var earliest = void 0; + var keys = t.VISITOR_KEYS[deepest.type]; + + for (var _iterator = ancestries, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var ancestry = _ref; + + var path = ancestry[i + 1]; + + if (!earliest) { + earliest = path; + continue; + } + + if (path.listKey && earliest.listKey === path.listKey) { + if (path.key < earliest.key) { + earliest = path; + continue; + } + } + + var earliestKeyIndex = keys.indexOf(earliest.parentKey); + var currentKeyIndex = keys.indexOf(path.parentKey); + if (earliestKeyIndex > currentKeyIndex) { + earliest = path; + } + } + + return earliest; + }); +} + +function getDeepestCommonAncestorFrom(paths, filter) { + var _this = this; + + if (!paths.length) { + return this; + } + + if (paths.length === 1) { + return paths[0]; + } + + var minDepth = Infinity; + + var lastCommonIndex = void 0, + lastCommon = void 0; + + var ancestries = paths.map(function (path) { + var ancestry = []; + + do { + ancestry.unshift(path); + } while ((path = path.parentPath) && path !== _this); + + if (ancestry.length < minDepth) { + minDepth = ancestry.length; + } + + return ancestry; + }); + + var first = ancestries[0]; + + depthLoop: for (var i = 0; i < minDepth; i++) { + var shouldMatch = first[i]; + + for (var _iterator2 = ancestries, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var ancestry = _ref2; + + if (ancestry[i] !== shouldMatch) { + break depthLoop; + } + } + + lastCommonIndex = i; + lastCommon = shouldMatch; + } + + if (lastCommon) { + if (filter) { + return filter(lastCommon, lastCommonIndex, ancestries); + } else { + return lastCommon; + } + } else { + throw new Error("Couldn't find intersection"); + } +} + +function getAncestry() { + var path = this; + var paths = []; + do { + paths.push(path); + } while (path = path.parentPath); + return paths; +} + +function isAncestor(maybeDescendant) { + return maybeDescendant.isDescendant(this); +} + +function isDescendant(maybeAncestor) { + return !!this.findParent(function (parent) { + return parent === maybeAncestor; + }); +} + +function inType() { + var path = this; + while (path) { + for (var _iterator3 = arguments, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var type = _ref3; + + if (path.node.type === type) return true; + } + path = path.parentPath; + } + + return false; +} + +function inShadow(key) { + var parentFn = this.isFunction() ? this : this.findParent(function (p) { + return p.isFunction(); + }); + if (!parentFn) return; + + if (parentFn.isFunctionExpression() || parentFn.isFunctionDeclaration()) { + var shadow = parentFn.node.shadow; + + if (shadow && (!key || shadow[key] !== false)) { + return parentFn; + } + } else if (parentFn.isArrowFunctionExpression()) { + return parentFn; + } + + return null; +} +},{"./index":86,"babel-runtime/core-js/get-iterator":56,"babel-types":112}],81:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.shareCommentsWithSiblings = shareCommentsWithSiblings; +exports.addComment = addComment; +exports.addComments = addComments; +function shareCommentsWithSiblings() { + if (typeof this.key === "string") return; + + var node = this.node; + if (!node) return; + + var trailing = node.trailingComments; + var leading = node.leadingComments; + if (!trailing && !leading) return; + + var prev = this.getSibling(this.key - 1); + var next = this.getSibling(this.key + 1); + + if (!prev.node) prev = next; + if (!next.node) next = prev; + + prev.addComments("trailing", leading); + next.addComments("leading", trailing); +} + +function addComment(type, content, line) { + this.addComments(type, [{ + type: line ? "CommentLine" : "CommentBlock", + value: content + }]); +} + +function addComments(type, comments) { + if (!comments) return; + + var node = this.node; + if (!node) return; + + var key = type + "Comments"; + + if (node[key]) { + node[key] = node[key].concat(comments); + } else { + node[key] = comments; + } +} +},{}],82:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.call = call; +exports._call = _call; +exports.isBlacklisted = isBlacklisted; +exports.visit = visit; +exports.skip = skip; +exports.skipKey = skipKey; +exports.stop = stop; +exports.setScope = setScope; +exports.setContext = setContext; +exports.resync = resync; +exports._resyncParent = _resyncParent; +exports._resyncKey = _resyncKey; +exports._resyncList = _resyncList; +exports._resyncRemoved = _resyncRemoved; +exports.popContext = popContext; +exports.pushContext = pushContext; +exports.setup = setup; +exports.setKey = setKey; +exports.requeue = requeue; +exports._getQueueContexts = _getQueueContexts; + +var _index = require("../index"); + +var _index2 = _interopRequireDefault(_index); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function call(key) { + var opts = this.opts; + + this.debug(function () { + return key; + }); + + if (this.node) { + if (this._call(opts[key])) return true; + } + + if (this.node) { + return this._call(opts[this.node.type] && opts[this.node.type][key]); + } + + return false; +} + +function _call(fns) { + if (!fns) return false; + + for (var _iterator = fns, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var fn = _ref; + + if (!fn) continue; + + var node = this.node; + if (!node) return true; + + var ret = fn.call(this.state, this, this.state); + if (ret) throw new Error("Unexpected return value from visitor method " + fn); + + if (this.node !== node) return true; + + if (this.shouldStop || this.shouldSkip || this.removed) return true; + } + + return false; +} + +function isBlacklisted() { + var blacklist = this.opts.blacklist; + return blacklist && blacklist.indexOf(this.node.type) > -1; +} + +function visit() { + if (!this.node) { + return false; + } + + if (this.isBlacklisted()) { + return false; + } + + if (this.opts.shouldSkip && this.opts.shouldSkip(this)) { + return false; + } + + if (this.call("enter") || this.shouldSkip) { + this.debug(function () { + return "Skip..."; + }); + return this.shouldStop; + } + + this.debug(function () { + return "Recursing into..."; + }); + _index2.default.node(this.node, this.opts, this.scope, this.state, this, this.skipKeys); + + this.call("exit"); + + return this.shouldStop; +} + +function skip() { + this.shouldSkip = true; +} + +function skipKey(key) { + this.skipKeys[key] = true; +} + +function stop() { + this.shouldStop = true; + this.shouldSkip = true; +} + +function setScope() { + if (this.opts && this.opts.noScope) return; + + var target = this.context && this.context.scope; + + if (!target) { + var path = this.parentPath; + while (path && !target) { + if (path.opts && path.opts.noScope) return; + + target = path.scope; + path = path.parentPath; + } + } + + this.scope = this.getScope(target); + if (this.scope) this.scope.init(); +} + +function setContext(context) { + this.shouldSkip = false; + this.shouldStop = false; + this.removed = false; + this.skipKeys = {}; + + if (context) { + this.context = context; + this.state = context.state; + this.opts = context.opts; + } + + this.setScope(); + + return this; +} + +function resync() { + if (this.removed) return; + + this._resyncParent(); + this._resyncList(); + this._resyncKey(); +} + +function _resyncParent() { + if (this.parentPath) { + this.parent = this.parentPath.node; + } +} + +function _resyncKey() { + if (!this.container) return; + + if (this.node === this.container[this.key]) return; + + if (Array.isArray(this.container)) { + for (var i = 0; i < this.container.length; i++) { + if (this.container[i] === this.node) { + return this.setKey(i); + } + } + } else { + for (var key in this.container) { + if (this.container[key] === this.node) { + return this.setKey(key); + } + } + } + + this.key = null; +} + +function _resyncList() { + if (!this.parent || !this.inList) return; + + var newContainer = this.parent[this.listKey]; + if (this.container === newContainer) return; + + this.container = newContainer || null; +} + +function _resyncRemoved() { + if (this.key == null || !this.container || this.container[this.key] !== this.node) { + this._markRemoved(); + } +} + +function popContext() { + this.contexts.pop(); + this.setContext(this.contexts[this.contexts.length - 1]); +} + +function pushContext(context) { + this.contexts.push(context); + this.setContext(context); +} + +function setup(parentPath, container, listKey, key) { + this.inList = !!listKey; + this.listKey = listKey; + this.parentKey = listKey || key; + this.container = container; + + this.parentPath = parentPath || this.parentPath; + this.setKey(key); +} + +function setKey(key) { + this.key = key; + this.node = this.container[this.key]; + this.type = this.node && this.node.type; +} + +function requeue() { + var pathToQueue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this; + + if (pathToQueue.removed) return; + + var contexts = this.contexts; + + for (var _iterator2 = contexts, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var context = _ref2; + + context.maybeQueue(pathToQueue); + } +} + +function _getQueueContexts() { + var path = this; + var contexts = this.contexts; + while (!contexts.length) { + path = path.parentPath; + contexts = path.contexts; + } + return contexts; +} +},{"../index":79,"babel-runtime/core-js/get-iterator":56}],83:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.toComputedKey = toComputedKey; +exports.ensureBlock = ensureBlock; +exports.arrowFunctionToShadowed = arrowFunctionToShadowed; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function toComputedKey() { + var node = this.node; + + var key = void 0; + if (this.isMemberExpression()) { + key = node.property; + } else if (this.isProperty() || this.isMethod()) { + key = node.key; + } else { + throw new ReferenceError("todo"); + } + + if (!node.computed) { + if (t.isIdentifier(key)) key = t.stringLiteral(key.name); + } + + return key; +} + +function ensureBlock() { + return t.ensureBlock(this.node); +} + +function arrowFunctionToShadowed() { + if (!this.isArrowFunctionExpression()) return; + + this.ensureBlock(); + + var node = this.node; + + node.expression = false; + node.type = "FunctionExpression"; + node.shadow = node.shadow || true; +} +},{"babel-types":112}],84:[function(require,module,exports){ +(function (global){ +"use strict"; + +exports.__esModule = true; + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _map = require("babel-runtime/core-js/map"); + +var _map2 = _interopRequireDefault(_map); + +exports.evaluateTruthy = evaluateTruthy; +exports.evaluate = evaluate; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var VALID_CALLEES = ["String", "Number", "Math"]; +var INVALID_METHODS = ["random"]; + +function evaluateTruthy() { + var res = this.evaluate(); + if (res.confident) return !!res.value; +} + +function evaluate() { + var confident = true; + var deoptPath = void 0; + var seen = new _map2.default(); + + function deopt(path) { + if (!confident) return; + deoptPath = path; + confident = false; + } + + var value = evaluate(this); + if (!confident) value = undefined; + return { + confident: confident, + deopt: deoptPath, + value: value + }; + + function evaluate(path) { + var node = path.node; + + + if (seen.has(node)) { + var existing = seen.get(node); + if (existing.resolved) { + return existing.value; + } else { + deopt(path); + return; + } + } else { + var item = { resolved: false }; + seen.set(node, item); + + var val = _evaluate(path); + if (confident) { + item.resolved = true; + item.value = val; + } + return val; + } + } + + function _evaluate(path) { + if (!confident) return; + + var node = path.node; + + + if (path.isSequenceExpression()) { + var exprs = path.get("expressions"); + return evaluate(exprs[exprs.length - 1]); + } + + if (path.isStringLiteral() || path.isNumericLiteral() || path.isBooleanLiteral()) { + return node.value; + } + + if (path.isNullLiteral()) { + return null; + } + + if (path.isTemplateLiteral()) { + var str = ""; + + var i = 0; + var _exprs = path.get("expressions"); + + for (var _iterator = node.quasis, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var elem = _ref; + + if (!confident) break; + + str += elem.value.cooked; + + var expr = _exprs[i++]; + if (expr) str += String(evaluate(expr)); + } + + if (!confident) return; + return str; + } + + if (path.isConditionalExpression()) { + var testResult = evaluate(path.get("test")); + if (!confident) return; + if (testResult) { + return evaluate(path.get("consequent")); + } else { + return evaluate(path.get("alternate")); + } + } + + if (path.isExpressionWrapper()) { + return evaluate(path.get("expression")); + } + + if (path.isMemberExpression() && !path.parentPath.isCallExpression({ callee: node })) { + var property = path.get("property"); + var object = path.get("object"); + + if (object.isLiteral() && property.isIdentifier()) { + var _value = object.node.value; + var type = typeof _value === "undefined" ? "undefined" : (0, _typeof3.default)(_value); + if (type === "number" || type === "string") { + return _value[property.node.name]; + } + } + } + + if (path.isReferencedIdentifier()) { + var binding = path.scope.getBinding(node.name); + + if (binding && binding.constantViolations.length > 0) { + return deopt(binding.path); + } + + if (binding && path.node.start < binding.path.node.end) { + return deopt(binding.path); + } + + if (binding && binding.hasValue) { + return binding.value; + } else { + if (node.name === "undefined") { + return binding ? deopt(binding.path) : undefined; + } else if (node.name === "Infinity") { + return binding ? deopt(binding.path) : Infinity; + } else if (node.name === "NaN") { + return binding ? deopt(binding.path) : NaN; + } + + var resolved = path.resolve(); + if (resolved === path) { + return deopt(path); + } else { + return evaluate(resolved); + } + } + } + + if (path.isUnaryExpression({ prefix: true })) { + if (node.operator === "void") { + return undefined; + } + + var argument = path.get("argument"); + if (node.operator === "typeof" && (argument.isFunction() || argument.isClass())) { + return "function"; + } + + var arg = evaluate(argument); + if (!confident) return; + switch (node.operator) { + case "!": + return !arg; + case "+": + return +arg; + case "-": + return -arg; + case "~": + return ~arg; + case "typeof": + return typeof arg === "undefined" ? "undefined" : (0, _typeof3.default)(arg); + } + } + + if (path.isArrayExpression()) { + var arr = []; + var elems = path.get("elements"); + for (var _iterator2 = elems, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var _elem = _ref2; + + _elem = _elem.evaluate(); + + if (_elem.confident) { + arr.push(_elem.value); + } else { + return deopt(_elem); + } + } + return arr; + } + + if (path.isObjectExpression()) { + var obj = {}; + var props = path.get("properties"); + for (var _iterator3 = props, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var prop = _ref3; + + if (prop.isObjectMethod() || prop.isSpreadProperty()) { + return deopt(prop); + } + var keyPath = prop.get("key"); + var key = keyPath; + if (prop.node.computed) { + key = key.evaluate(); + if (!key.confident) { + return deopt(keyPath); + } + key = key.value; + } else if (key.isIdentifier()) { + key = key.node.name; + } else { + key = key.node.value; + } + var valuePath = prop.get("value"); + var _value2 = valuePath.evaluate(); + if (!_value2.confident) { + return deopt(valuePath); + } + _value2 = _value2.value; + obj[key] = _value2; + } + return obj; + } + + if (path.isLogicalExpression()) { + var wasConfident = confident; + var left = evaluate(path.get("left")); + var leftConfident = confident; + confident = wasConfident; + var right = evaluate(path.get("right")); + var rightConfident = confident; + confident = leftConfident && rightConfident; + + switch (node.operator) { + case "||": + if (left && leftConfident) { + confident = true; + return left; + } + + if (!confident) return; + + return left || right; + case "&&": + if (!left && leftConfident || !right && rightConfident) { + confident = true; + } + + if (!confident) return; + + return left && right; + } + } + + if (path.isBinaryExpression()) { + var _left = evaluate(path.get("left")); + if (!confident) return; + var _right = evaluate(path.get("right")); + if (!confident) return; + + switch (node.operator) { + case "-": + return _left - _right; + case "+": + return _left + _right; + case "/": + return _left / _right; + case "*": + return _left * _right; + case "%": + return _left % _right; + case "**": + return Math.pow(_left, _right); + case "<": + return _left < _right; + case ">": + return _left > _right; + case "<=": + return _left <= _right; + case ">=": + return _left >= _right; + case "==": + return _left == _right; + case "!=": + return _left != _right; + case "===": + return _left === _right; + case "!==": + return _left !== _right; + case "|": + return _left | _right; + case "&": + return _left & _right; + case "^": + return _left ^ _right; + case "<<": + return _left << _right; + case ">>": + return _left >> _right; + case ">>>": + return _left >>> _right; + } + } + + if (path.isCallExpression()) { + var callee = path.get("callee"); + var context = void 0; + var func = void 0; + + if (callee.isIdentifier() && !path.scope.getBinding(callee.node.name, true) && VALID_CALLEES.indexOf(callee.node.name) >= 0) { + func = global[node.callee.name]; + } + + if (callee.isMemberExpression()) { + var _object = callee.get("object"); + var _property = callee.get("property"); + + if (_object.isIdentifier() && _property.isIdentifier() && VALID_CALLEES.indexOf(_object.node.name) >= 0 && INVALID_METHODS.indexOf(_property.node.name) < 0) { + context = global[_object.node.name]; + func = context[_property.node.name]; + } + + if (_object.isLiteral() && _property.isIdentifier()) { + var _type = (0, _typeof3.default)(_object.node.value); + if (_type === "string" || _type === "number") { + context = _object.node.value; + func = context[_property.node.name]; + } + } + } + + if (func) { + var args = path.get("arguments").map(evaluate); + if (!confident) return; + + return func.apply(context, args); + } + } + + deopt(path); + } +} +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"babel-runtime/core-js/get-iterator":56,"babel-runtime/core-js/map":58,"babel-runtime/helpers/typeof":74}],85:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _create = require("babel-runtime/core-js/object/create"); + +var _create2 = _interopRequireDefault(_create); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.getStatementParent = getStatementParent; +exports.getOpposite = getOpposite; +exports.getCompletionRecords = getCompletionRecords; +exports.getSibling = getSibling; +exports.getPrevSibling = getPrevSibling; +exports.getNextSibling = getNextSibling; +exports.getAllNextSiblings = getAllNextSiblings; +exports.getAllPrevSiblings = getAllPrevSiblings; +exports.get = get; +exports._getKey = _getKey; +exports._getPattern = _getPattern; +exports.getBindingIdentifiers = getBindingIdentifiers; +exports.getOuterBindingIdentifiers = getOuterBindingIdentifiers; +exports.getBindingIdentifierPaths = getBindingIdentifierPaths; +exports.getOuterBindingIdentifierPaths = getOuterBindingIdentifierPaths; + +var _index = require("./index"); + +var _index2 = _interopRequireDefault(_index); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getStatementParent() { + var path = this; + + do { + if (!path.parentPath || Array.isArray(path.container) && path.isStatement()) { + break; + } else { + path = path.parentPath; + } + } while (path); + + if (path && (path.isProgram() || path.isFile())) { + throw new Error("File/Program node, we can't possibly find a statement parent to this"); + } + + return path; +} + +function getOpposite() { + if (this.key === "left") { + return this.getSibling("right"); + } else if (this.key === "right") { + return this.getSibling("left"); + } +} + +function getCompletionRecords() { + var paths = []; + + var add = function add(path) { + if (path) paths = paths.concat(path.getCompletionRecords()); + }; + + if (this.isIfStatement()) { + add(this.get("consequent")); + add(this.get("alternate")); + } else if (this.isDoExpression() || this.isFor() || this.isWhile()) { + add(this.get("body")); + } else if (this.isProgram() || this.isBlockStatement()) { + add(this.get("body").pop()); + } else if (this.isFunction()) { + return this.get("body").getCompletionRecords(); + } else if (this.isTryStatement()) { + add(this.get("block")); + add(this.get("handler")); + add(this.get("finalizer")); + } else { + paths.push(this); + } + + return paths; +} + +function getSibling(key) { + return _index2.default.get({ + parentPath: this.parentPath, + parent: this.parent, + container: this.container, + listKey: this.listKey, + key: key + }); +} + +function getPrevSibling() { + return this.getSibling(this.key - 1); +} + +function getNextSibling() { + return this.getSibling(this.key + 1); +} + +function getAllNextSiblings() { + var _key = this.key; + var sibling = this.getSibling(++_key); + var siblings = []; + while (sibling.node) { + siblings.push(sibling); + sibling = this.getSibling(++_key); + } + return siblings; +} + +function getAllPrevSiblings() { + var _key = this.key; + var sibling = this.getSibling(--_key); + var siblings = []; + while (sibling.node) { + siblings.push(sibling); + sibling = this.getSibling(--_key); + } + return siblings; +} + +function get(key, context) { + if (context === true) context = this.context; + var parts = key.split("."); + if (parts.length === 1) { + return this._getKey(key, context); + } else { + return this._getPattern(parts, context); + } +} + +function _getKey(key, context) { + var _this = this; + + var node = this.node; + var container = node[key]; + + if (Array.isArray(container)) { + return container.map(function (_, i) { + return _index2.default.get({ + listKey: key, + parentPath: _this, + parent: node, + container: container, + key: i + }).setContext(context); + }); + } else { + return _index2.default.get({ + parentPath: this, + parent: node, + container: node, + key: key + }).setContext(context); + } +} + +function _getPattern(parts, context) { + var path = this; + for (var _iterator = parts, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var part = _ref; + + if (part === ".") { + path = path.parentPath; + } else { + if (Array.isArray(path)) { + path = path[part]; + } else { + path = path.get(part, context); + } + } + } + return path; +} + +function getBindingIdentifiers(duplicates) { + return t.getBindingIdentifiers(this.node, duplicates); +} + +function getOuterBindingIdentifiers(duplicates) { + return t.getOuterBindingIdentifiers(this.node, duplicates); +} + +function getBindingIdentifierPaths() { + var duplicates = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var outerOnly = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + var path = this; + var search = [].concat(path); + var ids = (0, _create2.default)(null); + + while (search.length) { + var id = search.shift(); + if (!id) continue; + if (!id.node) continue; + + var keys = t.getBindingIdentifiers.keys[id.node.type]; + + if (id.isIdentifier()) { + if (duplicates) { + var _ids = ids[id.node.name] = ids[id.node.name] || []; + _ids.push(id); + } else { + ids[id.node.name] = id; + } + continue; + } + + if (id.isExportDeclaration()) { + var declaration = id.get("declaration"); + if (declaration.isDeclaration()) { + search.push(declaration); + } + continue; + } + + if (outerOnly) { + if (id.isFunctionDeclaration()) { + search.push(id.get("id")); + continue; + } + if (id.isFunctionExpression()) { + continue; + } + } + + if (keys) { + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var child = id.get(key); + if (Array.isArray(child) || child.node) { + search = search.concat(child); + } + } + } + } + + return ids; +} + +function getOuterBindingIdentifierPaths(duplicates) { + return this.getBindingIdentifierPaths(duplicates, true); +} +},{"./index":86,"babel-runtime/core-js/get-iterator":56,"babel-runtime/core-js/object/create":61,"babel-types":112}],86:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _virtualTypes = require("./lib/virtual-types"); + +var virtualTypes = _interopRequireWildcard(_virtualTypes); + +var _debug2 = require("debug"); + +var _debug3 = _interopRequireDefault(_debug2); + +var _invariant = require("invariant"); + +var _invariant2 = _interopRequireDefault(_invariant); + +var _index = require("../index"); + +var _index2 = _interopRequireDefault(_index); + +var _assign = require("lodash/assign"); + +var _assign2 = _interopRequireDefault(_assign); + +var _scope = require("../scope"); + +var _scope2 = _interopRequireDefault(_scope); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +var _cache = require("../cache"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var _debug = (0, _debug3.default)("babel"); + +var NodePath = function () { + function NodePath(hub, parent) { + (0, _classCallCheck3.default)(this, NodePath); + + this.parent = parent; + this.hub = hub; + this.contexts = []; + this.data = {}; + this.shouldSkip = false; + this.shouldStop = false; + this.removed = false; + this.state = null; + this.opts = null; + this.skipKeys = null; + this.parentPath = null; + this.context = null; + this.container = null; + this.listKey = null; + this.inList = false; + this.parentKey = null; + this.key = null; + this.node = null; + this.scope = null; + this.type = null; + this.typeAnnotation = null; + } + + NodePath.get = function get(_ref) { + var hub = _ref.hub, + parentPath = _ref.parentPath, + parent = _ref.parent, + container = _ref.container, + listKey = _ref.listKey, + key = _ref.key; + + if (!hub && parentPath) { + hub = parentPath.hub; + } + + (0, _invariant2.default)(parent, "To get a node path the parent needs to exist"); + + var targetNode = container[key]; + + var paths = _cache.path.get(parent) || []; + if (!_cache.path.has(parent)) { + _cache.path.set(parent, paths); + } + + var path = void 0; + + for (var i = 0; i < paths.length; i++) { + var pathCheck = paths[i]; + if (pathCheck.node === targetNode) { + path = pathCheck; + break; + } + } + + if (!path) { + path = new NodePath(hub, parent); + paths.push(path); + } + + path.setup(parentPath, container, listKey, key); + + return path; + }; + + NodePath.prototype.getScope = function getScope(scope) { + var ourScope = scope; + + if (this.isScope()) { + ourScope = new _scope2.default(this, scope); + } + + return ourScope; + }; + + NodePath.prototype.setData = function setData(key, val) { + return this.data[key] = val; + }; + + NodePath.prototype.getData = function getData(key, def) { + var val = this.data[key]; + if (!val && def) val = this.data[key] = def; + return val; + }; + + NodePath.prototype.buildCodeFrameError = function buildCodeFrameError(msg) { + var Error = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : SyntaxError; + + return this.hub.file.buildCodeFrameError(this.node, msg, Error); + }; + + NodePath.prototype.traverse = function traverse(visitor, state) { + (0, _index2.default)(this.node, visitor, this.scope, state, this); + }; + + NodePath.prototype.mark = function mark(type, message) { + this.hub.file.metadata.marked.push({ + type: type, + message: message, + loc: this.node.loc + }); + }; + + NodePath.prototype.set = function set(key, node) { + t.validate(this.node, key, node); + this.node[key] = node; + }; + + NodePath.prototype.getPathLocation = function getPathLocation() { + var parts = []; + var path = this; + do { + var key = path.key; + if (path.inList) key = path.listKey + "[" + key + "]"; + parts.unshift(key); + } while (path = path.parentPath); + return parts.join("."); + }; + + NodePath.prototype.debug = function debug(buildMessage) { + if (!_debug.enabled) return; + _debug(this.getPathLocation() + " " + this.type + ": " + buildMessage()); + }; + + return NodePath; +}(); + +exports.default = NodePath; + + +(0, _assign2.default)(NodePath.prototype, require("./ancestry")); +(0, _assign2.default)(NodePath.prototype, require("./inference")); +(0, _assign2.default)(NodePath.prototype, require("./replacement")); +(0, _assign2.default)(NodePath.prototype, require("./evaluation")); +(0, _assign2.default)(NodePath.prototype, require("./conversion")); +(0, _assign2.default)(NodePath.prototype, require("./introspection")); +(0, _assign2.default)(NodePath.prototype, require("./context")); +(0, _assign2.default)(NodePath.prototype, require("./removal")); +(0, _assign2.default)(NodePath.prototype, require("./modification")); +(0, _assign2.default)(NodePath.prototype, require("./family")); +(0, _assign2.default)(NodePath.prototype, require("./comments")); + +var _loop2 = function _loop2() { + if (_isArray) { + if (_i >= _iterator.length) return "break"; + _ref2 = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) return "break"; + _ref2 = _i.value; + } + + var type = _ref2; + + var typeKey = "is" + type; + NodePath.prototype[typeKey] = function (opts) { + return t[typeKey](this.node, opts); + }; + + NodePath.prototype["assert" + type] = function (opts) { + if (!this[typeKey](opts)) { + throw new TypeError("Expected node path of type " + type); + } + }; +}; + +for (var _iterator = t.TYPES, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref2; + + var _ret2 = _loop2(); + + if (_ret2 === "break") break; +} + +var _loop = function _loop(type) { + if (type[0] === "_") return "continue"; + if (t.TYPES.indexOf(type) < 0) t.TYPES.push(type); + + var virtualType = virtualTypes[type]; + + NodePath.prototype["is" + type] = function (opts) { + return virtualType.checkPath(this, opts); + }; +}; + +for (var type in virtualTypes) { + var _ret = _loop(type); + + if (_ret === "continue") continue; +} +module.exports = exports["default"]; +},{"../cache":76,"../index":79,"../scope":98,"./ancestry":80,"./comments":81,"./context":82,"./conversion":83,"./evaluation":84,"./family":85,"./inference":87,"./introspection":90,"./lib/virtual-types":93,"./modification":94,"./removal":95,"./replacement":96,"babel-runtime/core-js/get-iterator":56,"babel-runtime/helpers/classCallCheck":70,"babel-types":112,"debug":232,"invariant":245,"lodash/assign":414}],87:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.getTypeAnnotation = getTypeAnnotation; +exports._getTypeAnnotation = _getTypeAnnotation; +exports.isBaseType = isBaseType; +exports.couldBeBaseType = couldBeBaseType; +exports.baseTypeStrictlyMatches = baseTypeStrictlyMatches; +exports.isGenericType = isGenericType; + +var _inferers = require("./inferers"); + +var inferers = _interopRequireWildcard(_inferers); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getTypeAnnotation() { + if (this.typeAnnotation) return this.typeAnnotation; + + var type = this._getTypeAnnotation() || t.anyTypeAnnotation(); + if (t.isTypeAnnotation(type)) type = type.typeAnnotation; + return this.typeAnnotation = type; +} + +function _getTypeAnnotation() { + var node = this.node; + + if (!node) { + if (this.key === "init" && this.parentPath.isVariableDeclarator()) { + var declar = this.parentPath.parentPath; + var declarParent = declar.parentPath; + + if (declar.key === "left" && declarParent.isForInStatement()) { + return t.stringTypeAnnotation(); + } + + if (declar.key === "left" && declarParent.isForOfStatement()) { + return t.anyTypeAnnotation(); + } + + return t.voidTypeAnnotation(); + } else { + return; + } + } + + if (node.typeAnnotation) { + return node.typeAnnotation; + } + + var inferer = inferers[node.type]; + if (inferer) { + return inferer.call(this, node); + } + + inferer = inferers[this.parentPath.type]; + if (inferer && inferer.validParent) { + return this.parentPath.getTypeAnnotation(); + } +} + +function isBaseType(baseName, soft) { + return _isBaseType(baseName, this.getTypeAnnotation(), soft); +} + +function _isBaseType(baseName, type, soft) { + if (baseName === "string") { + return t.isStringTypeAnnotation(type); + } else if (baseName === "number") { + return t.isNumberTypeAnnotation(type); + } else if (baseName === "boolean") { + return t.isBooleanTypeAnnotation(type); + } else if (baseName === "any") { + return t.isAnyTypeAnnotation(type); + } else if (baseName === "mixed") { + return t.isMixedTypeAnnotation(type); + } else if (baseName === "empty") { + return t.isEmptyTypeAnnotation(type); + } else if (baseName === "void") { + return t.isVoidTypeAnnotation(type); + } else { + if (soft) { + return false; + } else { + throw new Error("Unknown base type " + baseName); + } + } +} + +function couldBeBaseType(name) { + var type = this.getTypeAnnotation(); + if (t.isAnyTypeAnnotation(type)) return true; + + if (t.isUnionTypeAnnotation(type)) { + for (var _iterator = type.types, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var type2 = _ref; + + if (t.isAnyTypeAnnotation(type2) || _isBaseType(name, type2, true)) { + return true; + } + } + return false; + } else { + return _isBaseType(name, type, true); + } +} + +function baseTypeStrictlyMatches(right) { + var left = this.getTypeAnnotation(); + right = right.getTypeAnnotation(); + + if (!t.isAnyTypeAnnotation(left) && t.isFlowBaseAnnotation(left)) { + return right.type === left.type; + } +} + +function isGenericType(genericName) { + var type = this.getTypeAnnotation(); + return t.isGenericTypeAnnotation(type) && t.isIdentifier(type.id, { name: genericName }); +} +},{"./inferers":89,"babel-runtime/core-js/get-iterator":56,"babel-types":112}],88:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.default = function (node) { + if (!this.isReferenced()) return; + + var binding = this.scope.getBinding(node.name); + if (binding) { + if (binding.identifier.typeAnnotation) { + return binding.identifier.typeAnnotation; + } else { + return getTypeAnnotationBindingConstantViolations(this, node.name); + } + } + + if (node.name === "undefined") { + return t.voidTypeAnnotation(); + } else if (node.name === "NaN" || node.name === "Infinity") { + return t.numberTypeAnnotation(); + } else if (node.name === "arguments") {} +}; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getTypeAnnotationBindingConstantViolations(path, name) { + var binding = path.scope.getBinding(name); + + var types = []; + path.typeAnnotation = t.unionTypeAnnotation(types); + + var functionConstantViolations = []; + var constantViolations = getConstantViolationsBefore(binding, path, functionConstantViolations); + + var testType = getConditionalAnnotation(path, name); + if (testType) { + (function () { + var testConstantViolations = getConstantViolationsBefore(binding, testType.ifStatement); + + constantViolations = constantViolations.filter(function (path) { + return testConstantViolations.indexOf(path) < 0; + }); + + types.push(testType.typeAnnotation); + })(); + } + + if (constantViolations.length) { + constantViolations = constantViolations.concat(functionConstantViolations); + + for (var _iterator = constantViolations, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var violation = _ref; + + types.push(violation.getTypeAnnotation()); + } + } + + if (types.length) { + return t.createUnionTypeAnnotation(types); + } +} + +function getConstantViolationsBefore(binding, path, functions) { + var violations = binding.constantViolations.slice(); + violations.unshift(binding.path); + return violations.filter(function (violation) { + violation = violation.resolve(); + var status = violation._guessExecutionStatusRelativeTo(path); + if (functions && status === "function") functions.push(violation); + return status === "before"; + }); +} + +function inferAnnotationFromBinaryExpression(name, path) { + var operator = path.node.operator; + + var right = path.get("right").resolve(); + var left = path.get("left").resolve(); + + var target = void 0; + if (left.isIdentifier({ name: name })) { + target = right; + } else if (right.isIdentifier({ name: name })) { + target = left; + } + if (target) { + if (operator === "===") { + return target.getTypeAnnotation(); + } else if (t.BOOLEAN_NUMBER_BINARY_OPERATORS.indexOf(operator) >= 0) { + return t.numberTypeAnnotation(); + } else { + return; + } + } else { + if (operator !== "===") return; + } + + var typeofPath = void 0; + var typePath = void 0; + if (left.isUnaryExpression({ operator: "typeof" })) { + typeofPath = left; + typePath = right; + } else if (right.isUnaryExpression({ operator: "typeof" })) { + typeofPath = right; + typePath = left; + } + if (!typePath && !typeofPath) return; + + typePath = typePath.resolve(); + if (!typePath.isLiteral()) return; + + var typeValue = typePath.node.value; + if (typeof typeValue !== "string") return; + + if (!typeofPath.get("argument").isIdentifier({ name: name })) return; + + return t.createTypeAnnotationBasedOnTypeof(typePath.node.value); +} + +function getParentConditionalPath(path) { + var parentPath = void 0; + while (parentPath = path.parentPath) { + if (parentPath.isIfStatement() || parentPath.isConditionalExpression()) { + if (path.key === "test") { + return; + } else { + return parentPath; + } + } else { + path = parentPath; + } + } +} + +function getConditionalAnnotation(path, name) { + var ifStatement = getParentConditionalPath(path); + if (!ifStatement) return; + + var test = ifStatement.get("test"); + var paths = [test]; + var types = []; + + do { + var _path = paths.shift().resolve(); + + if (_path.isLogicalExpression()) { + paths.push(_path.get("left")); + paths.push(_path.get("right")); + } + + if (_path.isBinaryExpression()) { + var type = inferAnnotationFromBinaryExpression(name, _path); + if (type) types.push(type); + } + } while (paths.length); + + if (types.length) { + return { + typeAnnotation: t.createUnionTypeAnnotation(types), + ifStatement: ifStatement + }; + } else { + return getConditionalAnnotation(ifStatement, name); + } +} +module.exports = exports["default"]; +},{"babel-runtime/core-js/get-iterator":56,"babel-types":112}],89:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.ClassDeclaration = exports.ClassExpression = exports.FunctionDeclaration = exports.ArrowFunctionExpression = exports.FunctionExpression = exports.Identifier = undefined; + +var _infererReference = require("./inferer-reference"); + +Object.defineProperty(exports, "Identifier", { + enumerable: true, + get: function get() { + return _interopRequireDefault(_infererReference).default; + } +}); +exports.VariableDeclarator = VariableDeclarator; +exports.TypeCastExpression = TypeCastExpression; +exports.NewExpression = NewExpression; +exports.TemplateLiteral = TemplateLiteral; +exports.UnaryExpression = UnaryExpression; +exports.BinaryExpression = BinaryExpression; +exports.LogicalExpression = LogicalExpression; +exports.ConditionalExpression = ConditionalExpression; +exports.SequenceExpression = SequenceExpression; +exports.AssignmentExpression = AssignmentExpression; +exports.UpdateExpression = UpdateExpression; +exports.StringLiteral = StringLiteral; +exports.NumericLiteral = NumericLiteral; +exports.BooleanLiteral = BooleanLiteral; +exports.NullLiteral = NullLiteral; +exports.RegExpLiteral = RegExpLiteral; +exports.ObjectExpression = ObjectExpression; +exports.ArrayExpression = ArrayExpression; +exports.RestElement = RestElement; +exports.CallExpression = CallExpression; +exports.TaggedTemplateExpression = TaggedTemplateExpression; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function VariableDeclarator() { + var id = this.get("id"); + + if (id.isIdentifier()) { + return this.get("init").getTypeAnnotation(); + } else { + return; + } +} + +function TypeCastExpression(node) { + return node.typeAnnotation; +} + +TypeCastExpression.validParent = true; + +function NewExpression(node) { + if (this.get("callee").isIdentifier()) { + return t.genericTypeAnnotation(node.callee); + } +} + +function TemplateLiteral() { + return t.stringTypeAnnotation(); +} + +function UnaryExpression(node) { + var operator = node.operator; + + if (operator === "void") { + return t.voidTypeAnnotation(); + } else if (t.NUMBER_UNARY_OPERATORS.indexOf(operator) >= 0) { + return t.numberTypeAnnotation(); + } else if (t.STRING_UNARY_OPERATORS.indexOf(operator) >= 0) { + return t.stringTypeAnnotation(); + } else if (t.BOOLEAN_UNARY_OPERATORS.indexOf(operator) >= 0) { + return t.booleanTypeAnnotation(); + } +} + +function BinaryExpression(node) { + var operator = node.operator; + + if (t.NUMBER_BINARY_OPERATORS.indexOf(operator) >= 0) { + return t.numberTypeAnnotation(); + } else if (t.BOOLEAN_BINARY_OPERATORS.indexOf(operator) >= 0) { + return t.booleanTypeAnnotation(); + } else if (operator === "+") { + var right = this.get("right"); + var left = this.get("left"); + + if (left.isBaseType("number") && right.isBaseType("number")) { + return t.numberTypeAnnotation(); + } else if (left.isBaseType("string") || right.isBaseType("string")) { + return t.stringTypeAnnotation(); + } + + return t.unionTypeAnnotation([t.stringTypeAnnotation(), t.numberTypeAnnotation()]); + } +} + +function LogicalExpression() { + return t.createUnionTypeAnnotation([this.get("left").getTypeAnnotation(), this.get("right").getTypeAnnotation()]); +} + +function ConditionalExpression() { + return t.createUnionTypeAnnotation([this.get("consequent").getTypeAnnotation(), this.get("alternate").getTypeAnnotation()]); +} + +function SequenceExpression() { + return this.get("expressions").pop().getTypeAnnotation(); +} + +function AssignmentExpression() { + return this.get("right").getTypeAnnotation(); +} + +function UpdateExpression(node) { + var operator = node.operator; + if (operator === "++" || operator === "--") { + return t.numberTypeAnnotation(); + } +} + +function StringLiteral() { + return t.stringTypeAnnotation(); +} + +function NumericLiteral() { + return t.numberTypeAnnotation(); +} + +function BooleanLiteral() { + return t.booleanTypeAnnotation(); +} + +function NullLiteral() { + return t.nullLiteralTypeAnnotation(); +} + +function RegExpLiteral() { + return t.genericTypeAnnotation(t.identifier("RegExp")); +} + +function ObjectExpression() { + return t.genericTypeAnnotation(t.identifier("Object")); +} + +function ArrayExpression() { + return t.genericTypeAnnotation(t.identifier("Array")); +} + +function RestElement() { + return ArrayExpression(); +} + +RestElement.validParent = true; + +function Func() { + return t.genericTypeAnnotation(t.identifier("Function")); +} + +exports.FunctionExpression = Func; +exports.ArrowFunctionExpression = Func; +exports.FunctionDeclaration = Func; +exports.ClassExpression = Func; +exports.ClassDeclaration = Func; +function CallExpression() { + return resolveCall(this.get("callee")); +} + +function TaggedTemplateExpression() { + return resolveCall(this.get("tag")); +} + +function resolveCall(callee) { + callee = callee.resolve(); + + if (callee.isFunction()) { + if (callee.is("async")) { + if (callee.is("generator")) { + return t.genericTypeAnnotation(t.identifier("AsyncIterator")); + } else { + return t.genericTypeAnnotation(t.identifier("Promise")); + } + } else { + if (callee.node.returnType) { + return callee.node.returnType; + } else {} + } + } +} +},{"./inferer-reference":88,"babel-types":112}],90:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.is = undefined; + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.matchesPattern = matchesPattern; +exports.has = has; +exports.isStatic = isStatic; +exports.isnt = isnt; +exports.equals = equals; +exports.isNodeType = isNodeType; +exports.canHaveVariableDeclarationOrExpression = canHaveVariableDeclarationOrExpression; +exports.canSwapBetweenExpressionAndStatement = canSwapBetweenExpressionAndStatement; +exports.isCompletionRecord = isCompletionRecord; +exports.isStatementOrBlock = isStatementOrBlock; +exports.referencesImport = referencesImport; +exports.getSource = getSource; +exports.willIMaybeExecuteBefore = willIMaybeExecuteBefore; +exports._guessExecutionStatusRelativeTo = _guessExecutionStatusRelativeTo; +exports._guessExecutionStatusRelativeToDifferentFunctions = _guessExecutionStatusRelativeToDifferentFunctions; +exports.resolve = resolve; +exports._resolve = _resolve; + +var _includes = require("lodash/includes"); + +var _includes2 = _interopRequireDefault(_includes); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function matchesPattern(pattern, allowPartial) { + if (!this.isMemberExpression()) return false; + + var parts = pattern.split("."); + var search = [this.node]; + var i = 0; + + function matches(name) { + var part = parts[i]; + return part === "*" || name === part; + } + + while (search.length) { + var node = search.shift(); + + if (allowPartial && i === parts.length) { + return true; + } + + if (t.isIdentifier(node)) { + if (!matches(node.name)) return false; + } else if (t.isLiteral(node)) { + if (!matches(node.value)) return false; + } else if (t.isMemberExpression(node)) { + if (node.computed && !t.isLiteral(node.property)) { + return false; + } else { + search.unshift(node.property); + search.unshift(node.object); + continue; + } + } else if (t.isThisExpression(node)) { + if (!matches("this")) return false; + } else { + return false; + } + + if (++i > parts.length) { + return false; + } + } + + return i === parts.length; +} + +function has(key) { + var val = this.node && this.node[key]; + if (val && Array.isArray(val)) { + return !!val.length; + } else { + return !!val; + } +} + +function isStatic() { + return this.scope.isStatic(this.node); +} + +var is = exports.is = has; + +function isnt(key) { + return !this.has(key); +} + +function equals(key, value) { + return this.node[key] === value; +} + +function isNodeType(type) { + return t.isType(this.type, type); +} + +function canHaveVariableDeclarationOrExpression() { + return (this.key === "init" || this.key === "left") && this.parentPath.isFor(); +} + +function canSwapBetweenExpressionAndStatement(replacement) { + if (this.key !== "body" || !this.parentPath.isArrowFunctionExpression()) { + return false; + } + + if (this.isExpression()) { + return t.isBlockStatement(replacement); + } else if (this.isBlockStatement()) { + return t.isExpression(replacement); + } + + return false; +} + +function isCompletionRecord(allowInsideFunction) { + var path = this; + var first = true; + + do { + var container = path.container; + + if (path.isFunction() && !first) { + return !!allowInsideFunction; + } + + first = false; + + if (Array.isArray(container) && path.key !== container.length - 1) { + return false; + } + } while ((path = path.parentPath) && !path.isProgram()); + + return true; +} + +function isStatementOrBlock() { + if (this.parentPath.isLabeledStatement() || t.isBlockStatement(this.container)) { + return false; + } else { + return (0, _includes2.default)(t.STATEMENT_OR_BLOCK_KEYS, this.key); + } +} + +function referencesImport(moduleSource, importName) { + if (!this.isReferencedIdentifier()) return false; + + var binding = this.scope.getBinding(this.node.name); + if (!binding || binding.kind !== "module") return false; + + var path = binding.path; + var parent = path.parentPath; + if (!parent.isImportDeclaration()) return false; + + if (parent.node.source.value === moduleSource) { + if (!importName) return true; + } else { + return false; + } + + if (path.isImportDefaultSpecifier() && importName === "default") { + return true; + } + + if (path.isImportNamespaceSpecifier() && importName === "*") { + return true; + } + + if (path.isImportSpecifier() && path.node.imported.name === importName) { + return true; + } + + return false; +} + +function getSource() { + var node = this.node; + if (node.end) { + return this.hub.file.code.slice(node.start, node.end); + } else { + return ""; + } +} + +function willIMaybeExecuteBefore(target) { + return this._guessExecutionStatusRelativeTo(target) !== "after"; +} + +function _guessExecutionStatusRelativeTo(target) { + var targetFuncParent = target.scope.getFunctionParent(); + var selfFuncParent = this.scope.getFunctionParent(); + + if (targetFuncParent.node !== selfFuncParent.node) { + var status = this._guessExecutionStatusRelativeToDifferentFunctions(targetFuncParent); + if (status) { + return status; + } else { + target = targetFuncParent.path; + } + } + + var targetPaths = target.getAncestry(); + if (targetPaths.indexOf(this) >= 0) return "after"; + + var selfPaths = this.getAncestry(); + + var commonPath = void 0; + var targetIndex = void 0; + var selfIndex = void 0; + for (selfIndex = 0; selfIndex < selfPaths.length; selfIndex++) { + var selfPath = selfPaths[selfIndex]; + targetIndex = targetPaths.indexOf(selfPath); + if (targetIndex >= 0) { + commonPath = selfPath; + break; + } + } + if (!commonPath) { + return "before"; + } + + var targetRelationship = targetPaths[targetIndex - 1]; + var selfRelationship = selfPaths[selfIndex - 1]; + if (!targetRelationship || !selfRelationship) { + return "before"; + } + + if (targetRelationship.listKey && targetRelationship.container === selfRelationship.container) { + return targetRelationship.key > selfRelationship.key ? "before" : "after"; + } + + var targetKeyPosition = t.VISITOR_KEYS[targetRelationship.type].indexOf(targetRelationship.key); + var selfKeyPosition = t.VISITOR_KEYS[selfRelationship.type].indexOf(selfRelationship.key); + return targetKeyPosition > selfKeyPosition ? "before" : "after"; +} + +function _guessExecutionStatusRelativeToDifferentFunctions(targetFuncParent) { + var targetFuncPath = targetFuncParent.path; + if (!targetFuncPath.isFunctionDeclaration()) return; + + var binding = targetFuncPath.scope.getBinding(targetFuncPath.node.id.name); + + if (!binding.references) return "before"; + + var referencePaths = binding.referencePaths; + + for (var _iterator = referencePaths, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var path = _ref; + + if (path.key !== "callee" || !path.parentPath.isCallExpression()) { + return; + } + } + + var allStatus = void 0; + + for (var _iterator2 = referencePaths, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var _path = _ref2; + + var childOfFunction = !!_path.find(function (path) { + return path.node === targetFuncPath.node; + }); + if (childOfFunction) continue; + + var status = this._guessExecutionStatusRelativeTo(_path); + + if (allStatus) { + if (allStatus !== status) return; + } else { + allStatus = status; + } + } + + return allStatus; +} + +function resolve(dangerous, resolved) { + return this._resolve(dangerous, resolved) || this; +} + +function _resolve(dangerous, resolved) { + var _this = this; + + if (resolved && resolved.indexOf(this) >= 0) return; + + resolved = resolved || []; + resolved.push(this); + + if (this.isVariableDeclarator()) { + if (this.get("id").isIdentifier()) { + return this.get("init").resolve(dangerous, resolved); + } else {} + } else if (this.isReferencedIdentifier()) { + var binding = this.scope.getBinding(this.node.name); + if (!binding) return; + + if (!binding.constant) return; + + if (binding.kind === "module") return; + + if (binding.path !== this) { + var _ret = function () { + var ret = binding.path.resolve(dangerous, resolved); + + if (_this.find(function (parent) { + return parent.node === ret.node; + })) return { + v: void 0 + }; + return { + v: ret + }; + }(); + + if ((typeof _ret === "undefined" ? "undefined" : (0, _typeof3.default)(_ret)) === "object") return _ret.v; + } + } else if (this.isTypeCastExpression()) { + return this.get("expression").resolve(dangerous, resolved); + } else if (dangerous && this.isMemberExpression()) { + + var targetKey = this.toComputedKey(); + if (!t.isLiteral(targetKey)) return; + + var targetName = targetKey.value; + + var target = this.get("object").resolve(dangerous, resolved); + + if (target.isObjectExpression()) { + var props = target.get("properties"); + for (var _iterator3 = props, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var prop = _ref3; + + if (!prop.isProperty()) continue; + + var key = prop.get("key"); + + var match = prop.isnt("computed") && key.isIdentifier({ name: targetName }); + + match = match || key.isLiteral({ value: targetName }); + + if (match) return prop.get("value").resolve(dangerous, resolved); + } + } else if (target.isArrayExpression() && !isNaN(+targetName)) { + var elems = target.get("elements"); + var elem = elems[targetName]; + if (elem) return elem.resolve(dangerous, resolved); + } + } +} +},{"babel-runtime/core-js/get-iterator":56,"babel-runtime/helpers/typeof":74,"babel-types":112,"lodash/includes":431}],91:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var referenceVisitor = { + ReferencedIdentifier: function ReferencedIdentifier(path, state) { + if (path.isJSXIdentifier() && _babelTypes.react.isCompatTag(path.node.name) && !path.parentPath.isJSXMemberExpression()) { + return; + } + + if (path.node.name === "this") { + var scope = path.scope; + do { + if (scope.path.isFunction() && !scope.path.isArrowFunctionExpression()) break; + } while (scope = scope.parent); + if (scope) state.breakOnScopePaths.push(scope.path); + } + + var binding = path.scope.getBinding(path.node.name); + if (!binding) return; + + if (binding !== state.scope.getBinding(path.node.name)) return; + + state.bindings[path.node.name] = binding; + } +}; + +var PathHoister = function () { + function PathHoister(path, scope) { + (0, _classCallCheck3.default)(this, PathHoister); + + this.breakOnScopePaths = []; + + this.bindings = {}; + + this.scopes = []; + + this.scope = scope; + this.path = path; + + this.attachAfter = false; + } + + PathHoister.prototype.isCompatibleScope = function isCompatibleScope(scope) { + for (var key in this.bindings) { + var binding = this.bindings[key]; + if (!scope.bindingIdentifierEquals(key, binding.identifier)) { + return false; + } + } + + return true; + }; + + PathHoister.prototype.getCompatibleScopes = function getCompatibleScopes() { + var scope = this.path.scope; + do { + if (this.isCompatibleScope(scope)) { + this.scopes.push(scope); + } else { + break; + } + + if (this.breakOnScopePaths.indexOf(scope.path) >= 0) { + break; + } + } while (scope = scope.parent); + }; + + PathHoister.prototype.getAttachmentPath = function getAttachmentPath() { + var path = this._getAttachmentPath(); + if (!path) return; + + var targetScope = path.scope; + + if (targetScope.path === path) { + targetScope = path.scope.parent; + } + + if (targetScope.path.isProgram() || targetScope.path.isFunction()) { + for (var name in this.bindings) { + if (!targetScope.hasOwnBinding(name)) continue; + + var binding = this.bindings[name]; + + if (binding.kind === "param") continue; + + if (this.getAttachmentParentForPath(binding.path).key > path.key) { + this.attachAfter = true; + path = binding.path; + + for (var _iterator = binding.constantViolations, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var violationPath = _ref; + + if (this.getAttachmentParentForPath(violationPath).key > path.key) { + path = violationPath; + } + } + } + } + } + + return path; + }; + + PathHoister.prototype._getAttachmentPath = function _getAttachmentPath() { + var scopes = this.scopes; + + var scope = scopes.pop(); + + if (!scope) return; + + if (scope.path.isFunction()) { + if (this.hasOwnParamBindings(scope)) { + if (this.scope === scope) return; + + return scope.path.get("body").get("body")[0]; + } else { + return this.getNextScopeAttachmentParent(); + } + } else if (scope.path.isProgram()) { + return this.getNextScopeAttachmentParent(); + } + }; + + PathHoister.prototype.getNextScopeAttachmentParent = function getNextScopeAttachmentParent() { + var scope = this.scopes.pop(); + if (scope) return this.getAttachmentParentForPath(scope.path); + }; + + PathHoister.prototype.getAttachmentParentForPath = function getAttachmentParentForPath(path) { + do { + if (!path.parentPath || Array.isArray(path.container) && path.isStatement() || path.isVariableDeclarator() && path.parentPath.node !== null && path.parentPath.node.declarations.length > 1) return path; + } while (path = path.parentPath); + }; + + PathHoister.prototype.hasOwnParamBindings = function hasOwnParamBindings(scope) { + for (var name in this.bindings) { + if (!scope.hasOwnBinding(name)) continue; + + var binding = this.bindings[name]; + + if (binding.kind === "param" && binding.constant) return true; + } + return false; + }; + + PathHoister.prototype.run = function run() { + var node = this.path.node; + if (node._hoisted) return; + node._hoisted = true; + + this.path.traverse(referenceVisitor, this); + + this.getCompatibleScopes(); + + var attachTo = this.getAttachmentPath(); + if (!attachTo) return; + + if (attachTo.getFunctionParent() === this.path.getFunctionParent()) return; + + var uid = attachTo.scope.generateUidIdentifier("ref"); + var declarator = t.variableDeclarator(uid, this.path.node); + + var insertFn = this.attachAfter ? "insertAfter" : "insertBefore"; + attachTo[insertFn]([attachTo.isVariableDeclarator() ? declarator : t.variableDeclaration("var", [declarator])]); + + var parent = this.path.parentPath; + if (parent.isJSXElement() && this.path.container === parent.node.children) { + uid = t.JSXExpressionContainer(uid); + } + + this.path.replaceWith(uid); + }; + + return PathHoister; +}(); + +exports.default = PathHoister; +module.exports = exports["default"]; +},{"babel-runtime/core-js/get-iterator":56,"babel-runtime/helpers/classCallCheck":70,"babel-types":112}],92:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +var hooks = exports.hooks = [function (self, parent) { + var removeParent = self.key === "test" && (parent.isWhile() || parent.isSwitchCase()) || self.key === "declaration" && parent.isExportDeclaration() || self.key === "body" && parent.isLabeledStatement() || self.listKey === "declarations" && parent.isVariableDeclaration() && parent.node.declarations.length === 1 || self.key === "expression" && parent.isExpressionStatement(); + + if (removeParent) { + parent.remove(); + return true; + } +}, function (self, parent) { + if (parent.isSequenceExpression() && parent.node.expressions.length === 1) { + parent.replaceWith(parent.node.expressions[0]); + return true; + } +}, function (self, parent) { + if (parent.isBinary()) { + if (self.key === "left") { + parent.replaceWith(parent.node.right); + } else { + parent.replaceWith(parent.node.left); + } + return true; + } +}, function (self, parent) { + if (parent.isIfStatement() && (self.key === "consequent" || self.key === "alternate") || self.key === "body" && (parent.isLoop() || parent.isArrowFunctionExpression())) { + self.replaceWith({ + type: "BlockStatement", + body: [] + }); + return true; + } +}]; +},{}],93:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.Flow = exports.Pure = exports.Generated = exports.User = exports.Var = exports.BlockScoped = exports.Referenced = exports.Scope = exports.Expression = exports.Statement = exports.BindingIdentifier = exports.ReferencedMemberExpression = exports.ReferencedIdentifier = undefined; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var ReferencedIdentifier = exports.ReferencedIdentifier = { + types: ["Identifier", "JSXIdentifier"], + checkPath: function checkPath(_ref, opts) { + var node = _ref.node, + parent = _ref.parent; + + if (!t.isIdentifier(node, opts) && !t.isJSXMemberExpression(parent, opts)) { + if (t.isJSXIdentifier(node, opts)) { + if (_babelTypes.react.isCompatTag(node.name)) return false; + } else { + return false; + } + } + + return t.isReferenced(node, parent); + } +}; + +var ReferencedMemberExpression = exports.ReferencedMemberExpression = { + types: ["MemberExpression"], + checkPath: function checkPath(_ref2) { + var node = _ref2.node, + parent = _ref2.parent; + + return t.isMemberExpression(node) && t.isReferenced(node, parent); + } +}; + +var BindingIdentifier = exports.BindingIdentifier = { + types: ["Identifier"], + checkPath: function checkPath(_ref3) { + var node = _ref3.node, + parent = _ref3.parent; + + return t.isIdentifier(node) && t.isBinding(node, parent); + } +}; + +var Statement = exports.Statement = { + types: ["Statement"], + checkPath: function checkPath(_ref4) { + var node = _ref4.node, + parent = _ref4.parent; + + if (t.isStatement(node)) { + if (t.isVariableDeclaration(node)) { + if (t.isForXStatement(parent, { left: node })) return false; + if (t.isForStatement(parent, { init: node })) return false; + } + + return true; + } else { + return false; + } + } +}; + +var Expression = exports.Expression = { + types: ["Expression"], + checkPath: function checkPath(path) { + if (path.isIdentifier()) { + return path.isReferencedIdentifier(); + } else { + return t.isExpression(path.node); + } + } +}; + +var Scope = exports.Scope = { + types: ["Scopable"], + checkPath: function checkPath(path) { + return t.isScope(path.node, path.parent); + } +}; + +var Referenced = exports.Referenced = { + checkPath: function checkPath(path) { + return t.isReferenced(path.node, path.parent); + } +}; + +var BlockScoped = exports.BlockScoped = { + checkPath: function checkPath(path) { + return t.isBlockScoped(path.node); + } +}; + +var Var = exports.Var = { + types: ["VariableDeclaration"], + checkPath: function checkPath(path) { + return t.isVar(path.node); + } +}; + +var User = exports.User = { + checkPath: function checkPath(path) { + return path.node && !!path.node.loc; + } +}; + +var Generated = exports.Generated = { + checkPath: function checkPath(path) { + return !path.isUser(); + } +}; + +var Pure = exports.Pure = { + checkPath: function checkPath(path, opts) { + return path.scope.isPure(path.node, opts); + } +}; + +var Flow = exports.Flow = { + types: ["Flow", "ImportDeclaration", "ExportDeclaration", "ImportSpecifier"], + checkPath: function checkPath(_ref5) { + var node = _ref5.node; + + if (t.isFlow(node)) { + return true; + } else if (t.isImportDeclaration(node)) { + return node.importKind === "type" || node.importKind === "typeof"; + } else if (t.isExportDeclaration(node)) { + return node.exportKind === "type"; + } else if (t.isImportSpecifier(node)) { + return node.importKind === "type" || node.importKind === "typeof"; + } else { + return false; + } + } +}; +},{"babel-types":112}],94:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.insertBefore = insertBefore; +exports._containerInsert = _containerInsert; +exports._containerInsertBefore = _containerInsertBefore; +exports._containerInsertAfter = _containerInsertAfter; +exports._maybePopFromStatements = _maybePopFromStatements; +exports.insertAfter = insertAfter; +exports.updateSiblingKeys = updateSiblingKeys; +exports._verifyNodeList = _verifyNodeList; +exports.unshiftContainer = unshiftContainer; +exports.pushContainer = pushContainer; +exports.hoist = hoist; + +var _cache = require("../cache"); + +var _hoister = require("./lib/hoister"); + +var _hoister2 = _interopRequireDefault(_hoister); + +var _index = require("./index"); + +var _index2 = _interopRequireDefault(_index); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function insertBefore(nodes) { + this._assertUnremoved(); + + nodes = this._verifyNodeList(nodes); + + if (this.parentPath.isExpressionStatement() || this.parentPath.isLabeledStatement()) { + return this.parentPath.insertBefore(nodes); + } else if (this.isNodeType("Expression") || this.parentPath.isForStatement() && this.key === "init") { + if (this.node) nodes.push(this.node); + this.replaceExpressionWithStatements(nodes); + } else { + this._maybePopFromStatements(nodes); + if (Array.isArray(this.container)) { + return this._containerInsertBefore(nodes); + } else if (this.isStatementOrBlock()) { + if (this.node) nodes.push(this.node); + this._replaceWith(t.blockStatement(nodes)); + } else { + throw new Error("We don't know what to do with this node type. " + "We were previously a Statement but we can't fit in here?"); + } + } + + return [this]; +} + +function _containerInsert(from, nodes) { + this.updateSiblingKeys(from, nodes.length); + + var paths = []; + + for (var i = 0; i < nodes.length; i++) { + var to = from + i; + var node = nodes[i]; + this.container.splice(to, 0, node); + + if (this.context) { + var path = this.context.create(this.parent, this.container, to, this.listKey); + + if (this.context.queue) path.pushContext(this.context); + paths.push(path); + } else { + paths.push(_index2.default.get({ + parentPath: this.parentPath, + parent: this.parent, + container: this.container, + listKey: this.listKey, + key: to + })); + } + } + + var contexts = this._getQueueContexts(); + + for (var _iterator = paths, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var _path = _ref; + + _path.setScope(); + _path.debug(function () { + return "Inserted."; + }); + + for (var _iterator2 = contexts, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var context = _ref2; + + context.maybeQueue(_path, true); + } + } + + return paths; +} + +function _containerInsertBefore(nodes) { + return this._containerInsert(this.key, nodes); +} + +function _containerInsertAfter(nodes) { + return this._containerInsert(this.key + 1, nodes); +} + +function _maybePopFromStatements(nodes) { + var last = nodes[nodes.length - 1]; + var isIdentifier = t.isIdentifier(last) || t.isExpressionStatement(last) && t.isIdentifier(last.expression); + + if (isIdentifier && !this.isCompletionRecord()) { + nodes.pop(); + } +} + +function insertAfter(nodes) { + this._assertUnremoved(); + + nodes = this._verifyNodeList(nodes); + + if (this.parentPath.isExpressionStatement() || this.parentPath.isLabeledStatement()) { + return this.parentPath.insertAfter(nodes); + } else if (this.isNodeType("Expression") || this.parentPath.isForStatement() && this.key === "init") { + if (this.node) { + var temp = this.scope.generateDeclaredUidIdentifier(); + nodes.unshift(t.expressionStatement(t.assignmentExpression("=", temp, this.node))); + nodes.push(t.expressionStatement(temp)); + } + this.replaceExpressionWithStatements(nodes); + } else { + this._maybePopFromStatements(nodes); + if (Array.isArray(this.container)) { + return this._containerInsertAfter(nodes); + } else if (this.isStatementOrBlock()) { + if (this.node) nodes.unshift(this.node); + this._replaceWith(t.blockStatement(nodes)); + } else { + throw new Error("We don't know what to do with this node type. " + "We were previously a Statement but we can't fit in here?"); + } + } + + return [this]; +} + +function updateSiblingKeys(fromIndex, incrementBy) { + if (!this.parent) return; + + var paths = _cache.path.get(this.parent); + for (var i = 0; i < paths.length; i++) { + var path = paths[i]; + if (path.key >= fromIndex) { + path.key += incrementBy; + } + } +} + +function _verifyNodeList(nodes) { + if (!nodes) { + return []; + } + + if (nodes.constructor !== Array) { + nodes = [nodes]; + } + + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + var msg = void 0; + + if (!node) { + msg = "has falsy node"; + } else if ((typeof node === "undefined" ? "undefined" : (0, _typeof3.default)(node)) !== "object") { + msg = "contains a non-object node"; + } else if (!node.type) { + msg = "without a type"; + } else if (node instanceof _index2.default) { + msg = "has a NodePath when it expected a raw object"; + } + + if (msg) { + var type = Array.isArray(node) ? "array" : typeof node === "undefined" ? "undefined" : (0, _typeof3.default)(node); + throw new Error("Node list " + msg + " with the index of " + i + " and type of " + type); + } + } + + return nodes; +} + +function unshiftContainer(listKey, nodes) { + this._assertUnremoved(); + + nodes = this._verifyNodeList(nodes); + + var path = _index2.default.get({ + parentPath: this, + parent: this.node, + container: this.node[listKey], + listKey: listKey, + key: 0 + }); + + return path.insertBefore(nodes); +} + +function pushContainer(listKey, nodes) { + this._assertUnremoved(); + + nodes = this._verifyNodeList(nodes); + + var container = this.node[listKey]; + var path = _index2.default.get({ + parentPath: this, + parent: this.node, + container: container, + listKey: listKey, + key: container.length + }); + + return path.replaceWithMultiple(nodes); +} + +function hoist() { + var scope = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.scope; + + var hoister = new _hoister2.default(this, scope); + return hoister.run(); +} +},{"../cache":76,"./index":86,"./lib/hoister":91,"babel-runtime/core-js/get-iterator":56,"babel-runtime/helpers/typeof":74,"babel-types":112}],95:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.remove = remove; +exports._callRemovalHooks = _callRemovalHooks; +exports._remove = _remove; +exports._markRemoved = _markRemoved; +exports._assertUnremoved = _assertUnremoved; + +var _removalHooks = require("./lib/removal-hooks"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function remove() { + this._assertUnremoved(); + + this.resync(); + + if (this._callRemovalHooks()) { + this._markRemoved(); + return; + } + + this.shareCommentsWithSiblings(); + this._remove(); + this._markRemoved(); +} + +function _callRemovalHooks() { + for (var _iterator = _removalHooks.hooks, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var fn = _ref; + + if (fn(this, this.parentPath)) return true; + } +} + +function _remove() { + if (Array.isArray(this.container)) { + this.container.splice(this.key, 1); + this.updateSiblingKeys(this.key, -1); + } else { + this._replaceWith(null); + } +} + +function _markRemoved() { + this.shouldSkip = true; + this.removed = true; + this.node = null; +} + +function _assertUnremoved() { + if (this.removed) { + throw this.buildCodeFrameError("NodePath has been removed so is read-only."); + } +} +},{"./lib/removal-hooks":92,"babel-runtime/core-js/get-iterator":56}],96:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.replaceWithMultiple = replaceWithMultiple; +exports.replaceWithSourceString = replaceWithSourceString; +exports.replaceWith = replaceWith; +exports._replaceWith = _replaceWith; +exports.replaceExpressionWithStatements = replaceExpressionWithStatements; +exports.replaceInline = replaceInline; + +var _babelCodeFrame = require("babel-code-frame"); + +var _babelCodeFrame2 = _interopRequireDefault(_babelCodeFrame); + +var _index = require("../index"); + +var _index2 = _interopRequireDefault(_index); + +var _index3 = require("./index"); + +var _index4 = _interopRequireDefault(_index3); + +var _babylon = require("babylon"); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var hoistVariablesVisitor = { + Function: function Function(path) { + path.skip(); + }, + VariableDeclaration: function VariableDeclaration(path) { + if (path.node.kind !== "var") return; + + var bindings = path.getBindingIdentifiers(); + for (var key in bindings) { + path.scope.push({ id: bindings[key] }); + } + + var exprs = []; + + for (var _iterator = path.node.declarations, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var declar = _ref; + + if (declar.init) { + exprs.push(t.expressionStatement(t.assignmentExpression("=", declar.id, declar.init))); + } + } + + path.replaceWithMultiple(exprs); + } +}; + +function replaceWithMultiple(nodes) { + this.resync(); + + nodes = this._verifyNodeList(nodes); + t.inheritLeadingComments(nodes[0], this.node); + t.inheritTrailingComments(nodes[nodes.length - 1], this.node); + this.node = this.container[this.key] = null; + this.insertAfter(nodes); + + if (this.node) { + this.requeue(); + } else { + this.remove(); + } +} + +function replaceWithSourceString(replacement) { + this.resync(); + + try { + replacement = "(" + replacement + ")"; + replacement = (0, _babylon.parse)(replacement); + } catch (err) { + var loc = err.loc; + if (loc) { + err.message += " - make sure this is an expression."; + err.message += "\n" + (0, _babelCodeFrame2.default)(replacement, loc.line, loc.column + 1); + } + throw err; + } + + replacement = replacement.program.body[0].expression; + _index2.default.removeProperties(replacement); + return this.replaceWith(replacement); +} + +function replaceWith(replacement) { + this.resync(); + + if (this.removed) { + throw new Error("You can't replace this node, we've already removed it"); + } + + if (replacement instanceof _index4.default) { + replacement = replacement.node; + } + + if (!replacement) { + throw new Error("You passed `path.replaceWith()` a falsy node, use `path.remove()` instead"); + } + + if (this.node === replacement) { + return; + } + + if (this.isProgram() && !t.isProgram(replacement)) { + throw new Error("You can only replace a Program root node with another Program node"); + } + + if (Array.isArray(replacement)) { + throw new Error("Don't use `path.replaceWith()` with an array of nodes, use `path.replaceWithMultiple()`"); + } + + if (typeof replacement === "string") { + throw new Error("Don't use `path.replaceWith()` with a source string, use `path.replaceWithSourceString()`"); + } + + if (this.isNodeType("Statement") && t.isExpression(replacement)) { + if (!this.canHaveVariableDeclarationOrExpression() && !this.canSwapBetweenExpressionAndStatement(replacement)) { + replacement = t.expressionStatement(replacement); + } + } + + if (this.isNodeType("Expression") && t.isStatement(replacement)) { + if (!this.canHaveVariableDeclarationOrExpression() && !this.canSwapBetweenExpressionAndStatement(replacement)) { + return this.replaceExpressionWithStatements([replacement]); + } + } + + var oldNode = this.node; + if (oldNode) { + t.inheritsComments(replacement, oldNode); + t.removeComments(oldNode); + } + + this._replaceWith(replacement); + this.type = replacement.type; + + this.setScope(); + + this.requeue(); +} + +function _replaceWith(node) { + if (!this.container) { + throw new ReferenceError("Container is falsy"); + } + + if (this.inList) { + t.validate(this.parent, this.key, [node]); + } else { + t.validate(this.parent, this.key, node); + } + + this.debug(function () { + return "Replace with " + (node && node.type); + }); + + this.node = this.container[this.key] = node; +} + +function replaceExpressionWithStatements(nodes) { + this.resync(); + + var toSequenceExpression = t.toSequenceExpression(nodes, this.scope); + + if (t.isSequenceExpression(toSequenceExpression)) { + var exprs = toSequenceExpression.expressions; + + if (exprs.length >= 2 && this.parentPath.isExpressionStatement()) { + this._maybePopFromStatements(exprs); + } + + if (exprs.length === 1) { + this.replaceWith(exprs[0]); + } else { + this.replaceWith(toSequenceExpression); + } + } else if (toSequenceExpression) { + this.replaceWith(toSequenceExpression); + } else { + var container = t.functionExpression(null, [], t.blockStatement(nodes)); + container.shadow = true; + + this.replaceWith(t.callExpression(container, [])); + this.traverse(hoistVariablesVisitor); + + var completionRecords = this.get("callee").getCompletionRecords(); + for (var _iterator2 = completionRecords, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var path = _ref2; + + if (!path.isExpressionStatement()) continue; + + var loop = path.findParent(function (path) { + return path.isLoop(); + }); + if (loop) { + var uid = loop.getData("expressionReplacementReturnUid"); + + if (!uid) { + var callee = this.get("callee"); + uid = callee.scope.generateDeclaredUidIdentifier("ret"); + callee.get("body").pushContainer("body", t.returnStatement(uid)); + loop.setData("expressionReplacementReturnUid", uid); + } else { + uid = t.identifier(uid.name); + } + + path.get("expression").replaceWith(t.assignmentExpression("=", uid, path.node.expression)); + } else { + path.replaceWith(t.returnStatement(path.node.expression)); + } + } + + return this.node; + } +} + +function replaceInline(nodes) { + this.resync(); + + if (Array.isArray(nodes)) { + if (Array.isArray(this.container)) { + nodes = this._verifyNodeList(nodes); + this._containerInsertAfter(nodes); + return this.remove(); + } else { + return this.replaceWithMultiple(nodes); + } + } else { + return this.replaceWith(nodes); + } +} +},{"../index":79,"./index":86,"babel-code-frame":3,"babel-runtime/core-js/get-iterator":56,"babel-types":112,"babylon":116}],97:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var Binding = function () { + function Binding(_ref) { + var existing = _ref.existing, + identifier = _ref.identifier, + scope = _ref.scope, + path = _ref.path, + kind = _ref.kind; + (0, _classCallCheck3.default)(this, Binding); + + this.identifier = identifier; + this.scope = scope; + this.path = path; + this.kind = kind; + + this.constantViolations = []; + this.constant = true; + + this.referencePaths = []; + this.referenced = false; + this.references = 0; + + this.clearValue(); + + if (existing) { + this.constantViolations = [].concat(existing.path, existing.constantViolations, this.constantViolations); + } + } + + Binding.prototype.deoptValue = function deoptValue() { + this.clearValue(); + this.hasDeoptedValue = true; + }; + + Binding.prototype.setValue = function setValue(value) { + if (this.hasDeoptedValue) return; + this.hasValue = true; + this.value = value; + }; + + Binding.prototype.clearValue = function clearValue() { + this.hasDeoptedValue = false; + this.hasValue = false; + this.value = null; + }; + + Binding.prototype.reassign = function reassign(path) { + this.constant = false; + if (this.constantViolations.indexOf(path) !== -1) { + return; + } + this.constantViolations.push(path); + }; + + Binding.prototype.reference = function reference(path) { + if (this.referencePaths.indexOf(path) !== -1) { + return; + } + this.referenced = true; + this.references++; + this.referencePaths.push(path); + }; + + Binding.prototype.dereference = function dereference() { + this.references--; + this.referenced = !!this.references; + }; + + return Binding; +}(); + +exports.default = Binding; +module.exports = exports["default"]; +},{"babel-runtime/helpers/classCallCheck":70}],98:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _keys = require("babel-runtime/core-js/object/keys"); + +var _keys2 = _interopRequireDefault(_keys); + +var _create = require("babel-runtime/core-js/object/create"); + +var _create2 = _interopRequireDefault(_create); + +var _map = require("babel-runtime/core-js/map"); + +var _map2 = _interopRequireDefault(_map); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _includes = require("lodash/includes"); + +var _includes2 = _interopRequireDefault(_includes); + +var _repeat = require("lodash/repeat"); + +var _repeat2 = _interopRequireDefault(_repeat); + +var _renamer = require("./lib/renamer"); + +var _renamer2 = _interopRequireDefault(_renamer); + +var _index = require("../index"); + +var _index2 = _interopRequireDefault(_index); + +var _defaults = require("lodash/defaults"); + +var _defaults2 = _interopRequireDefault(_defaults); + +var _babelMessages = require("babel-messages"); + +var messages = _interopRequireWildcard(_babelMessages); + +var _binding2 = require("./binding"); + +var _binding3 = _interopRequireDefault(_binding2); + +var _globals = require("globals"); + +var _globals2 = _interopRequireDefault(_globals); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +var _cache = require("../cache"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var _crawlCallsCount = 0; + +function getCache(path, parentScope, self) { + var scopes = _cache.scope.get(path.node) || []; + + for (var _iterator = scopes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var scope = _ref; + + if (scope.parent === parentScope && scope.path === path) return scope; + } + + scopes.push(self); + + if (!_cache.scope.has(path.node)) { + _cache.scope.set(path.node, scopes); + } +} + +function gatherNodeParts(node, parts) { + if (t.isModuleDeclaration(node)) { + if (node.source) { + gatherNodeParts(node.source, parts); + } else if (node.specifiers && node.specifiers.length) { + for (var _iterator2 = node.specifiers, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var specifier = _ref2; + + gatherNodeParts(specifier, parts); + } + } else if (node.declaration) { + gatherNodeParts(node.declaration, parts); + } + } else if (t.isModuleSpecifier(node)) { + gatherNodeParts(node.local, parts); + } else if (t.isMemberExpression(node)) { + gatherNodeParts(node.object, parts); + gatherNodeParts(node.property, parts); + } else if (t.isIdentifier(node)) { + parts.push(node.name); + } else if (t.isLiteral(node)) { + parts.push(node.value); + } else if (t.isCallExpression(node)) { + gatherNodeParts(node.callee, parts); + } else if (t.isObjectExpression(node) || t.isObjectPattern(node)) { + for (var _iterator3 = node.properties, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var prop = _ref3; + + gatherNodeParts(prop.key || prop.argument, parts); + } + } +} + +var collectorVisitor = { + For: function For(path) { + for (var _iterator4 = t.FOR_INIT_KEYS, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : (0, _getIterator3.default)(_iterator4);;) { + var _ref4; + + if (_isArray4) { + if (_i4 >= _iterator4.length) break; + _ref4 = _iterator4[_i4++]; + } else { + _i4 = _iterator4.next(); + if (_i4.done) break; + _ref4 = _i4.value; + } + + var key = _ref4; + + var declar = path.get(key); + if (declar.isVar()) path.scope.getFunctionParent().registerBinding("var", declar); + } + }, + Declaration: function Declaration(path) { + if (path.isBlockScoped()) return; + + if (path.isExportDeclaration() && path.get("declaration").isDeclaration()) return; + + path.scope.getFunctionParent().registerDeclaration(path); + }, + ReferencedIdentifier: function ReferencedIdentifier(path, state) { + state.references.push(path); + }, + ForXStatement: function ForXStatement(path, state) { + var left = path.get("left"); + if (left.isPattern() || left.isIdentifier()) { + state.constantViolations.push(left); + } + }, + + + ExportDeclaration: { + exit: function exit(path) { + var node = path.node, + scope = path.scope; + + var declar = node.declaration; + if (t.isClassDeclaration(declar) || t.isFunctionDeclaration(declar)) { + var _id = declar.id; + if (!_id) return; + + var binding = scope.getBinding(_id.name); + if (binding) binding.reference(path); + } else if (t.isVariableDeclaration(declar)) { + for (var _iterator5 = declar.declarations, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : (0, _getIterator3.default)(_iterator5);;) { + var _ref5; + + if (_isArray5) { + if (_i5 >= _iterator5.length) break; + _ref5 = _iterator5[_i5++]; + } else { + _i5 = _iterator5.next(); + if (_i5.done) break; + _ref5 = _i5.value; + } + + var decl = _ref5; + + var ids = t.getBindingIdentifiers(decl); + for (var name in ids) { + var _binding = scope.getBinding(name); + if (_binding) _binding.reference(path); + } + } + } + } + }, + + LabeledStatement: function LabeledStatement(path) { + path.scope.getProgramParent().addGlobal(path.node); + path.scope.getBlockParent().registerDeclaration(path); + }, + AssignmentExpression: function AssignmentExpression(path, state) { + state.assignments.push(path); + }, + UpdateExpression: function UpdateExpression(path, state) { + state.constantViolations.push(path.get("argument")); + }, + UnaryExpression: function UnaryExpression(path, state) { + if (path.node.operator === "delete") { + state.constantViolations.push(path.get("argument")); + } + }, + BlockScoped: function BlockScoped(path) { + var scope = path.scope; + if (scope.path === path) scope = scope.parent; + scope.getBlockParent().registerDeclaration(path); + }, + ClassDeclaration: function ClassDeclaration(path) { + var id = path.node.id; + if (!id) return; + + var name = id.name; + path.scope.bindings[name] = path.scope.getBinding(name); + }, + Block: function Block(path) { + var paths = path.get("body"); + for (var _iterator6 = paths, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : (0, _getIterator3.default)(_iterator6);;) { + var _ref6; + + if (_isArray6) { + if (_i6 >= _iterator6.length) break; + _ref6 = _iterator6[_i6++]; + } else { + _i6 = _iterator6.next(); + if (_i6.done) break; + _ref6 = _i6.value; + } + + var bodyPath = _ref6; + + if (bodyPath.isFunctionDeclaration()) { + path.scope.getBlockParent().registerDeclaration(bodyPath); + } + } + } +}; + +var uid = 0; + +var Scope = function () { + function Scope(path, parentScope) { + (0, _classCallCheck3.default)(this, Scope); + + if (parentScope && parentScope.block === path.node) { + return parentScope; + } + + var cached = getCache(path, parentScope, this); + if (cached) return cached; + + this.uid = uid++; + this.parent = parentScope; + this.hub = path.hub; + + this.parentBlock = path.parent; + this.block = path.node; + this.path = path; + + this.labels = new _map2.default(); + } + + Scope.prototype.traverse = function traverse(node, opts, state) { + (0, _index2.default)(node, opts, this, state, this.path); + }; + + Scope.prototype.generateDeclaredUidIdentifier = function generateDeclaredUidIdentifier() { + var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "temp"; + + var id = this.generateUidIdentifier(name); + this.push({ id: id }); + return id; + }; + + Scope.prototype.generateUidIdentifier = function generateUidIdentifier() { + var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "temp"; + + return t.identifier(this.generateUid(name)); + }; + + Scope.prototype.generateUid = function generateUid() { + var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "temp"; + + name = t.toIdentifier(name).replace(/^_+/, "").replace(/[0-9]+$/g, ""); + + var uid = void 0; + var i = 0; + do { + uid = this._generateUid(name, i); + i++; + } while (this.hasLabel(uid) || this.hasBinding(uid) || this.hasGlobal(uid) || this.hasReference(uid)); + + var program = this.getProgramParent(); + program.references[uid] = true; + program.uids[uid] = true; + + return uid; + }; + + Scope.prototype._generateUid = function _generateUid(name, i) { + var id = name; + if (i > 1) id += i; + return "_" + id; + }; + + Scope.prototype.generateUidIdentifierBasedOnNode = function generateUidIdentifierBasedOnNode(parent, defaultName) { + var node = parent; + + if (t.isAssignmentExpression(parent)) { + node = parent.left; + } else if (t.isVariableDeclarator(parent)) { + node = parent.id; + } else if (t.isObjectProperty(node) || t.isObjectMethod(node)) { + node = node.key; + } + + var parts = []; + gatherNodeParts(node, parts); + + var id = parts.join("$"); + id = id.replace(/^_/, "") || defaultName || "ref"; + + return this.generateUidIdentifier(id.slice(0, 20)); + }; + + Scope.prototype.isStatic = function isStatic(node) { + if (t.isThisExpression(node) || t.isSuper(node)) { + return true; + } + + if (t.isIdentifier(node)) { + var binding = this.getBinding(node.name); + if (binding) { + return binding.constant; + } else { + return this.hasBinding(node.name); + } + } + + return false; + }; + + Scope.prototype.maybeGenerateMemoised = function maybeGenerateMemoised(node, dontPush) { + if (this.isStatic(node)) { + return null; + } else { + var _id2 = this.generateUidIdentifierBasedOnNode(node); + if (!dontPush) this.push({ id: _id2 }); + return _id2; + } + }; + + Scope.prototype.checkBlockScopedCollisions = function checkBlockScopedCollisions(local, kind, name, id) { + if (kind === "param") return; + + if (kind === "hoisted" && local.kind === "let") return; + + var duplicate = kind === "let" || local.kind === "let" || local.kind === "const" || local.kind === "module" || local.kind === "param" && (kind === "let" || kind === "const"); + + if (duplicate) { + throw this.hub.file.buildCodeFrameError(id, messages.get("scopeDuplicateDeclaration", name), TypeError); + } + }; + + Scope.prototype.rename = function rename(oldName, newName, block) { + var binding = this.getBinding(oldName); + if (binding) { + newName = newName || this.generateUidIdentifier(oldName).name; + return new _renamer2.default(binding, oldName, newName).rename(block); + } + }; + + Scope.prototype._renameFromMap = function _renameFromMap(map, oldName, newName, value) { + if (map[oldName]) { + map[newName] = value; + map[oldName] = null; + } + }; + + Scope.prototype.dump = function dump() { + var sep = (0, _repeat2.default)("-", 60); + console.log(sep); + var scope = this; + do { + console.log("#", scope.block.type); + for (var name in scope.bindings) { + var binding = scope.bindings[name]; + console.log(" -", name, { + constant: binding.constant, + references: binding.references, + violations: binding.constantViolations.length, + kind: binding.kind + }); + } + } while (scope = scope.parent); + console.log(sep); + }; + + Scope.prototype.toArray = function toArray(node, i) { + var file = this.hub.file; + + if (t.isIdentifier(node)) { + var binding = this.getBinding(node.name); + if (binding && binding.constant && binding.path.isGenericType("Array")) return node; + } + + if (t.isArrayExpression(node)) { + return node; + } + + if (t.isIdentifier(node, { name: "arguments" })) { + return t.callExpression(t.memberExpression(t.memberExpression(t.memberExpression(t.identifier("Array"), t.identifier("prototype")), t.identifier("slice")), t.identifier("call")), [node]); + } + + var helperName = "toArray"; + var args = [node]; + if (i === true) { + helperName = "toConsumableArray"; + } else if (i) { + args.push(t.numericLiteral(i)); + helperName = "slicedToArray"; + } + return t.callExpression(file.addHelper(helperName), args); + }; + + Scope.prototype.hasLabel = function hasLabel(name) { + return !!this.getLabel(name); + }; + + Scope.prototype.getLabel = function getLabel(name) { + return this.labels.get(name); + }; + + Scope.prototype.registerLabel = function registerLabel(path) { + this.labels.set(path.node.label.name, path); + }; + + Scope.prototype.registerDeclaration = function registerDeclaration(path) { + if (path.isLabeledStatement()) { + this.registerLabel(path); + } else if (path.isFunctionDeclaration()) { + this.registerBinding("hoisted", path.get("id"), path); + } else if (path.isVariableDeclaration()) { + var declarations = path.get("declarations"); + for (var _iterator7 = declarations, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : (0, _getIterator3.default)(_iterator7);;) { + var _ref7; + + if (_isArray7) { + if (_i7 >= _iterator7.length) break; + _ref7 = _iterator7[_i7++]; + } else { + _i7 = _iterator7.next(); + if (_i7.done) break; + _ref7 = _i7.value; + } + + var declar = _ref7; + + this.registerBinding(path.node.kind, declar); + } + } else if (path.isClassDeclaration()) { + this.registerBinding("let", path); + } else if (path.isImportDeclaration()) { + var specifiers = path.get("specifiers"); + for (var _iterator8 = specifiers, _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : (0, _getIterator3.default)(_iterator8);;) { + var _ref8; + + if (_isArray8) { + if (_i8 >= _iterator8.length) break; + _ref8 = _iterator8[_i8++]; + } else { + _i8 = _iterator8.next(); + if (_i8.done) break; + _ref8 = _i8.value; + } + + var specifier = _ref8; + + this.registerBinding("module", specifier); + } + } else if (path.isExportDeclaration()) { + var _declar = path.get("declaration"); + if (_declar.isClassDeclaration() || _declar.isFunctionDeclaration() || _declar.isVariableDeclaration()) { + this.registerDeclaration(_declar); + } + } else { + this.registerBinding("unknown", path); + } + }; + + Scope.prototype.buildUndefinedNode = function buildUndefinedNode() { + if (this.hasBinding("undefined")) { + return t.unaryExpression("void", t.numericLiteral(0), true); + } else { + return t.identifier("undefined"); + } + }; + + Scope.prototype.registerConstantViolation = function registerConstantViolation(path) { + var ids = path.getBindingIdentifiers(); + for (var name in ids) { + var binding = this.getBinding(name); + if (binding) binding.reassign(path); + } + }; + + Scope.prototype.registerBinding = function registerBinding(kind, path) { + var bindingPath = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : path; + + if (!kind) throw new ReferenceError("no `kind`"); + + if (path.isVariableDeclaration()) { + var declarators = path.get("declarations"); + for (var _iterator9 = declarators, _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : (0, _getIterator3.default)(_iterator9);;) { + var _ref9; + + if (_isArray9) { + if (_i9 >= _iterator9.length) break; + _ref9 = _iterator9[_i9++]; + } else { + _i9 = _iterator9.next(); + if (_i9.done) break; + _ref9 = _i9.value; + } + + var declar = _ref9; + + this.registerBinding(kind, declar); + } + return; + } + + var parent = this.getProgramParent(); + var ids = path.getBindingIdentifiers(true); + + for (var name in ids) { + for (var _iterator10 = ids[name], _isArray10 = Array.isArray(_iterator10), _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : (0, _getIterator3.default)(_iterator10);;) { + var _ref10; + + if (_isArray10) { + if (_i10 >= _iterator10.length) break; + _ref10 = _iterator10[_i10++]; + } else { + _i10 = _iterator10.next(); + if (_i10.done) break; + _ref10 = _i10.value; + } + + var _id3 = _ref10; + + var local = this.getOwnBinding(name); + if (local) { + if (local.identifier === _id3) continue; + + this.checkBlockScopedCollisions(local, kind, name, _id3); + } + + if (local && local.path.isFlow()) local = null; + + parent.references[name] = true; + + this.bindings[name] = new _binding3.default({ + identifier: _id3, + existing: local, + scope: this, + path: bindingPath, + kind: kind + }); + } + } + }; + + Scope.prototype.addGlobal = function addGlobal(node) { + this.globals[node.name] = node; + }; + + Scope.prototype.hasUid = function hasUid(name) { + var scope = this; + + do { + if (scope.uids[name]) return true; + } while (scope = scope.parent); + + return false; + }; + + Scope.prototype.hasGlobal = function hasGlobal(name) { + var scope = this; + + do { + if (scope.globals[name]) return true; + } while (scope = scope.parent); + + return false; + }; + + Scope.prototype.hasReference = function hasReference(name) { + var scope = this; + + do { + if (scope.references[name]) return true; + } while (scope = scope.parent); + + return false; + }; + + Scope.prototype.isPure = function isPure(node, constantsOnly) { + if (t.isIdentifier(node)) { + var binding = this.getBinding(node.name); + if (!binding) return false; + if (constantsOnly) return binding.constant; + return true; + } else if (t.isClass(node)) { + if (node.superClass && !this.isPure(node.superClass, constantsOnly)) return false; + return this.isPure(node.body, constantsOnly); + } else if (t.isClassBody(node)) { + for (var _iterator11 = node.body, _isArray11 = Array.isArray(_iterator11), _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : (0, _getIterator3.default)(_iterator11);;) { + var _ref11; + + if (_isArray11) { + if (_i11 >= _iterator11.length) break; + _ref11 = _iterator11[_i11++]; + } else { + _i11 = _iterator11.next(); + if (_i11.done) break; + _ref11 = _i11.value; + } + + var method = _ref11; + + if (!this.isPure(method, constantsOnly)) return false; + } + return true; + } else if (t.isBinary(node)) { + return this.isPure(node.left, constantsOnly) && this.isPure(node.right, constantsOnly); + } else if (t.isArrayExpression(node)) { + for (var _iterator12 = node.elements, _isArray12 = Array.isArray(_iterator12), _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : (0, _getIterator3.default)(_iterator12);;) { + var _ref12; + + if (_isArray12) { + if (_i12 >= _iterator12.length) break; + _ref12 = _iterator12[_i12++]; + } else { + _i12 = _iterator12.next(); + if (_i12.done) break; + _ref12 = _i12.value; + } + + var elem = _ref12; + + if (!this.isPure(elem, constantsOnly)) return false; + } + return true; + } else if (t.isObjectExpression(node)) { + for (var _iterator13 = node.properties, _isArray13 = Array.isArray(_iterator13), _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : (0, _getIterator3.default)(_iterator13);;) { + var _ref13; + + if (_isArray13) { + if (_i13 >= _iterator13.length) break; + _ref13 = _iterator13[_i13++]; + } else { + _i13 = _iterator13.next(); + if (_i13.done) break; + _ref13 = _i13.value; + } + + var prop = _ref13; + + if (!this.isPure(prop, constantsOnly)) return false; + } + return true; + } else if (t.isClassMethod(node)) { + if (node.computed && !this.isPure(node.key, constantsOnly)) return false; + if (node.kind === "get" || node.kind === "set") return false; + return true; + } else if (t.isClassProperty(node) || t.isObjectProperty(node)) { + if (node.computed && !this.isPure(node.key, constantsOnly)) return false; + return this.isPure(node.value, constantsOnly); + } else if (t.isUnaryExpression(node)) { + return this.isPure(node.argument, constantsOnly); + } else { + return t.isPureish(node); + } + }; + + Scope.prototype.setData = function setData(key, val) { + return this.data[key] = val; + }; + + Scope.prototype.getData = function getData(key) { + var scope = this; + do { + var data = scope.data[key]; + if (data != null) return data; + } while (scope = scope.parent); + }; + + Scope.prototype.removeData = function removeData(key) { + var scope = this; + do { + var data = scope.data[key]; + if (data != null) scope.data[key] = null; + } while (scope = scope.parent); + }; + + Scope.prototype.init = function init() { + if (!this.references) this.crawl(); + }; + + Scope.prototype.crawl = function crawl() { + _crawlCallsCount++; + this._crawl(); + _crawlCallsCount--; + }; + + Scope.prototype._crawl = function _crawl() { + var path = this.path; + + this.references = (0, _create2.default)(null); + this.bindings = (0, _create2.default)(null); + this.globals = (0, _create2.default)(null); + this.uids = (0, _create2.default)(null); + this.data = (0, _create2.default)(null); + + if (path.isLoop()) { + for (var _iterator14 = t.FOR_INIT_KEYS, _isArray14 = Array.isArray(_iterator14), _i14 = 0, _iterator14 = _isArray14 ? _iterator14 : (0, _getIterator3.default)(_iterator14);;) { + var _ref14; + + if (_isArray14) { + if (_i14 >= _iterator14.length) break; + _ref14 = _iterator14[_i14++]; + } else { + _i14 = _iterator14.next(); + if (_i14.done) break; + _ref14 = _i14.value; + } + + var key = _ref14; + + var node = path.get(key); + if (node.isBlockScoped()) this.registerBinding(node.node.kind, node); + } + } + + if (path.isFunctionExpression() && path.has("id")) { + if (!path.get("id").node[t.NOT_LOCAL_BINDING]) { + this.registerBinding("local", path.get("id"), path); + } + } + + if (path.isClassExpression() && path.has("id")) { + if (!path.get("id").node[t.NOT_LOCAL_BINDING]) { + this.registerBinding("local", path); + } + } + + if (path.isFunction()) { + var params = path.get("params"); + for (var _iterator15 = params, _isArray15 = Array.isArray(_iterator15), _i15 = 0, _iterator15 = _isArray15 ? _iterator15 : (0, _getIterator3.default)(_iterator15);;) { + var _ref15; + + if (_isArray15) { + if (_i15 >= _iterator15.length) break; + _ref15 = _iterator15[_i15++]; + } else { + _i15 = _iterator15.next(); + if (_i15.done) break; + _ref15 = _i15.value; + } + + var param = _ref15; + + this.registerBinding("param", param); + } + } + + if (path.isCatchClause()) { + this.registerBinding("let", path); + } + + var parent = this.getProgramParent(); + if (parent.crawling) return; + + var state = { + references: [], + constantViolations: [], + assignments: [] + }; + + this.crawling = true; + path.traverse(collectorVisitor, state); + this.crawling = false; + + for (var _iterator16 = state.assignments, _isArray16 = Array.isArray(_iterator16), _i16 = 0, _iterator16 = _isArray16 ? _iterator16 : (0, _getIterator3.default)(_iterator16);;) { + var _ref16; + + if (_isArray16) { + if (_i16 >= _iterator16.length) break; + _ref16 = _iterator16[_i16++]; + } else { + _i16 = _iterator16.next(); + if (_i16.done) break; + _ref16 = _i16.value; + } + + var _path = _ref16; + + var ids = _path.getBindingIdentifiers(); + var programParent = void 0; + for (var name in ids) { + if (_path.scope.getBinding(name)) continue; + + programParent = programParent || _path.scope.getProgramParent(); + programParent.addGlobal(ids[name]); + } + + _path.scope.registerConstantViolation(_path); + } + + for (var _iterator17 = state.references, _isArray17 = Array.isArray(_iterator17), _i17 = 0, _iterator17 = _isArray17 ? _iterator17 : (0, _getIterator3.default)(_iterator17);;) { + var _ref17; + + if (_isArray17) { + if (_i17 >= _iterator17.length) break; + _ref17 = _iterator17[_i17++]; + } else { + _i17 = _iterator17.next(); + if (_i17.done) break; + _ref17 = _i17.value; + } + + var ref = _ref17; + + var binding = ref.scope.getBinding(ref.node.name); + if (binding) { + binding.reference(ref); + } else { + ref.scope.getProgramParent().addGlobal(ref.node); + } + } + + for (var _iterator18 = state.constantViolations, _isArray18 = Array.isArray(_iterator18), _i18 = 0, _iterator18 = _isArray18 ? _iterator18 : (0, _getIterator3.default)(_iterator18);;) { + var _ref18; + + if (_isArray18) { + if (_i18 >= _iterator18.length) break; + _ref18 = _iterator18[_i18++]; + } else { + _i18 = _iterator18.next(); + if (_i18.done) break; + _ref18 = _i18.value; + } + + var _path2 = _ref18; + + _path2.scope.registerConstantViolation(_path2); + } + }; + + Scope.prototype.push = function push(opts) { + var path = this.path; + + if (!path.isBlockStatement() && !path.isProgram()) { + path = this.getBlockParent().path; + } + + if (path.isSwitchStatement()) { + path = this.getFunctionParent().path; + } + + if (path.isLoop() || path.isCatchClause() || path.isFunction()) { + t.ensureBlock(path.node); + path = path.get("body"); + } + + var unique = opts.unique; + var kind = opts.kind || "var"; + var blockHoist = opts._blockHoist == null ? 2 : opts._blockHoist; + + var dataKey = "declaration:" + kind + ":" + blockHoist; + var declarPath = !unique && path.getData(dataKey); + + if (!declarPath) { + var declar = t.variableDeclaration(kind, []); + declar._generated = true; + declar._blockHoist = blockHoist; + + var _path$unshiftContaine = path.unshiftContainer("body", [declar]); + + declarPath = _path$unshiftContaine[0]; + + if (!unique) path.setData(dataKey, declarPath); + } + + var declarator = t.variableDeclarator(opts.id, opts.init); + declarPath.node.declarations.push(declarator); + this.registerBinding(kind, declarPath.get("declarations").pop()); + }; + + Scope.prototype.getProgramParent = function getProgramParent() { + var scope = this; + do { + if (scope.path.isProgram()) { + return scope; + } + } while (scope = scope.parent); + throw new Error("We couldn't find a Function or Program..."); + }; + + Scope.prototype.getFunctionParent = function getFunctionParent() { + var scope = this; + do { + if (scope.path.isFunctionParent()) { + return scope; + } + } while (scope = scope.parent); + throw new Error("We couldn't find a Function or Program..."); + }; + + Scope.prototype.getBlockParent = function getBlockParent() { + var scope = this; + do { + if (scope.path.isBlockParent()) { + return scope; + } + } while (scope = scope.parent); + throw new Error("We couldn't find a BlockStatement, For, Switch, Function, Loop or Program..."); + }; + + Scope.prototype.getAllBindings = function getAllBindings() { + var ids = (0, _create2.default)(null); + + var scope = this; + do { + (0, _defaults2.default)(ids, scope.bindings); + scope = scope.parent; + } while (scope); + + return ids; + }; + + Scope.prototype.getAllBindingsOfKind = function getAllBindingsOfKind() { + var ids = (0, _create2.default)(null); + + for (var _iterator19 = arguments, _isArray19 = Array.isArray(_iterator19), _i19 = 0, _iterator19 = _isArray19 ? _iterator19 : (0, _getIterator3.default)(_iterator19);;) { + var _ref19; + + if (_isArray19) { + if (_i19 >= _iterator19.length) break; + _ref19 = _iterator19[_i19++]; + } else { + _i19 = _iterator19.next(); + if (_i19.done) break; + _ref19 = _i19.value; + } + + var kind = _ref19; + + var scope = this; + do { + for (var name in scope.bindings) { + var binding = scope.bindings[name]; + if (binding.kind === kind) ids[name] = binding; + } + scope = scope.parent; + } while (scope); + } + + return ids; + }; + + Scope.prototype.bindingIdentifierEquals = function bindingIdentifierEquals(name, node) { + return this.getBindingIdentifier(name) === node; + }; + + Scope.prototype.warnOnFlowBinding = function warnOnFlowBinding(binding) { + if (_crawlCallsCount === 0 && binding && binding.path.isFlow()) { + console.warn("\n You or one of the Babel plugins you are using are using Flow declarations as bindings.\n Support for this will be removed in version 6.8. To find out the caller, grep for this\n message and change it to a `console.trace()`.\n "); + } + return binding; + }; + + Scope.prototype.getBinding = function getBinding(name) { + var scope = this; + + do { + var binding = scope.getOwnBinding(name); + if (binding) return this.warnOnFlowBinding(binding); + } while (scope = scope.parent); + }; + + Scope.prototype.getOwnBinding = function getOwnBinding(name) { + return this.warnOnFlowBinding(this.bindings[name]); + }; + + Scope.prototype.getBindingIdentifier = function getBindingIdentifier(name) { + var info = this.getBinding(name); + return info && info.identifier; + }; + + Scope.prototype.getOwnBindingIdentifier = function getOwnBindingIdentifier(name) { + var binding = this.bindings[name]; + return binding && binding.identifier; + }; + + Scope.prototype.hasOwnBinding = function hasOwnBinding(name) { + return !!this.getOwnBinding(name); + }; + + Scope.prototype.hasBinding = function hasBinding(name, noGlobals) { + if (!name) return false; + if (this.hasOwnBinding(name)) return true; + if (this.parentHasBinding(name, noGlobals)) return true; + if (this.hasUid(name)) return true; + if (!noGlobals && (0, _includes2.default)(Scope.globals, name)) return true; + if (!noGlobals && (0, _includes2.default)(Scope.contextVariables, name)) return true; + return false; + }; + + Scope.prototype.parentHasBinding = function parentHasBinding(name, noGlobals) { + return this.parent && this.parent.hasBinding(name, noGlobals); + }; + + Scope.prototype.moveBindingTo = function moveBindingTo(name, scope) { + var info = this.getBinding(name); + if (info) { + info.scope.removeOwnBinding(name); + info.scope = scope; + scope.bindings[name] = info; + } + }; + + Scope.prototype.removeOwnBinding = function removeOwnBinding(name) { + delete this.bindings[name]; + }; + + Scope.prototype.removeBinding = function removeBinding(name) { + var info = this.getBinding(name); + if (info) { + info.scope.removeOwnBinding(name); + } + + var scope = this; + do { + if (scope.uids[name]) { + scope.uids[name] = false; + } + } while (scope = scope.parent); + }; + + return Scope; +}(); + +Scope.globals = (0, _keys2.default)(_globals2.default.builtin); +Scope.contextVariables = ["arguments", "undefined", "Infinity", "NaN"]; +exports.default = Scope; +module.exports = exports["default"]; +},{"../cache":76,"../index":79,"./binding":97,"./lib/renamer":99,"babel-messages":53,"babel-runtime/core-js/get-iterator":56,"babel-runtime/core-js/map":58,"babel-runtime/core-js/object/create":61,"babel-runtime/core-js/object/keys":63,"babel-runtime/helpers/classCallCheck":70,"babel-types":112,"globals":242,"lodash/defaults":420,"lodash/includes":431,"lodash/repeat":454}],99:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _binding = require("../binding"); + +var _binding2 = _interopRequireDefault(_binding); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var renameVisitor = { + ReferencedIdentifier: function ReferencedIdentifier(_ref, state) { + var node = _ref.node; + + if (node.name === state.oldName) { + node.name = state.newName; + } + }, + Scope: function Scope(path, state) { + if (!path.scope.bindingIdentifierEquals(state.oldName, state.binding.identifier)) { + path.skip(); + } + }, + "AssignmentExpression|Declaration": function AssignmentExpressionDeclaration(path, state) { + var ids = path.getOuterBindingIdentifiers(); + + for (var name in ids) { + if (name === state.oldName) ids[name].name = state.newName; + } + } +}; + +var Renamer = function () { + function Renamer(binding, oldName, newName) { + (0, _classCallCheck3.default)(this, Renamer); + + this.newName = newName; + this.oldName = oldName; + this.binding = binding; + } + + Renamer.prototype.maybeConvertFromExportDeclaration = function maybeConvertFromExportDeclaration(parentDeclar) { + var exportDeclar = parentDeclar.parentPath.isExportDeclaration() && parentDeclar.parentPath; + if (!exportDeclar) return; + + var isDefault = exportDeclar.isExportDefaultDeclaration(); + + if (isDefault && (parentDeclar.isFunctionDeclaration() || parentDeclar.isClassDeclaration()) && !parentDeclar.node.id) { + parentDeclar.node.id = parentDeclar.scope.generateUidIdentifier("default"); + } + + var bindingIdentifiers = parentDeclar.getOuterBindingIdentifiers(); + var specifiers = []; + + for (var name in bindingIdentifiers) { + var localName = name === this.oldName ? this.newName : name; + var exportedName = isDefault ? "default" : name; + specifiers.push(t.exportSpecifier(t.identifier(localName), t.identifier(exportedName))); + } + + if (specifiers.length) { + var aliasDeclar = t.exportNamedDeclaration(null, specifiers); + + if (parentDeclar.isFunctionDeclaration()) { + aliasDeclar._blockHoist = 3; + } + + exportDeclar.insertAfter(aliasDeclar); + exportDeclar.replaceWith(parentDeclar.node); + } + }; + + Renamer.prototype.maybeConvertFromClassFunctionDeclaration = function maybeConvertFromClassFunctionDeclaration(path) { + return; + + if (!path.isFunctionDeclaration() && !path.isClassDeclaration()) return; + if (this.binding.kind !== "hoisted") return; + + path.node.id = t.identifier(this.oldName); + path.node._blockHoist = 3; + + path.replaceWith(t.variableDeclaration("let", [t.variableDeclarator(t.identifier(this.newName), t.toExpression(path.node))])); + }; + + Renamer.prototype.maybeConvertFromClassFunctionExpression = function maybeConvertFromClassFunctionExpression(path) { + return; + + if (!path.isFunctionExpression() && !path.isClassExpression()) return; + if (this.binding.kind !== "local") return; + + path.node.id = t.identifier(this.oldName); + + this.binding.scope.parent.push({ + id: t.identifier(this.newName) + }); + + path.replaceWith(t.assignmentExpression("=", t.identifier(this.newName), path.node)); + }; + + Renamer.prototype.rename = function rename(block) { + var binding = this.binding, + oldName = this.oldName, + newName = this.newName; + var scope = binding.scope, + path = binding.path; + + + var parentDeclar = path.find(function (path) { + return path.isDeclaration() || path.isFunctionExpression(); + }); + if (parentDeclar) { + this.maybeConvertFromExportDeclaration(parentDeclar); + } + + scope.traverse(block || scope.block, renameVisitor, this); + + if (!block) { + scope.removeOwnBinding(oldName); + scope.bindings[newName] = binding; + this.binding.identifier.name = newName; + } + + if (binding.type === "hoisted") {} + + if (parentDeclar) { + this.maybeConvertFromClassFunctionDeclaration(parentDeclar); + this.maybeConvertFromClassFunctionExpression(parentDeclar); + } + }; + + return Renamer; +}(); + +exports.default = Renamer; +module.exports = exports["default"]; +},{"../binding":97,"babel-runtime/helpers/classCallCheck":70,"babel-types":112}],100:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +var _keys = require("babel-runtime/core-js/object/keys"); + +var _keys2 = _interopRequireDefault(_keys); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.explode = explode; +exports.verify = verify; +exports.merge = merge; + +var _virtualTypes = require("./path/lib/virtual-types"); + +var virtualTypes = _interopRequireWildcard(_virtualTypes); + +var _babelMessages = require("babel-messages"); + +var messages = _interopRequireWildcard(_babelMessages); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +var _clone = require("lodash/clone"); + +var _clone2 = _interopRequireDefault(_clone); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function explode(visitor) { + if (visitor._exploded) return visitor; + visitor._exploded = true; + + for (var nodeType in visitor) { + if (shouldIgnoreKey(nodeType)) continue; + + var parts = nodeType.split("|"); + if (parts.length === 1) continue; + + var fns = visitor[nodeType]; + delete visitor[nodeType]; + + for (var _iterator = parts, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var part = _ref; + + visitor[part] = fns; + } + } + + verify(visitor); + + delete visitor.__esModule; + + ensureEntranceObjects(visitor); + + ensureCallbackArrays(visitor); + + for (var _iterator2 = (0, _keys2.default)(visitor), _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var _nodeType3 = _ref2; + + if (shouldIgnoreKey(_nodeType3)) continue; + + var wrapper = virtualTypes[_nodeType3]; + if (!wrapper) continue; + + var _fns2 = visitor[_nodeType3]; + for (var type in _fns2) { + _fns2[type] = wrapCheck(wrapper, _fns2[type]); + } + + delete visitor[_nodeType3]; + + if (wrapper.types) { + for (var _iterator4 = wrapper.types, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : (0, _getIterator3.default)(_iterator4);;) { + var _ref4; + + if (_isArray4) { + if (_i4 >= _iterator4.length) break; + _ref4 = _iterator4[_i4++]; + } else { + _i4 = _iterator4.next(); + if (_i4.done) break; + _ref4 = _i4.value; + } + + var _type = _ref4; + + if (visitor[_type]) { + mergePair(visitor[_type], _fns2); + } else { + visitor[_type] = _fns2; + } + } + } else { + mergePair(visitor, _fns2); + } + } + + for (var _nodeType in visitor) { + if (shouldIgnoreKey(_nodeType)) continue; + + var _fns = visitor[_nodeType]; + + var aliases = t.FLIPPED_ALIAS_KEYS[_nodeType]; + + var deprecratedKey = t.DEPRECATED_KEYS[_nodeType]; + if (deprecratedKey) { + console.trace("Visitor defined for " + _nodeType + " but it has been renamed to " + deprecratedKey); + aliases = [deprecratedKey]; + } + + if (!aliases) continue; + + delete visitor[_nodeType]; + + for (var _iterator3 = aliases, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var alias = _ref3; + + var existing = visitor[alias]; + if (existing) { + mergePair(existing, _fns); + } else { + visitor[alias] = (0, _clone2.default)(_fns); + } + } + } + + for (var _nodeType2 in visitor) { + if (shouldIgnoreKey(_nodeType2)) continue; + + ensureCallbackArrays(visitor[_nodeType2]); + } + + return visitor; +} + +function verify(visitor) { + if (visitor._verified) return; + + if (typeof visitor === "function") { + throw new Error(messages.get("traverseVerifyRootFunction")); + } + + for (var nodeType in visitor) { + if (nodeType === "enter" || nodeType === "exit") { + validateVisitorMethods(nodeType, visitor[nodeType]); + } + + if (shouldIgnoreKey(nodeType)) continue; + + if (t.TYPES.indexOf(nodeType) < 0) { + throw new Error(messages.get("traverseVerifyNodeType", nodeType)); + } + + var visitors = visitor[nodeType]; + if ((typeof visitors === "undefined" ? "undefined" : (0, _typeof3.default)(visitors)) === "object") { + for (var visitorKey in visitors) { + if (visitorKey === "enter" || visitorKey === "exit") { + validateVisitorMethods(nodeType + "." + visitorKey, visitors[visitorKey]); + } else { + throw new Error(messages.get("traverseVerifyVisitorProperty", nodeType, visitorKey)); + } + } + } + } + + visitor._verified = true; +} + +function validateVisitorMethods(path, val) { + var fns = [].concat(val); + for (var _iterator5 = fns, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : (0, _getIterator3.default)(_iterator5);;) { + var _ref5; + + if (_isArray5) { + if (_i5 >= _iterator5.length) break; + _ref5 = _iterator5[_i5++]; + } else { + _i5 = _iterator5.next(); + if (_i5.done) break; + _ref5 = _i5.value; + } + + var fn = _ref5; + + if (typeof fn !== "function") { + throw new TypeError("Non-function found defined in " + path + " with type " + (typeof fn === "undefined" ? "undefined" : (0, _typeof3.default)(fn))); + } + } +} + +function merge(visitors) { + var states = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + var wrapper = arguments[2]; + + var rootVisitor = {}; + + for (var i = 0; i < visitors.length; i++) { + var visitor = visitors[i]; + var state = states[i]; + + explode(visitor); + + for (var type in visitor) { + var visitorType = visitor[type]; + + if (state || wrapper) { + visitorType = wrapWithStateOrWrapper(visitorType, state, wrapper); + } + + var nodeVisitor = rootVisitor[type] = rootVisitor[type] || {}; + mergePair(nodeVisitor, visitorType); + } + } + + return rootVisitor; +} + +function wrapWithStateOrWrapper(oldVisitor, state, wrapper) { + var newVisitor = {}; + + var _loop = function _loop(key) { + var fns = oldVisitor[key]; + + if (!Array.isArray(fns)) return "continue"; + + fns = fns.map(function (fn) { + var newFn = fn; + + if (state) { + newFn = function newFn(path) { + return fn.call(state, path, state); + }; + } + + if (wrapper) { + newFn = wrapper(state.key, key, newFn); + } + + return newFn; + }); + + newVisitor[key] = fns; + }; + + for (var key in oldVisitor) { + var _ret = _loop(key); + + if (_ret === "continue") continue; + } + + return newVisitor; +} + +function ensureEntranceObjects(obj) { + for (var key in obj) { + if (shouldIgnoreKey(key)) continue; + + var fns = obj[key]; + if (typeof fns === "function") { + obj[key] = { enter: fns }; + } + } +} + +function ensureCallbackArrays(obj) { + if (obj.enter && !Array.isArray(obj.enter)) obj.enter = [obj.enter]; + if (obj.exit && !Array.isArray(obj.exit)) obj.exit = [obj.exit]; +} + +function wrapCheck(wrapper, fn) { + var newFn = function newFn(path) { + if (wrapper.checkPath(path)) { + return fn.apply(this, arguments); + } + }; + newFn.toString = function () { + return fn.toString(); + }; + return newFn; +} + +function shouldIgnoreKey(key) { + if (key[0] === "_") return true; + + if (key === "enter" || key === "exit" || key === "shouldSkip") return true; + + if (key === "blacklist" || key === "noScope" || key === "skipKeys") return true; + + return false; +} + +function mergePair(dest, src) { + for (var key in src) { + dest[key] = [].concat(dest[key] || [], src[key]); + } +} +},{"./path/lib/virtual-types":93,"babel-messages":53,"babel-runtime/core-js/get-iterator":56,"babel-runtime/core-js/object/keys":63,"babel-runtime/helpers/typeof":74,"babel-types":112,"lodash/clone":416}],101:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.NOT_LOCAL_BINDING = exports.BLOCK_SCOPED_SYMBOL = exports.INHERIT_KEYS = exports.UNARY_OPERATORS = exports.STRING_UNARY_OPERATORS = exports.NUMBER_UNARY_OPERATORS = exports.BOOLEAN_UNARY_OPERATORS = exports.BINARY_OPERATORS = exports.NUMBER_BINARY_OPERATORS = exports.BOOLEAN_BINARY_OPERATORS = exports.COMPARISON_BINARY_OPERATORS = exports.EQUALITY_BINARY_OPERATORS = exports.BOOLEAN_NUMBER_BINARY_OPERATORS = exports.UPDATE_OPERATORS = exports.LOGICAL_OPERATORS = exports.COMMENT_KEYS = exports.FOR_INIT_KEYS = exports.FLATTENABLE_KEYS = exports.STATEMENT_OR_BLOCK_KEYS = undefined; + +var _for = require("babel-runtime/core-js/symbol/for"); + +var _for2 = _interopRequireDefault(_for); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var STATEMENT_OR_BLOCK_KEYS = exports.STATEMENT_OR_BLOCK_KEYS = ["consequent", "body", "alternate"]; +var FLATTENABLE_KEYS = exports.FLATTENABLE_KEYS = ["body", "expressions"]; +var FOR_INIT_KEYS = exports.FOR_INIT_KEYS = ["left", "init"]; +var COMMENT_KEYS = exports.COMMENT_KEYS = ["leadingComments", "trailingComments", "innerComments"]; + +var LOGICAL_OPERATORS = exports.LOGICAL_OPERATORS = ["||", "&&"]; +var UPDATE_OPERATORS = exports.UPDATE_OPERATORS = ["++", "--"]; + +var BOOLEAN_NUMBER_BINARY_OPERATORS = exports.BOOLEAN_NUMBER_BINARY_OPERATORS = [">", "<", ">=", "<="]; +var EQUALITY_BINARY_OPERATORS = exports.EQUALITY_BINARY_OPERATORS = ["==", "===", "!=", "!=="]; +var COMPARISON_BINARY_OPERATORS = exports.COMPARISON_BINARY_OPERATORS = [].concat(EQUALITY_BINARY_OPERATORS, ["in", "instanceof"]); +var BOOLEAN_BINARY_OPERATORS = exports.BOOLEAN_BINARY_OPERATORS = [].concat(COMPARISON_BINARY_OPERATORS, BOOLEAN_NUMBER_BINARY_OPERATORS); +var NUMBER_BINARY_OPERATORS = exports.NUMBER_BINARY_OPERATORS = ["-", "/", "%", "*", "**", "&", "|", ">>", ">>>", "<<", "^"]; +var BINARY_OPERATORS = exports.BINARY_OPERATORS = ["+"].concat(NUMBER_BINARY_OPERATORS, BOOLEAN_BINARY_OPERATORS); + +var BOOLEAN_UNARY_OPERATORS = exports.BOOLEAN_UNARY_OPERATORS = ["delete", "!"]; +var NUMBER_UNARY_OPERATORS = exports.NUMBER_UNARY_OPERATORS = ["+", "-", "++", "--", "~"]; +var STRING_UNARY_OPERATORS = exports.STRING_UNARY_OPERATORS = ["typeof"]; +var UNARY_OPERATORS = exports.UNARY_OPERATORS = ["void"].concat(BOOLEAN_UNARY_OPERATORS, NUMBER_UNARY_OPERATORS, STRING_UNARY_OPERATORS); + +var INHERIT_KEYS = exports.INHERIT_KEYS = { + optional: ["typeAnnotation", "typeParameters", "returnType"], + force: ["start", "loc", "end"] +}; + +var BLOCK_SCOPED_SYMBOL = exports.BLOCK_SCOPED_SYMBOL = (0, _for2.default)("var used to be block scoped"); +var NOT_LOCAL_BINDING = exports.NOT_LOCAL_BINDING = (0, _for2.default)("should not be considered a local binding"); +},{"babel-runtime/core-js/symbol/for":66}],102:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _maxSafeInteger = require("babel-runtime/core-js/number/max-safe-integer"); + +var _maxSafeInteger2 = _interopRequireDefault(_maxSafeInteger); + +var _stringify = require("babel-runtime/core-js/json/stringify"); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.toComputedKey = toComputedKey; +exports.toSequenceExpression = toSequenceExpression; +exports.toKeyAlias = toKeyAlias; +exports.toIdentifier = toIdentifier; +exports.toBindingIdentifierName = toBindingIdentifierName; +exports.toStatement = toStatement; +exports.toExpression = toExpression; +exports.toBlock = toBlock; +exports.valueToNode = valueToNode; + +var _isPlainObject = require("lodash/isPlainObject"); + +var _isPlainObject2 = _interopRequireDefault(_isPlainObject); + +var _isRegExp = require("lodash/isRegExp"); + +var _isRegExp2 = _interopRequireDefault(_isRegExp); + +var _index = require("./index"); + +var t = _interopRequireWildcard(_index); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function toComputedKey(node) { + var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : node.key || node.property; + + if (!node.computed) { + if (t.isIdentifier(key)) key = t.stringLiteral(key.name); + } + return key; +} + +function toSequenceExpression(nodes, scope) { + if (!nodes || !nodes.length) return; + + var declars = []; + var bailed = false; + + var result = convert(nodes); + if (bailed) return; + + for (var i = 0; i < declars.length; i++) { + scope.push(declars[i]); + } + + return result; + + function convert(nodes) { + var ensureLastUndefined = false; + var exprs = []; + + for (var _iterator = nodes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var node = _ref; + + if (t.isExpression(node)) { + exprs.push(node); + } else if (t.isExpressionStatement(node)) { + exprs.push(node.expression); + } else if (t.isVariableDeclaration(node)) { + if (node.kind !== "var") return bailed = true; + + for (var _iterator2 = node.declarations, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var declar = _ref2; + + var bindings = t.getBindingIdentifiers(declar); + for (var key in bindings) { + declars.push({ + kind: node.kind, + id: bindings[key] + }); + } + + if (declar.init) { + exprs.push(t.assignmentExpression("=", declar.id, declar.init)); + } + } + + ensureLastUndefined = true; + continue; + } else if (t.isIfStatement(node)) { + var consequent = node.consequent ? convert([node.consequent]) : scope.buildUndefinedNode(); + var alternate = node.alternate ? convert([node.alternate]) : scope.buildUndefinedNode(); + if (!consequent || !alternate) return bailed = true; + + exprs.push(t.conditionalExpression(node.test, consequent, alternate)); + } else if (t.isBlockStatement(node)) { + exprs.push(convert(node.body)); + } else if (t.isEmptyStatement(node)) { + ensureLastUndefined = true; + continue; + } else { + return bailed = true; + } + + ensureLastUndefined = false; + } + + if (ensureLastUndefined || exprs.length === 0) { + exprs.push(scope.buildUndefinedNode()); + } + + if (exprs.length === 1) { + return exprs[0]; + } else { + return t.sequenceExpression(exprs); + } + } +} + +function toKeyAlias(node) { + var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : node.key; + + var alias = void 0; + + if (node.kind === "method") { + return toKeyAlias.increment() + ""; + } else if (t.isIdentifier(key)) { + alias = key.name; + } else if (t.isStringLiteral(key)) { + alias = (0, _stringify2.default)(key.value); + } else { + alias = (0, _stringify2.default)(t.removePropertiesDeep(t.cloneDeep(key))); + } + + if (node.computed) { + alias = "[" + alias + "]"; + } + + if (node.static) { + alias = "static:" + alias; + } + + return alias; +} + +toKeyAlias.uid = 0; + +toKeyAlias.increment = function () { + if (toKeyAlias.uid >= _maxSafeInteger2.default) { + return toKeyAlias.uid = 0; + } else { + return toKeyAlias.uid++; + } +}; + +function toIdentifier(name) { + name = name + ""; + + name = name.replace(/[^a-zA-Z0-9$_]/g, "-"); + + name = name.replace(/^[-0-9]+/, ""); + + name = name.replace(/[-\s]+(.)?/g, function (match, c) { + return c ? c.toUpperCase() : ""; + }); + + if (!t.isValidIdentifier(name)) { + name = "_" + name; + } + + return name || "_"; +} + +function toBindingIdentifierName(name) { + name = toIdentifier(name); + if (name === "eval" || name === "arguments") name = "_" + name; + return name; +} + +function toStatement(node, ignore) { + if (t.isStatement(node)) { + return node; + } + + var mustHaveId = false; + var newType = void 0; + + if (t.isClass(node)) { + mustHaveId = true; + newType = "ClassDeclaration"; + } else if (t.isFunction(node)) { + mustHaveId = true; + newType = "FunctionDeclaration"; + } else if (t.isAssignmentExpression(node)) { + return t.expressionStatement(node); + } + + if (mustHaveId && !node.id) { + newType = false; + } + + if (!newType) { + if (ignore) { + return false; + } else { + throw new Error("cannot turn " + node.type + " to a statement"); + } + } + + node.type = newType; + + return node; +} + +function toExpression(node) { + if (t.isExpressionStatement(node)) { + node = node.expression; + } + + if (t.isExpression(node)) { + return node; + } + + if (t.isClass(node)) { + node.type = "ClassExpression"; + } else if (t.isFunction(node)) { + node.type = "FunctionExpression"; + } + + if (!t.isExpression(node)) { + throw new Error("cannot turn " + node.type + " to an expression"); + } + + return node; +} + +function toBlock(node, parent) { + if (t.isBlockStatement(node)) { + return node; + } + + if (t.isEmptyStatement(node)) { + node = []; + } + + if (!Array.isArray(node)) { + if (!t.isStatement(node)) { + if (t.isFunction(parent)) { + node = t.returnStatement(node); + } else { + node = t.expressionStatement(node); + } + } + + node = [node]; + } + + return t.blockStatement(node); +} + +function valueToNode(value) { + if (value === undefined) { + return t.identifier("undefined"); + } + + if (value === true || value === false) { + return t.booleanLiteral(value); + } + + if (value === null) { + return t.nullLiteral(); + } + + if (typeof value === "string") { + return t.stringLiteral(value); + } + + if (typeof value === "number") { + return t.numericLiteral(value); + } + + if ((0, _isRegExp2.default)(value)) { + var pattern = value.source; + var flags = value.toString().match(/\/([a-z]+|)$/)[1]; + return t.regExpLiteral(pattern, flags); + } + + if (Array.isArray(value)) { + return t.arrayExpression(value.map(t.valueToNode)); + } + + if ((0, _isPlainObject2.default)(value)) { + var props = []; + for (var key in value) { + var nodeKey = void 0; + if (t.isValidIdentifier(key)) { + nodeKey = t.identifier(key); + } else { + nodeKey = t.stringLiteral(key); + } + props.push(t.objectProperty(nodeKey, t.valueToNode(value[key]))); + } + return t.objectExpression(props); + } + + throw new Error("don't know how to turn this value into a node"); +} +},{"./index":112,"babel-runtime/core-js/get-iterator":56,"babel-runtime/core-js/json/stringify":57,"babel-runtime/core-js/number/max-safe-integer":59,"lodash/isPlainObject":442,"lodash/isRegExp":443}],103:[function(require,module,exports){ +"use strict"; + +var _index = require("../index"); + +var t = _interopRequireWildcard(_index); + +var _constants = require("../constants"); + +var _index2 = require("./index"); + +var _index3 = _interopRequireDefault(_index2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +(0, _index3.default)("ArrayExpression", { + fields: { + elements: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeOrValueType)("null", "Expression", "SpreadElement"))), + default: [] + } + }, + visitor: ["elements"], + aliases: ["Expression"] +}); + +(0, _index3.default)("AssignmentExpression", { + fields: { + operator: { + validate: (0, _index2.assertValueType)("string") + }, + left: { + validate: (0, _index2.assertNodeType)("LVal") + }, + right: { + validate: (0, _index2.assertNodeType)("Expression") + } + }, + builder: ["operator", "left", "right"], + visitor: ["left", "right"], + aliases: ["Expression"] +}); + +(0, _index3.default)("BinaryExpression", { + builder: ["operator", "left", "right"], + fields: { + operator: { + validate: _index2.assertOneOf.apply(undefined, _constants.BINARY_OPERATORS) + }, + left: { + validate: (0, _index2.assertNodeType)("Expression") + }, + right: { + validate: (0, _index2.assertNodeType)("Expression") + } + }, + visitor: ["left", "right"], + aliases: ["Binary", "Expression"] +}); + +(0, _index3.default)("Directive", { + visitor: ["value"], + fields: { + value: { + validate: (0, _index2.assertNodeType)("DirectiveLiteral") + } + } +}); + +(0, _index3.default)("DirectiveLiteral", { + builder: ["value"], + fields: { + value: { + validate: (0, _index2.assertValueType)("string") + } + } +}); + +(0, _index3.default)("BlockStatement", { + builder: ["body", "directives"], + visitor: ["directives", "body"], + fields: { + directives: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("Directive"))), + default: [] + }, + body: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("Statement"))) + } + }, + aliases: ["Scopable", "BlockParent", "Block", "Statement"] +}); + +(0, _index3.default)("BreakStatement", { + visitor: ["label"], + fields: { + label: { + validate: (0, _index2.assertNodeType)("Identifier"), + optional: true + } + }, + aliases: ["Statement", "Terminatorless", "CompletionStatement"] +}); + +(0, _index3.default)("CallExpression", { + visitor: ["callee", "arguments"], + fields: { + callee: { + validate: (0, _index2.assertNodeType)("Expression") + }, + arguments: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("Expression", "SpreadElement"))) + } + }, + aliases: ["Expression"] +}); + +(0, _index3.default)("CatchClause", { + visitor: ["param", "body"], + fields: { + param: { + validate: (0, _index2.assertNodeType)("Identifier") + }, + body: { + validate: (0, _index2.assertNodeType)("BlockStatement") + } + }, + aliases: ["Scopable"] +}); + +(0, _index3.default)("ConditionalExpression", { + visitor: ["test", "consequent", "alternate"], + fields: { + test: { + validate: (0, _index2.assertNodeType)("Expression") + }, + consequent: { + validate: (0, _index2.assertNodeType)("Expression") + }, + alternate: { + validate: (0, _index2.assertNodeType)("Expression") + } + }, + aliases: ["Expression", "Conditional"] +}); + +(0, _index3.default)("ContinueStatement", { + visitor: ["label"], + fields: { + label: { + validate: (0, _index2.assertNodeType)("Identifier"), + optional: true + } + }, + aliases: ["Statement", "Terminatorless", "CompletionStatement"] +}); + +(0, _index3.default)("DebuggerStatement", { + aliases: ["Statement"] +}); + +(0, _index3.default)("DoWhileStatement", { + visitor: ["test", "body"], + fields: { + test: { + validate: (0, _index2.assertNodeType)("Expression") + }, + body: { + validate: (0, _index2.assertNodeType)("Statement") + } + }, + aliases: ["Statement", "BlockParent", "Loop", "While", "Scopable"] +}); + +(0, _index3.default)("EmptyStatement", { + aliases: ["Statement"] +}); + +(0, _index3.default)("ExpressionStatement", { + visitor: ["expression"], + fields: { + expression: { + validate: (0, _index2.assertNodeType)("Expression") + } + }, + aliases: ["Statement", "ExpressionWrapper"] +}); + +(0, _index3.default)("File", { + builder: ["program", "comments", "tokens"], + visitor: ["program"], + fields: { + program: { + validate: (0, _index2.assertNodeType)("Program") + } + } +}); + +(0, _index3.default)("ForInStatement", { + visitor: ["left", "right", "body"], + aliases: ["Scopable", "Statement", "For", "BlockParent", "Loop", "ForXStatement"], + fields: { + left: { + validate: (0, _index2.assertNodeType)("VariableDeclaration", "LVal") + }, + right: { + validate: (0, _index2.assertNodeType)("Expression") + }, + body: { + validate: (0, _index2.assertNodeType)("Statement") + } + } +}); + +(0, _index3.default)("ForStatement", { + visitor: ["init", "test", "update", "body"], + aliases: ["Scopable", "Statement", "For", "BlockParent", "Loop"], + fields: { + init: { + validate: (0, _index2.assertNodeType)("VariableDeclaration", "Expression"), + optional: true + }, + test: { + validate: (0, _index2.assertNodeType)("Expression"), + optional: true + }, + update: { + validate: (0, _index2.assertNodeType)("Expression"), + optional: true + }, + body: { + validate: (0, _index2.assertNodeType)("Statement") + } + } +}); + +(0, _index3.default)("FunctionDeclaration", { + builder: ["id", "params", "body", "generator", "async"], + visitor: ["id", "params", "body", "returnType", "typeParameters"], + fields: { + id: { + validate: (0, _index2.assertNodeType)("Identifier") + }, + params: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("LVal"))) + }, + body: { + validate: (0, _index2.assertNodeType)("BlockStatement") + }, + generator: { + default: false, + validate: (0, _index2.assertValueType)("boolean") + }, + async: { + default: false, + validate: (0, _index2.assertValueType)("boolean") + } + }, + aliases: ["Scopable", "Function", "BlockParent", "FunctionParent", "Statement", "Pureish", "Declaration"] +}); + +(0, _index3.default)("FunctionExpression", { + inherits: "FunctionDeclaration", + aliases: ["Scopable", "Function", "BlockParent", "FunctionParent", "Expression", "Pureish"], + fields: { + id: { + validate: (0, _index2.assertNodeType)("Identifier"), + optional: true + }, + params: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("LVal"))) + }, + body: { + validate: (0, _index2.assertNodeType)("BlockStatement") + }, + generator: { + default: false, + validate: (0, _index2.assertValueType)("boolean") + }, + async: { + default: false, + validate: (0, _index2.assertValueType)("boolean") + } + } +}); + +(0, _index3.default)("Identifier", { + builder: ["name"], + visitor: ["typeAnnotation"], + aliases: ["Expression", "LVal"], + fields: { + name: { + validate: function validate(node, key, val) { + if (!t.isValidIdentifier(val)) {} + } + }, + decorators: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("Decorator"))) + } + } +}); + +(0, _index3.default)("IfStatement", { + visitor: ["test", "consequent", "alternate"], + aliases: ["Statement", "Conditional"], + fields: { + test: { + validate: (0, _index2.assertNodeType)("Expression") + }, + consequent: { + validate: (0, _index2.assertNodeType)("Statement") + }, + alternate: { + optional: true, + validate: (0, _index2.assertNodeType)("Statement") + } + } +}); + +(0, _index3.default)("LabeledStatement", { + visitor: ["label", "body"], + aliases: ["Statement"], + fields: { + label: { + validate: (0, _index2.assertNodeType)("Identifier") + }, + body: { + validate: (0, _index2.assertNodeType)("Statement") + } + } +}); + +(0, _index3.default)("StringLiteral", { + builder: ["value"], + fields: { + value: { + validate: (0, _index2.assertValueType)("string") + } + }, + aliases: ["Expression", "Pureish", "Literal", "Immutable"] +}); + +(0, _index3.default)("NumericLiteral", { + builder: ["value"], + deprecatedAlias: "NumberLiteral", + fields: { + value: { + validate: (0, _index2.assertValueType)("number") + } + }, + aliases: ["Expression", "Pureish", "Literal", "Immutable"] +}); + +(0, _index3.default)("NullLiteral", { + aliases: ["Expression", "Pureish", "Literal", "Immutable"] +}); + +(0, _index3.default)("BooleanLiteral", { + builder: ["value"], + fields: { + value: { + validate: (0, _index2.assertValueType)("boolean") + } + }, + aliases: ["Expression", "Pureish", "Literal", "Immutable"] +}); + +(0, _index3.default)("RegExpLiteral", { + builder: ["pattern", "flags"], + deprecatedAlias: "RegexLiteral", + aliases: ["Expression", "Literal"], + fields: { + pattern: { + validate: (0, _index2.assertValueType)("string") + }, + flags: { + validate: (0, _index2.assertValueType)("string"), + default: "" + } + } +}); + +(0, _index3.default)("LogicalExpression", { + builder: ["operator", "left", "right"], + visitor: ["left", "right"], + aliases: ["Binary", "Expression"], + fields: { + operator: { + validate: _index2.assertOneOf.apply(undefined, _constants.LOGICAL_OPERATORS) + }, + left: { + validate: (0, _index2.assertNodeType)("Expression") + }, + right: { + validate: (0, _index2.assertNodeType)("Expression") + } + } +}); + +(0, _index3.default)("MemberExpression", { + builder: ["object", "property", "computed"], + visitor: ["object", "property"], + aliases: ["Expression", "LVal"], + fields: { + object: { + validate: (0, _index2.assertNodeType)("Expression") + }, + property: { + validate: function validate(node, key, val) { + var expectedType = node.computed ? "Expression" : "Identifier"; + (0, _index2.assertNodeType)(expectedType)(node, key, val); + } + }, + computed: { + default: false + } + } +}); + +(0, _index3.default)("NewExpression", { + visitor: ["callee", "arguments"], + aliases: ["Expression"], + fields: { + callee: { + validate: (0, _index2.assertNodeType)("Expression") + }, + arguments: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("Expression", "SpreadElement"))) + } + } +}); + +(0, _index3.default)("Program", { + visitor: ["directives", "body"], + builder: ["body", "directives"], + fields: { + directives: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("Directive"))), + default: [] + }, + body: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("Statement"))) + } + }, + aliases: ["Scopable", "BlockParent", "Block", "FunctionParent"] +}); + +(0, _index3.default)("ObjectExpression", { + visitor: ["properties"], + aliases: ["Expression"], + fields: { + properties: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("ObjectMethod", "ObjectProperty", "SpreadProperty"))) + } + } +}); + +(0, _index3.default)("ObjectMethod", { + builder: ["kind", "key", "params", "body", "computed"], + fields: { + kind: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("string"), (0, _index2.assertOneOf)("method", "get", "set")), + default: "method" + }, + computed: { + validate: (0, _index2.assertValueType)("boolean"), + default: false + }, + key: { + validate: function validate(node, key, val) { + var expectedTypes = node.computed ? ["Expression"] : ["Identifier", "StringLiteral", "NumericLiteral"]; + _index2.assertNodeType.apply(undefined, expectedTypes)(node, key, val); + } + }, + decorators: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("Decorator"))) + }, + body: { + validate: (0, _index2.assertNodeType)("BlockStatement") + }, + generator: { + default: false, + validate: (0, _index2.assertValueType)("boolean") + }, + async: { + default: false, + validate: (0, _index2.assertValueType)("boolean") + } + }, + visitor: ["key", "params", "body", "decorators", "returnType", "typeParameters"], + aliases: ["UserWhitespacable", "Function", "Scopable", "BlockParent", "FunctionParent", "Method", "ObjectMember"] +}); + +(0, _index3.default)("ObjectProperty", { + builder: ["key", "value", "computed", "shorthand", "decorators"], + fields: { + computed: { + validate: (0, _index2.assertValueType)("boolean"), + default: false + }, + key: { + validate: function validate(node, key, val) { + var expectedTypes = node.computed ? ["Expression"] : ["Identifier", "StringLiteral", "NumericLiteral"]; + _index2.assertNodeType.apply(undefined, expectedTypes)(node, key, val); + } + }, + value: { + validate: (0, _index2.assertNodeType)("Expression") + }, + shorthand: { + validate: (0, _index2.assertValueType)("boolean"), + default: false + }, + decorators: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("Decorator"))), + optional: true + } + }, + visitor: ["key", "value", "decorators"], + aliases: ["UserWhitespacable", "Property", "ObjectMember"] +}); + +(0, _index3.default)("RestElement", { + visitor: ["argument", "typeAnnotation"], + aliases: ["LVal"], + fields: { + argument: { + validate: (0, _index2.assertNodeType)("LVal") + }, + decorators: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("Decorator"))) + } + } +}); + +(0, _index3.default)("ReturnStatement", { + visitor: ["argument"], + aliases: ["Statement", "Terminatorless", "CompletionStatement"], + fields: { + argument: { + validate: (0, _index2.assertNodeType)("Expression"), + optional: true + } + } +}); + +(0, _index3.default)("SequenceExpression", { + visitor: ["expressions"], + fields: { + expressions: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("Expression"))) + } + }, + aliases: ["Expression"] +}); + +(0, _index3.default)("SwitchCase", { + visitor: ["test", "consequent"], + fields: { + test: { + validate: (0, _index2.assertNodeType)("Expression"), + optional: true + }, + consequent: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("Statement"))) + } + } +}); + +(0, _index3.default)("SwitchStatement", { + visitor: ["discriminant", "cases"], + aliases: ["Statement", "BlockParent", "Scopable"], + fields: { + discriminant: { + validate: (0, _index2.assertNodeType)("Expression") + }, + cases: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("SwitchCase"))) + } + } +}); + +(0, _index3.default)("ThisExpression", { + aliases: ["Expression"] +}); + +(0, _index3.default)("ThrowStatement", { + visitor: ["argument"], + aliases: ["Statement", "Terminatorless", "CompletionStatement"], + fields: { + argument: { + validate: (0, _index2.assertNodeType)("Expression") + } + } +}); + +(0, _index3.default)("TryStatement", { + visitor: ["block", "handler", "finalizer"], + aliases: ["Statement"], + fields: { + body: { + validate: (0, _index2.assertNodeType)("BlockStatement") + }, + handler: { + optional: true, + handler: (0, _index2.assertNodeType)("BlockStatement") + }, + finalizer: { + optional: true, + validate: (0, _index2.assertNodeType)("BlockStatement") + } + } +}); + +(0, _index3.default)("UnaryExpression", { + builder: ["operator", "argument", "prefix"], + fields: { + prefix: { + default: true + }, + argument: { + validate: (0, _index2.assertNodeType)("Expression") + }, + operator: { + validate: _index2.assertOneOf.apply(undefined, _constants.UNARY_OPERATORS) + } + }, + visitor: ["argument"], + aliases: ["UnaryLike", "Expression"] +}); + +(0, _index3.default)("UpdateExpression", { + builder: ["operator", "argument", "prefix"], + fields: { + prefix: { + default: false + }, + argument: { + validate: (0, _index2.assertNodeType)("Expression") + }, + operator: { + validate: _index2.assertOneOf.apply(undefined, _constants.UPDATE_OPERATORS) + } + }, + visitor: ["argument"], + aliases: ["Expression"] +}); + +(0, _index3.default)("VariableDeclaration", { + builder: ["kind", "declarations"], + visitor: ["declarations"], + aliases: ["Statement", "Declaration"], + fields: { + kind: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("string"), (0, _index2.assertOneOf)("var", "let", "const")) + }, + declarations: { + validate: (0, _index2.chain)((0, _index2.assertValueType)("array"), (0, _index2.assertEach)((0, _index2.assertNodeType)("VariableDeclarator"))) + } + } +}); + +(0, _index3.default)("VariableDeclarator", { + visitor: ["id", "init"], + fields: { + id: { + validate: (0, _index2.assertNodeType)("LVal") + }, + init: { + optional: true, + validate: (0, _index2.assertNodeType)("Expression") + } + } +}); + +(0, _index3.default)("WhileStatement", { + visitor: ["test", "body"], + aliases: ["Statement", "BlockParent", "Loop", "While", "Scopable"], + fields: { + test: { + validate: (0, _index2.assertNodeType)("Expression") + }, + body: { + validate: (0, _index2.assertNodeType)("BlockStatement", "Statement") + } + } +}); + +(0, _index3.default)("WithStatement", { + visitor: ["object", "body"], + aliases: ["Statement"], + fields: { + object: { + object: (0, _index2.assertNodeType)("Expression") + }, + body: { + validate: (0, _index2.assertNodeType)("BlockStatement", "Statement") + } + } +}); +},{"../constants":101,"../index":112,"./index":107}],104:[function(require,module,exports){ +"use strict"; + +var _index = require("./index"); + +var _index2 = _interopRequireDefault(_index); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +(0, _index2.default)("AssignmentPattern", { + visitor: ["left", "right"], + aliases: ["Pattern", "LVal"], + fields: { + left: { + validate: (0, _index.assertNodeType)("Identifier") + }, + right: { + validate: (0, _index.assertNodeType)("Expression") + }, + decorators: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("Decorator"))) + } + } +}); + +(0, _index2.default)("ArrayPattern", { + visitor: ["elements", "typeAnnotation"], + aliases: ["Pattern", "LVal"], + fields: { + elements: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("Expression"))) + }, + decorators: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("Decorator"))) + } + } +}); + +(0, _index2.default)("ArrowFunctionExpression", { + builder: ["params", "body", "async"], + visitor: ["params", "body", "returnType", "typeParameters"], + aliases: ["Scopable", "Function", "BlockParent", "FunctionParent", "Expression", "Pureish"], + fields: { + params: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("LVal"))) + }, + body: { + validate: (0, _index.assertNodeType)("BlockStatement", "Expression") + }, + async: { + validate: (0, _index.assertValueType)("boolean"), + default: false + } + } +}); + +(0, _index2.default)("ClassBody", { + visitor: ["body"], + fields: { + body: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("ClassMethod", "ClassProperty"))) + } + } +}); + +(0, _index2.default)("ClassDeclaration", { + builder: ["id", "superClass", "body", "decorators"], + visitor: ["id", "body", "superClass", "mixins", "typeParameters", "superTypeParameters", "implements", "decorators"], + aliases: ["Scopable", "Class", "Statement", "Declaration", "Pureish"], + fields: { + id: { + validate: (0, _index.assertNodeType)("Identifier") + }, + body: { + validate: (0, _index.assertNodeType)("ClassBody") + }, + superClass: { + optional: true, + validate: (0, _index.assertNodeType)("Expression") + }, + decorators: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("Decorator"))) + } + } +}); + +(0, _index2.default)("ClassExpression", { + inherits: "ClassDeclaration", + aliases: ["Scopable", "Class", "Expression", "Pureish"], + fields: { + id: { + optional: true, + validate: (0, _index.assertNodeType)("Identifier") + }, + body: { + validate: (0, _index.assertNodeType)("ClassBody") + }, + superClass: { + optional: true, + validate: (0, _index.assertNodeType)("Expression") + }, + decorators: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("Decorator"))) + } + } +}); + +(0, _index2.default)("ExportAllDeclaration", { + visitor: ["source"], + aliases: ["Statement", "Declaration", "ModuleDeclaration", "ExportDeclaration"], + fields: { + source: { + validate: (0, _index.assertNodeType)("StringLiteral") + } + } +}); + +(0, _index2.default)("ExportDefaultDeclaration", { + visitor: ["declaration"], + aliases: ["Statement", "Declaration", "ModuleDeclaration", "ExportDeclaration"], + fields: { + declaration: { + validate: (0, _index.assertNodeType)("FunctionDeclaration", "ClassDeclaration", "Expression") + } + } +}); + +(0, _index2.default)("ExportNamedDeclaration", { + visitor: ["declaration", "specifiers", "source"], + aliases: ["Statement", "Declaration", "ModuleDeclaration", "ExportDeclaration"], + fields: { + declaration: { + validate: (0, _index.assertNodeType)("Declaration"), + optional: true + }, + specifiers: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("ExportSpecifier"))) + }, + source: { + validate: (0, _index.assertNodeType)("StringLiteral"), + optional: true + } + } +}); + +(0, _index2.default)("ExportSpecifier", { + visitor: ["local", "exported"], + aliases: ["ModuleSpecifier"], + fields: { + local: { + validate: (0, _index.assertNodeType)("Identifier") + }, + exported: { + validate: (0, _index.assertNodeType)("Identifier") + } + } +}); + +(0, _index2.default)("ForOfStatement", { + visitor: ["left", "right", "body"], + aliases: ["Scopable", "Statement", "For", "BlockParent", "Loop", "ForXStatement"], + fields: { + left: { + validate: (0, _index.assertNodeType)("VariableDeclaration", "LVal") + }, + right: { + validate: (0, _index.assertNodeType)("Expression") + }, + body: { + validate: (0, _index.assertNodeType)("Statement") + } + } +}); + +(0, _index2.default)("ImportDeclaration", { + visitor: ["specifiers", "source"], + aliases: ["Statement", "Declaration", "ModuleDeclaration"], + fields: { + specifiers: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("ImportSpecifier", "ImportDefaultSpecifier", "ImportNamespaceSpecifier"))) + }, + source: { + validate: (0, _index.assertNodeType)("StringLiteral") + } + } +}); + +(0, _index2.default)("ImportDefaultSpecifier", { + visitor: ["local"], + aliases: ["ModuleSpecifier"], + fields: { + local: { + validate: (0, _index.assertNodeType)("Identifier") + } + } +}); + +(0, _index2.default)("ImportNamespaceSpecifier", { + visitor: ["local"], + aliases: ["ModuleSpecifier"], + fields: { + local: { + validate: (0, _index.assertNodeType)("Identifier") + } + } +}); + +(0, _index2.default)("ImportSpecifier", { + visitor: ["local", "imported"], + aliases: ["ModuleSpecifier"], + fields: { + local: { + validate: (0, _index.assertNodeType)("Identifier") + }, + imported: { + validate: (0, _index.assertNodeType)("Identifier") + }, + importKind: { + validate: (0, _index.assertOneOf)(null, "type", "typeof") + } + } +}); + +(0, _index2.default)("MetaProperty", { + visitor: ["meta", "property"], + aliases: ["Expression"], + fields: { + meta: { + validate: (0, _index.assertValueType)("string") + }, + property: { + validate: (0, _index.assertValueType)("string") + } + } +}); + +(0, _index2.default)("ClassMethod", { + aliases: ["Function", "Scopable", "BlockParent", "FunctionParent", "Method"], + builder: ["kind", "key", "params", "body", "computed", "static"], + visitor: ["key", "params", "body", "decorators", "returnType", "typeParameters"], + fields: { + kind: { + validate: (0, _index.chain)((0, _index.assertValueType)("string"), (0, _index.assertOneOf)("get", "set", "method", "constructor")), + default: "method" + }, + computed: { + default: false, + validate: (0, _index.assertValueType)("boolean") + }, + static: { + default: false, + validate: (0, _index.assertValueType)("boolean") + }, + key: { + validate: function validate(node, key, val) { + var expectedTypes = node.computed ? ["Expression"] : ["Identifier", "StringLiteral", "NumericLiteral"]; + _index.assertNodeType.apply(undefined, expectedTypes)(node, key, val); + } + }, + params: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("LVal"))) + }, + body: { + validate: (0, _index.assertNodeType)("BlockStatement") + }, + generator: { + default: false, + validate: (0, _index.assertValueType)("boolean") + }, + async: { + default: false, + validate: (0, _index.assertValueType)("boolean") + } + } +}); + +(0, _index2.default)("ObjectPattern", { + visitor: ["properties", "typeAnnotation"], + aliases: ["Pattern", "LVal"], + fields: { + properties: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("RestProperty", "Property"))) + }, + decorators: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("Decorator"))) + } + } +}); + +(0, _index2.default)("SpreadElement", { + visitor: ["argument"], + aliases: ["UnaryLike"], + fields: { + argument: { + validate: (0, _index.assertNodeType)("Expression") + } + } +}); + +(0, _index2.default)("Super", { + aliases: ["Expression"] +}); + +(0, _index2.default)("TaggedTemplateExpression", { + visitor: ["tag", "quasi"], + aliases: ["Expression"], + fields: { + tag: { + validate: (0, _index.assertNodeType)("Expression") + }, + quasi: { + validate: (0, _index.assertNodeType)("TemplateLiteral") + } + } +}); + +(0, _index2.default)("TemplateElement", { + builder: ["value", "tail"], + fields: { + value: {}, + tail: { + validate: (0, _index.assertValueType)("boolean"), + default: false + } + } +}); + +(0, _index2.default)("TemplateLiteral", { + visitor: ["quasis", "expressions"], + aliases: ["Expression", "Literal"], + fields: { + quasis: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("TemplateElement"))) + }, + expressions: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("Expression"))) + } + } +}); + +(0, _index2.default)("YieldExpression", { + builder: ["argument", "delegate"], + visitor: ["argument"], + aliases: ["Expression", "Terminatorless"], + fields: { + delegate: { + validate: (0, _index.assertValueType)("boolean"), + default: false + }, + argument: { + optional: true, + validate: (0, _index.assertNodeType)("Expression") + } + } +}); +},{"./index":107}],105:[function(require,module,exports){ +"use strict"; + +var _index = require("./index"); + +var _index2 = _interopRequireDefault(_index); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +(0, _index2.default)("AwaitExpression", { + builder: ["argument"], + visitor: ["argument"], + aliases: ["Expression", "Terminatorless"], + fields: { + argument: { + validate: (0, _index.assertNodeType)("Expression") + } + } +}); + +(0, _index2.default)("ForAwaitStatement", { + visitor: ["left", "right", "body"], + aliases: ["Scopable", "Statement", "For", "BlockParent", "Loop", "ForXStatement"], + fields: { + left: { + validate: (0, _index.assertNodeType)("VariableDeclaration", "LVal") + }, + right: { + validate: (0, _index.assertNodeType)("Expression") + }, + body: { + validate: (0, _index.assertNodeType)("Statement") + } + } +}); + +(0, _index2.default)("BindExpression", { + visitor: ["object", "callee"], + aliases: ["Expression"], + fields: {} +}); + +(0, _index2.default)("Import", { + aliases: ["Expression"] +}); + +(0, _index2.default)("Decorator", { + visitor: ["expression"], + fields: { + expression: { + validate: (0, _index.assertNodeType)("Expression") + } + } +}); + +(0, _index2.default)("DoExpression", { + visitor: ["body"], + aliases: ["Expression"], + fields: { + body: { + validate: (0, _index.assertNodeType)("BlockStatement") + } + } +}); + +(0, _index2.default)("ExportDefaultSpecifier", { + visitor: ["exported"], + aliases: ["ModuleSpecifier"], + fields: { + exported: { + validate: (0, _index.assertNodeType)("Identifier") + } + } +}); + +(0, _index2.default)("ExportNamespaceSpecifier", { + visitor: ["exported"], + aliases: ["ModuleSpecifier"], + fields: { + exported: { + validate: (0, _index.assertNodeType)("Identifier") + } + } +}); + +(0, _index2.default)("RestProperty", { + visitor: ["argument"], + aliases: ["UnaryLike"], + fields: { + argument: { + validate: (0, _index.assertNodeType)("LVal") + } + } +}); + +(0, _index2.default)("SpreadProperty", { + visitor: ["argument"], + aliases: ["UnaryLike"], + fields: { + argument: { + validate: (0, _index.assertNodeType)("Expression") + } + } +}); +},{"./index":107}],106:[function(require,module,exports){ +"use strict"; + +var _index = require("./index"); + +var _index2 = _interopRequireDefault(_index); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +(0, _index2.default)("AnyTypeAnnotation", { + aliases: ["Flow", "FlowBaseAnnotation"], + fields: {} +}); + +(0, _index2.default)("ArrayTypeAnnotation", { + visitor: ["elementType"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("BooleanTypeAnnotation", { + aliases: ["Flow", "FlowBaseAnnotation"], + fields: {} +}); + +(0, _index2.default)("BooleanLiteralTypeAnnotation", { + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("NullLiteralTypeAnnotation", { + aliases: ["Flow", "FlowBaseAnnotation"], + fields: {} +}); + +(0, _index2.default)("ClassImplements", { + visitor: ["id", "typeParameters"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("ClassProperty", { + visitor: ["key", "value", "typeAnnotation", "decorators"], + builder: ["key", "value", "typeAnnotation", "decorators", "computed"], + aliases: ["Property"], + fields: { + computed: { + validate: (0, _index.assertValueType)("boolean"), + default: false + } + } +}); + +(0, _index2.default)("DeclareClass", { + visitor: ["id", "typeParameters", "extends", "body"], + aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"], + fields: {} +}); + +(0, _index2.default)("DeclareFunction", { + visitor: ["id"], + aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"], + fields: {} +}); + +(0, _index2.default)("DeclareInterface", { + visitor: ["id", "typeParameters", "extends", "body"], + aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"], + fields: {} +}); + +(0, _index2.default)("DeclareModule", { + visitor: ["id", "body"], + aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"], + fields: {} +}); + +(0, _index2.default)("DeclareModuleExports", { + visitor: ["typeAnnotation"], + aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"], + fields: {} +}); + +(0, _index2.default)("DeclareTypeAlias", { + visitor: ["id", "typeParameters", "right"], + aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"], + fields: {} +}); + +(0, _index2.default)("DeclareVariable", { + visitor: ["id"], + aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"], + fields: {} +}); + +(0, _index2.default)("ExistentialTypeParam", { + aliases: ["Flow"] +}); + +(0, _index2.default)("FunctionTypeAnnotation", { + visitor: ["typeParameters", "params", "rest", "returnType"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("FunctionTypeParam", { + visitor: ["name", "typeAnnotation"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("GenericTypeAnnotation", { + visitor: ["id", "typeParameters"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("InterfaceExtends", { + visitor: ["id", "typeParameters"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("InterfaceDeclaration", { + visitor: ["id", "typeParameters", "extends", "body"], + aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"], + fields: {} +}); + +(0, _index2.default)("IntersectionTypeAnnotation", { + visitor: ["types"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("MixedTypeAnnotation", { + aliases: ["Flow", "FlowBaseAnnotation"] +}); + +(0, _index2.default)("EmptyTypeAnnotation", { + aliases: ["Flow", "FlowBaseAnnotation"] +}); + +(0, _index2.default)("NullableTypeAnnotation", { + visitor: ["typeAnnotation"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("NumericLiteralTypeAnnotation", { + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("NumberTypeAnnotation", { + aliases: ["Flow", "FlowBaseAnnotation"], + fields: {} +}); + +(0, _index2.default)("StringLiteralTypeAnnotation", { + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("StringTypeAnnotation", { + aliases: ["Flow", "FlowBaseAnnotation"], + fields: {} +}); + +(0, _index2.default)("ThisTypeAnnotation", { + aliases: ["Flow", "FlowBaseAnnotation"], + fields: {} +}); + +(0, _index2.default)("TupleTypeAnnotation", { + visitor: ["types"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("TypeofTypeAnnotation", { + visitor: ["argument"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("TypeAlias", { + visitor: ["id", "typeParameters", "right"], + aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"], + fields: {} +}); + +(0, _index2.default)("TypeAnnotation", { + visitor: ["typeAnnotation"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("TypeCastExpression", { + visitor: ["expression", "typeAnnotation"], + aliases: ["Flow", "ExpressionWrapper", "Expression"], + fields: {} +}); + +(0, _index2.default)("TypeParameter", { + visitor: ["bound"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("TypeParameterDeclaration", { + visitor: ["params"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("TypeParameterInstantiation", { + visitor: ["params"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("ObjectTypeAnnotation", { + visitor: ["properties", "indexers", "callProperties"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("ObjectTypeCallProperty", { + visitor: ["value"], + aliases: ["Flow", "UserWhitespacable"], + fields: {} +}); + +(0, _index2.default)("ObjectTypeIndexer", { + visitor: ["id", "key", "value"], + aliases: ["Flow", "UserWhitespacable"], + fields: {} +}); + +(0, _index2.default)("ObjectTypeProperty", { + visitor: ["key", "value"], + aliases: ["Flow", "UserWhitespacable"], + fields: {} +}); + +(0, _index2.default)("QualifiedTypeIdentifier", { + visitor: ["id", "qualification"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("UnionTypeAnnotation", { + visitor: ["types"], + aliases: ["Flow"], + fields: {} +}); + +(0, _index2.default)("VoidTypeAnnotation", { + aliases: ["Flow", "FlowBaseAnnotation"], + fields: {} +}); +},{"./index":107}],107:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.DEPRECATED_KEYS = exports.BUILDER_KEYS = exports.NODE_FIELDS = exports.ALIAS_KEYS = exports.VISITOR_KEYS = undefined; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _stringify = require("babel-runtime/core-js/json/stringify"); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +exports.assertEach = assertEach; +exports.assertOneOf = assertOneOf; +exports.assertNodeType = assertNodeType; +exports.assertNodeOrValueType = assertNodeOrValueType; +exports.assertValueType = assertValueType; +exports.chain = chain; +exports.default = defineType; + +var _index = require("../index"); + +var t = _interopRequireWildcard(_index); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var VISITOR_KEYS = exports.VISITOR_KEYS = {}; +var ALIAS_KEYS = exports.ALIAS_KEYS = {}; +var NODE_FIELDS = exports.NODE_FIELDS = {}; +var BUILDER_KEYS = exports.BUILDER_KEYS = {}; +var DEPRECATED_KEYS = exports.DEPRECATED_KEYS = {}; + +function getType(val) { + if (Array.isArray(val)) { + return "array"; + } else if (val === null) { + return "null"; + } else if (val === undefined) { + return "undefined"; + } else { + return typeof val === "undefined" ? "undefined" : (0, _typeof3.default)(val); + } +} + +function assertEach(callback) { + function validator(node, key, val) { + if (!Array.isArray(val)) return; + + for (var i = 0; i < val.length; i++) { + callback(node, key + "[" + i + "]", val[i]); + } + } + validator.each = callback; + return validator; +} + +function assertOneOf() { + for (var _len = arguments.length, vals = Array(_len), _key = 0; _key < _len; _key++) { + vals[_key] = arguments[_key]; + } + + function validate(node, key, val) { + if (vals.indexOf(val) < 0) { + throw new TypeError("Property " + key + " expected value to be one of " + (0, _stringify2.default)(vals) + " but got " + (0, _stringify2.default)(val)); + } + } + + validate.oneOf = vals; + + return validate; +} + +function assertNodeType() { + for (var _len2 = arguments.length, types = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + types[_key2] = arguments[_key2]; + } + + function validate(node, key, val) { + var valid = false; + + for (var _iterator = types, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var type = _ref; + + if (t.is(type, val)) { + valid = true; + break; + } + } + + if (!valid) { + throw new TypeError("Property " + key + " of " + node.type + " expected node to be of a type " + (0, _stringify2.default)(types) + " " + ("but instead got " + (0, _stringify2.default)(val && val.type))); + } + } + + validate.oneOfNodeTypes = types; + + return validate; +} + +function assertNodeOrValueType() { + for (var _len3 = arguments.length, types = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + types[_key3] = arguments[_key3]; + } + + function validate(node, key, val) { + var valid = false; + + for (var _iterator2 = types, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var type = _ref2; + + if (getType(val) === type || t.is(type, val)) { + valid = true; + break; + } + } + + if (!valid) { + throw new TypeError("Property " + key + " of " + node.type + " expected node to be of a type " + (0, _stringify2.default)(types) + " " + ("but instead got " + (0, _stringify2.default)(val && val.type))); + } + } + + validate.oneOfNodeOrValueTypes = types; + + return validate; +} + +function assertValueType(type) { + function validate(node, key, val) { + var valid = getType(val) === type; + + if (!valid) { + throw new TypeError("Property " + key + " expected type of " + type + " but got " + getType(val)); + } + } + + validate.type = type; + + return validate; +} + +function chain() { + for (var _len4 = arguments.length, fns = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { + fns[_key4] = arguments[_key4]; + } + + function validate() { + for (var _iterator3 = fns, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var fn = _ref3; + + fn.apply(undefined, arguments); + } + } + validate.chainOf = fns; + return validate; +} + +function defineType(type) { + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var inherits = opts.inherits && store[opts.inherits] || {}; + + opts.fields = opts.fields || inherits.fields || {}; + opts.visitor = opts.visitor || inherits.visitor || []; + opts.aliases = opts.aliases || inherits.aliases || []; + opts.builder = opts.builder || inherits.builder || opts.visitor || []; + + if (opts.deprecatedAlias) { + DEPRECATED_KEYS[opts.deprecatedAlias] = type; + } + + for (var _iterator4 = opts.visitor.concat(opts.builder), _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : (0, _getIterator3.default)(_iterator4);;) { + var _ref4; + + if (_isArray4) { + if (_i4 >= _iterator4.length) break; + _ref4 = _iterator4[_i4++]; + } else { + _i4 = _iterator4.next(); + if (_i4.done) break; + _ref4 = _i4.value; + } + + var _key5 = _ref4; + + opts.fields[_key5] = opts.fields[_key5] || {}; + } + + for (var key in opts.fields) { + var field = opts.fields[key]; + + if (opts.builder.indexOf(key) === -1) { + field.optional = true; + } + if (field.default === undefined) { + field.default = null; + } else if (!field.validate) { + field.validate = assertValueType(getType(field.default)); + } + } + + VISITOR_KEYS[type] = opts.visitor; + BUILDER_KEYS[type] = opts.builder; + NODE_FIELDS[type] = opts.fields; + ALIAS_KEYS[type] = opts.aliases; + + store[type] = opts; +} + +var store = {}; +},{"../index":112,"babel-runtime/core-js/get-iterator":56,"babel-runtime/core-js/json/stringify":57,"babel-runtime/helpers/typeof":74}],108:[function(require,module,exports){ +"use strict"; + +require("./index"); + +require("./core"); + +require("./es2015"); + +require("./flow"); + +require("./jsx"); + +require("./misc"); + +require("./experimental"); +},{"./core":103,"./es2015":104,"./experimental":105,"./flow":106,"./index":107,"./jsx":109,"./misc":110}],109:[function(require,module,exports){ +"use strict"; + +var _index = require("./index"); + +var _index2 = _interopRequireDefault(_index); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +(0, _index2.default)("JSXAttribute", { + visitor: ["name", "value"], + aliases: ["JSX", "Immutable"], + fields: { + name: { + validate: (0, _index.assertNodeType)("JSXIdentifier", "JSXNamespacedName") + }, + value: { + optional: true, + validate: (0, _index.assertNodeType)("JSXElement", "StringLiteral", "JSXExpressionContainer") + } + } +}); + +(0, _index2.default)("JSXClosingElement", { + visitor: ["name"], + aliases: ["JSX", "Immutable"], + fields: { + name: { + validate: (0, _index.assertNodeType)("JSXIdentifier", "JSXMemberExpression") + } + } +}); + +(0, _index2.default)("JSXElement", { + builder: ["openingElement", "closingElement", "children", "selfClosing"], + visitor: ["openingElement", "children", "closingElement"], + aliases: ["JSX", "Immutable", "Expression"], + fields: { + openingElement: { + validate: (0, _index.assertNodeType)("JSXOpeningElement") + }, + closingElement: { + optional: true, + validate: (0, _index.assertNodeType)("JSXClosingElement") + }, + children: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("JSXText", "JSXExpressionContainer", "JSXSpreadChild", "JSXElement"))) + } + } +}); + +(0, _index2.default)("JSXEmptyExpression", { + aliases: ["JSX", "Expression"] +}); + +(0, _index2.default)("JSXExpressionContainer", { + visitor: ["expression"], + aliases: ["JSX", "Immutable"], + fields: { + expression: { + validate: (0, _index.assertNodeType)("Expression") + } + } +}); + +(0, _index2.default)("JSXSpreadChild", { + visitor: ["expression"], + aliases: ["JSX", "Immutable"], + fields: { + expression: { + validate: (0, _index.assertNodeType)("Expression") + } + } +}); + +(0, _index2.default)("JSXIdentifier", { + builder: ["name"], + aliases: ["JSX", "Expression"], + fields: { + name: { + validate: (0, _index.assertValueType)("string") + } + } +}); + +(0, _index2.default)("JSXMemberExpression", { + visitor: ["object", "property"], + aliases: ["JSX", "Expression"], + fields: { + object: { + validate: (0, _index.assertNodeType)("JSXMemberExpression", "JSXIdentifier") + }, + property: { + validate: (0, _index.assertNodeType)("JSXIdentifier") + } + } +}); + +(0, _index2.default)("JSXNamespacedName", { + visitor: ["namespace", "name"], + aliases: ["JSX"], + fields: { + namespace: { + validate: (0, _index.assertNodeType)("JSXIdentifier") + }, + name: { + validate: (0, _index.assertNodeType)("JSXIdentifier") + } + } +}); + +(0, _index2.default)("JSXOpeningElement", { + builder: ["name", "attributes", "selfClosing"], + visitor: ["name", "attributes"], + aliases: ["JSX", "Immutable"], + fields: { + name: { + validate: (0, _index.assertNodeType)("JSXIdentifier", "JSXMemberExpression") + }, + selfClosing: { + default: false, + validate: (0, _index.assertValueType)("boolean") + }, + attributes: { + validate: (0, _index.chain)((0, _index.assertValueType)("array"), (0, _index.assertEach)((0, _index.assertNodeType)("JSXAttribute", "JSXSpreadAttribute"))) + } + } +}); + +(0, _index2.default)("JSXSpreadAttribute", { + visitor: ["argument"], + aliases: ["JSX"], + fields: { + argument: { + validate: (0, _index.assertNodeType)("Expression") + } + } +}); + +(0, _index2.default)("JSXText", { + aliases: ["JSX", "Immutable"], + builder: ["value"], + fields: { + value: { + validate: (0, _index.assertValueType)("string") + } + } +}); +},{"./index":107}],110:[function(require,module,exports){ +"use strict"; + +var _index = require("./index"); + +var _index2 = _interopRequireDefault(_index); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +(0, _index2.default)("Noop", { + visitor: [] +}); + +(0, _index2.default)("ParenthesizedExpression", { + visitor: ["expression"], + aliases: ["Expression", "ExpressionWrapper"], + fields: { + expression: { + validate: (0, _index.assertNodeType)("Expression") + } + } +}); +},{"./index":107}],111:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.createUnionTypeAnnotation = createUnionTypeAnnotation; +exports.removeTypeDuplicates = removeTypeDuplicates; +exports.createTypeAnnotationBasedOnTypeof = createTypeAnnotationBasedOnTypeof; + +var _index = require("./index"); + +var t = _interopRequireWildcard(_index); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function createUnionTypeAnnotation(types) { + var flattened = removeTypeDuplicates(types); + + if (flattened.length === 1) { + return flattened[0]; + } else { + return t.unionTypeAnnotation(flattened); + } +} + +function removeTypeDuplicates(nodes) { + var generics = {}; + var bases = {}; + + var typeGroups = []; + + var types = []; + + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + if (!node) continue; + + if (types.indexOf(node) >= 0) { + continue; + } + + if (t.isAnyTypeAnnotation(node)) { + return [node]; + } + + if (t.isFlowBaseAnnotation(node)) { + bases[node.type] = node; + continue; + } + + if (t.isUnionTypeAnnotation(node)) { + if (typeGroups.indexOf(node.types) < 0) { + nodes = nodes.concat(node.types); + typeGroups.push(node.types); + } + continue; + } + + if (t.isGenericTypeAnnotation(node)) { + var name = node.id.name; + + if (generics[name]) { + var existing = generics[name]; + if (existing.typeParameters) { + if (node.typeParameters) { + existing.typeParameters.params = removeTypeDuplicates(existing.typeParameters.params.concat(node.typeParameters.params)); + } + } else { + existing = node.typeParameters; + } + } else { + generics[name] = node; + } + + continue; + } + + types.push(node); + } + + for (var type in bases) { + types.push(bases[type]); + } + + for (var _name in generics) { + types.push(generics[_name]); + } + + return types; +} + +function createTypeAnnotationBasedOnTypeof(type) { + if (type === "string") { + return t.stringTypeAnnotation(); + } else if (type === "number") { + return t.numberTypeAnnotation(); + } else if (type === "undefined") { + return t.voidTypeAnnotation(); + } else if (type === "boolean") { + return t.booleanTypeAnnotation(); + } else if (type === "function") { + return t.genericTypeAnnotation(t.identifier("Function")); + } else if (type === "object") { + return t.genericTypeAnnotation(t.identifier("Object")); + } else if (type === "symbol") { + return t.genericTypeAnnotation(t.identifier("Symbol")); + } else { + throw new Error("Invalid typeof value"); + } +} +},{"./index":112}],112:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.createTypeAnnotationBasedOnTypeof = exports.removeTypeDuplicates = exports.createUnionTypeAnnotation = exports.valueToNode = exports.toBlock = exports.toExpression = exports.toStatement = exports.toBindingIdentifierName = exports.toIdentifier = exports.toKeyAlias = exports.toSequenceExpression = exports.toComputedKey = exports.isNodesEquivalent = exports.isImmutable = exports.isScope = exports.isSpecifierDefault = exports.isVar = exports.isBlockScoped = exports.isLet = exports.isValidIdentifier = exports.isReferenced = exports.isBinding = exports.getOuterBindingIdentifiers = exports.getBindingIdentifiers = exports.TYPES = exports.react = exports.DEPRECATED_KEYS = exports.BUILDER_KEYS = exports.NODE_FIELDS = exports.ALIAS_KEYS = exports.VISITOR_KEYS = exports.NOT_LOCAL_BINDING = exports.BLOCK_SCOPED_SYMBOL = exports.INHERIT_KEYS = exports.UNARY_OPERATORS = exports.STRING_UNARY_OPERATORS = exports.NUMBER_UNARY_OPERATORS = exports.BOOLEAN_UNARY_OPERATORS = exports.BINARY_OPERATORS = exports.NUMBER_BINARY_OPERATORS = exports.BOOLEAN_BINARY_OPERATORS = exports.COMPARISON_BINARY_OPERATORS = exports.EQUALITY_BINARY_OPERATORS = exports.BOOLEAN_NUMBER_BINARY_OPERATORS = exports.UPDATE_OPERATORS = exports.LOGICAL_OPERATORS = exports.COMMENT_KEYS = exports.FOR_INIT_KEYS = exports.FLATTENABLE_KEYS = exports.STATEMENT_OR_BLOCK_KEYS = undefined; + +var _getOwnPropertySymbols = require("babel-runtime/core-js/object/get-own-property-symbols"); + +var _getOwnPropertySymbols2 = _interopRequireDefault(_getOwnPropertySymbols); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _keys = require("babel-runtime/core-js/object/keys"); + +var _keys2 = _interopRequireDefault(_keys); + +var _stringify = require("babel-runtime/core-js/json/stringify"); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _constants = require("./constants"); + +Object.defineProperty(exports, "STATEMENT_OR_BLOCK_KEYS", { + enumerable: true, + get: function get() { + return _constants.STATEMENT_OR_BLOCK_KEYS; + } +}); +Object.defineProperty(exports, "FLATTENABLE_KEYS", { + enumerable: true, + get: function get() { + return _constants.FLATTENABLE_KEYS; + } +}); +Object.defineProperty(exports, "FOR_INIT_KEYS", { + enumerable: true, + get: function get() { + return _constants.FOR_INIT_KEYS; + } +}); +Object.defineProperty(exports, "COMMENT_KEYS", { + enumerable: true, + get: function get() { + return _constants.COMMENT_KEYS; + } +}); +Object.defineProperty(exports, "LOGICAL_OPERATORS", { + enumerable: true, + get: function get() { + return _constants.LOGICAL_OPERATORS; + } +}); +Object.defineProperty(exports, "UPDATE_OPERATORS", { + enumerable: true, + get: function get() { + return _constants.UPDATE_OPERATORS; + } +}); +Object.defineProperty(exports, "BOOLEAN_NUMBER_BINARY_OPERATORS", { + enumerable: true, + get: function get() { + return _constants.BOOLEAN_NUMBER_BINARY_OPERATORS; + } +}); +Object.defineProperty(exports, "EQUALITY_BINARY_OPERATORS", { + enumerable: true, + get: function get() { + return _constants.EQUALITY_BINARY_OPERATORS; + } +}); +Object.defineProperty(exports, "COMPARISON_BINARY_OPERATORS", { + enumerable: true, + get: function get() { + return _constants.COMPARISON_BINARY_OPERATORS; + } +}); +Object.defineProperty(exports, "BOOLEAN_BINARY_OPERATORS", { + enumerable: true, + get: function get() { + return _constants.BOOLEAN_BINARY_OPERATORS; + } +}); +Object.defineProperty(exports, "NUMBER_BINARY_OPERATORS", { + enumerable: true, + get: function get() { + return _constants.NUMBER_BINARY_OPERATORS; + } +}); +Object.defineProperty(exports, "BINARY_OPERATORS", { + enumerable: true, + get: function get() { + return _constants.BINARY_OPERATORS; + } +}); +Object.defineProperty(exports, "BOOLEAN_UNARY_OPERATORS", { + enumerable: true, + get: function get() { + return _constants.BOOLEAN_UNARY_OPERATORS; + } +}); +Object.defineProperty(exports, "NUMBER_UNARY_OPERATORS", { + enumerable: true, + get: function get() { + return _constants.NUMBER_UNARY_OPERATORS; + } +}); +Object.defineProperty(exports, "STRING_UNARY_OPERATORS", { + enumerable: true, + get: function get() { + return _constants.STRING_UNARY_OPERATORS; + } +}); +Object.defineProperty(exports, "UNARY_OPERATORS", { + enumerable: true, + get: function get() { + return _constants.UNARY_OPERATORS; + } +}); +Object.defineProperty(exports, "INHERIT_KEYS", { + enumerable: true, + get: function get() { + return _constants.INHERIT_KEYS; + } +}); +Object.defineProperty(exports, "BLOCK_SCOPED_SYMBOL", { + enumerable: true, + get: function get() { + return _constants.BLOCK_SCOPED_SYMBOL; + } +}); +Object.defineProperty(exports, "NOT_LOCAL_BINDING", { + enumerable: true, + get: function get() { + return _constants.NOT_LOCAL_BINDING; + } +}); +exports.is = is; +exports.isType = isType; +exports.validate = validate; +exports.shallowEqual = shallowEqual; +exports.appendToMemberExpression = appendToMemberExpression; +exports.prependToMemberExpression = prependToMemberExpression; +exports.ensureBlock = ensureBlock; +exports.clone = clone; +exports.cloneWithoutLoc = cloneWithoutLoc; +exports.cloneDeep = cloneDeep; +exports.buildMatchMemberExpression = buildMatchMemberExpression; +exports.removeComments = removeComments; +exports.inheritsComments = inheritsComments; +exports.inheritTrailingComments = inheritTrailingComments; +exports.inheritLeadingComments = inheritLeadingComments; +exports.inheritInnerComments = inheritInnerComments; +exports.inherits = inherits; +exports.assertNode = assertNode; +exports.isNode = isNode; +exports.traverseFast = traverseFast; +exports.removeProperties = removeProperties; +exports.removePropertiesDeep = removePropertiesDeep; + +var _retrievers = require("./retrievers"); + +Object.defineProperty(exports, "getBindingIdentifiers", { + enumerable: true, + get: function get() { + return _retrievers.getBindingIdentifiers; + } +}); +Object.defineProperty(exports, "getOuterBindingIdentifiers", { + enumerable: true, + get: function get() { + return _retrievers.getOuterBindingIdentifiers; + } +}); + +var _validators = require("./validators"); + +Object.defineProperty(exports, "isBinding", { + enumerable: true, + get: function get() { + return _validators.isBinding; + } +}); +Object.defineProperty(exports, "isReferenced", { + enumerable: true, + get: function get() { + return _validators.isReferenced; + } +}); +Object.defineProperty(exports, "isValidIdentifier", { + enumerable: true, + get: function get() { + return _validators.isValidIdentifier; + } +}); +Object.defineProperty(exports, "isLet", { + enumerable: true, + get: function get() { + return _validators.isLet; + } +}); +Object.defineProperty(exports, "isBlockScoped", { + enumerable: true, + get: function get() { + return _validators.isBlockScoped; + } +}); +Object.defineProperty(exports, "isVar", { + enumerable: true, + get: function get() { + return _validators.isVar; + } +}); +Object.defineProperty(exports, "isSpecifierDefault", { + enumerable: true, + get: function get() { + return _validators.isSpecifierDefault; + } +}); +Object.defineProperty(exports, "isScope", { + enumerable: true, + get: function get() { + return _validators.isScope; + } +}); +Object.defineProperty(exports, "isImmutable", { + enumerable: true, + get: function get() { + return _validators.isImmutable; + } +}); +Object.defineProperty(exports, "isNodesEquivalent", { + enumerable: true, + get: function get() { + return _validators.isNodesEquivalent; + } +}); + +var _converters = require("./converters"); + +Object.defineProperty(exports, "toComputedKey", { + enumerable: true, + get: function get() { + return _converters.toComputedKey; + } +}); +Object.defineProperty(exports, "toSequenceExpression", { + enumerable: true, + get: function get() { + return _converters.toSequenceExpression; + } +}); +Object.defineProperty(exports, "toKeyAlias", { + enumerable: true, + get: function get() { + return _converters.toKeyAlias; + } +}); +Object.defineProperty(exports, "toIdentifier", { + enumerable: true, + get: function get() { + return _converters.toIdentifier; + } +}); +Object.defineProperty(exports, "toBindingIdentifierName", { + enumerable: true, + get: function get() { + return _converters.toBindingIdentifierName; + } +}); +Object.defineProperty(exports, "toStatement", { + enumerable: true, + get: function get() { + return _converters.toStatement; + } +}); +Object.defineProperty(exports, "toExpression", { + enumerable: true, + get: function get() { + return _converters.toExpression; + } +}); +Object.defineProperty(exports, "toBlock", { + enumerable: true, + get: function get() { + return _converters.toBlock; + } +}); +Object.defineProperty(exports, "valueToNode", { + enumerable: true, + get: function get() { + return _converters.valueToNode; + } +}); + +var _flow = require("./flow"); + +Object.defineProperty(exports, "createUnionTypeAnnotation", { + enumerable: true, + get: function get() { + return _flow.createUnionTypeAnnotation; + } +}); +Object.defineProperty(exports, "removeTypeDuplicates", { + enumerable: true, + get: function get() { + return _flow.removeTypeDuplicates; + } +}); +Object.defineProperty(exports, "createTypeAnnotationBasedOnTypeof", { + enumerable: true, + get: function get() { + return _flow.createTypeAnnotationBasedOnTypeof; + } +}); + +var _toFastProperties = require("to-fast-properties"); + +var _toFastProperties2 = _interopRequireDefault(_toFastProperties); + +var _clone = require("lodash/clone"); + +var _clone2 = _interopRequireDefault(_clone); + +var _uniq = require("lodash/uniq"); + +var _uniq2 = _interopRequireDefault(_uniq); + +require("./definitions/init"); + +var _definitions = require("./definitions"); + +var _react2 = require("./react"); + +var _react = _interopRequireWildcard(_react2); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var t = exports; + +function registerType(type) { + var is = t["is" + type]; + if (!is) { + is = t["is" + type] = function (node, opts) { + return t.is(type, node, opts); + }; + } + + t["assert" + type] = function (node, opts) { + opts = opts || {}; + if (!is(node, opts)) { + throw new Error("Expected type " + (0, _stringify2.default)(type) + " with option " + (0, _stringify2.default)(opts)); + } + }; +} + +exports.VISITOR_KEYS = _definitions.VISITOR_KEYS; +exports.ALIAS_KEYS = _definitions.ALIAS_KEYS; +exports.NODE_FIELDS = _definitions.NODE_FIELDS; +exports.BUILDER_KEYS = _definitions.BUILDER_KEYS; +exports.DEPRECATED_KEYS = _definitions.DEPRECATED_KEYS; +exports.react = _react; + + +for (var type in t.VISITOR_KEYS) { + registerType(type); +} + +t.FLIPPED_ALIAS_KEYS = {}; + +(0, _keys2.default)(t.ALIAS_KEYS).forEach(function (type) { + t.ALIAS_KEYS[type].forEach(function (alias) { + var types = t.FLIPPED_ALIAS_KEYS[alias] = t.FLIPPED_ALIAS_KEYS[alias] || []; + types.push(type); + }); +}); + +(0, _keys2.default)(t.FLIPPED_ALIAS_KEYS).forEach(function (type) { + t[type.toUpperCase() + "_TYPES"] = t.FLIPPED_ALIAS_KEYS[type]; + registerType(type); +}); + +var TYPES = exports.TYPES = (0, _keys2.default)(t.VISITOR_KEYS).concat((0, _keys2.default)(t.FLIPPED_ALIAS_KEYS)).concat((0, _keys2.default)(t.DEPRECATED_KEYS)); + +function is(type, node, opts) { + if (!node) return false; + + var matches = isType(node.type, type); + if (!matches) return false; + + if (typeof opts === "undefined") { + return true; + } else { + return t.shallowEqual(node, opts); + } +} + +function isType(nodeType, targetType) { + if (nodeType === targetType) return true; + + if (t.ALIAS_KEYS[targetType]) return false; + + var aliases = t.FLIPPED_ALIAS_KEYS[targetType]; + if (aliases) { + if (aliases[0] === nodeType) return true; + + for (var _iterator = aliases, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var alias = _ref; + + if (nodeType === alias) return true; + } + } + + return false; +} + +(0, _keys2.default)(t.BUILDER_KEYS).forEach(function (type) { + var keys = t.BUILDER_KEYS[type]; + + function builder() { + if (arguments.length > keys.length) { + throw new Error("t." + type + ": Too many arguments passed. Received " + arguments.length + " but can receive " + ("no more than " + keys.length)); + } + + var node = {}; + node.type = type; + + var i = 0; + + for (var _iterator2 = keys, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var _key = _ref2; + + var field = t.NODE_FIELDS[type][_key]; + + var arg = arguments[i++]; + if (arg === undefined) arg = (0, _clone2.default)(field.default); + + node[_key] = arg; + } + + for (var key in node) { + validate(node, key, node[key]); + } + + return node; + } + + t[type] = builder; + t[type[0].toLowerCase() + type.slice(1)] = builder; +}); + +var _loop = function _loop(_type) { + var newType = t.DEPRECATED_KEYS[_type]; + + function proxy(fn) { + return function () { + console.trace("The node type " + _type + " has been renamed to " + newType); + return fn.apply(this, arguments); + }; + } + + t[_type] = t[_type[0].toLowerCase() + _type.slice(1)] = proxy(t[newType]); + t["is" + _type] = proxy(t["is" + newType]); + t["assert" + _type] = proxy(t["assert" + newType]); +}; + +for (var _type in t.DEPRECATED_KEYS) { + _loop(_type); +} + +function validate(node, key, val) { + if (!node) return; + + var fields = t.NODE_FIELDS[node.type]; + if (!fields) return; + + var field = fields[key]; + if (!field || !field.validate) return; + if (field.optional && val == null) return; + + field.validate(node, key, val); +} + +function shallowEqual(actual, expected) { + var keys = (0, _keys2.default)(expected); + + for (var _iterator3 = keys, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var key = _ref3; + + if (actual[key] !== expected[key]) { + return false; + } + } + + return true; +} + +function appendToMemberExpression(member, append, computed) { + member.object = t.memberExpression(member.object, member.property, member.computed); + member.property = append; + member.computed = !!computed; + return member; +} + +function prependToMemberExpression(member, prepend) { + member.object = t.memberExpression(prepend, member.object); + return member; +} + +function ensureBlock(node) { + var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "body"; + + return node[key] = t.toBlock(node[key], node); +} + +function clone(node) { + if (!node) return node; + var newNode = {}; + for (var key in node) { + if (key[0] === "_") continue; + newNode[key] = node[key]; + } + return newNode; +} + +function cloneWithoutLoc(node) { + var newNode = clone(node); + delete newNode.loc; + return newNode; +} + +function cloneDeep(node) { + if (!node) return node; + var newNode = {}; + + for (var key in node) { + if (key[0] === "_") continue; + + var val = node[key]; + + if (val) { + if (val.type) { + val = t.cloneDeep(val); + } else if (Array.isArray(val)) { + val = val.map(t.cloneDeep); + } + } + + newNode[key] = val; + } + + return newNode; +} + +function buildMatchMemberExpression(match, allowPartial) { + var parts = match.split("."); + + return function (member) { + if (!t.isMemberExpression(member)) return false; + + var search = [member]; + var i = 0; + + while (search.length) { + var node = search.shift(); + + if (allowPartial && i === parts.length) { + return true; + } + + if (t.isIdentifier(node)) { + if (parts[i] !== node.name) return false; + } else if (t.isStringLiteral(node)) { + if (parts[i] !== node.value) return false; + } else if (t.isMemberExpression(node)) { + if (node.computed && !t.isStringLiteral(node.property)) { + return false; + } else { + search.push(node.object); + search.push(node.property); + continue; + } + } else { + return false; + } + + if (++i > parts.length) { + return false; + } + } + + return true; + }; +} + +function removeComments(node) { + for (var _iterator4 = t.COMMENT_KEYS, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : (0, _getIterator3.default)(_iterator4);;) { + var _ref4; + + if (_isArray4) { + if (_i4 >= _iterator4.length) break; + _ref4 = _iterator4[_i4++]; + } else { + _i4 = _iterator4.next(); + if (_i4.done) break; + _ref4 = _i4.value; + } + + var key = _ref4; + + delete node[key]; + } + return node; +} + +function inheritsComments(child, parent) { + inheritTrailingComments(child, parent); + inheritLeadingComments(child, parent); + inheritInnerComments(child, parent); + return child; +} + +function inheritTrailingComments(child, parent) { + _inheritComments("trailingComments", child, parent); +} + +function inheritLeadingComments(child, parent) { + _inheritComments("leadingComments", child, parent); +} + +function inheritInnerComments(child, parent) { + _inheritComments("innerComments", child, parent); +} + +function _inheritComments(key, child, parent) { + if (child && parent) { + child[key] = (0, _uniq2.default)([].concat(child[key], parent[key]).filter(Boolean)); + } +} + +function inherits(child, parent) { + if (!child || !parent) return child; + + for (var _iterator5 = t.INHERIT_KEYS.optional, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : (0, _getIterator3.default)(_iterator5);;) { + var _ref5; + + if (_isArray5) { + if (_i5 >= _iterator5.length) break; + _ref5 = _iterator5[_i5++]; + } else { + _i5 = _iterator5.next(); + if (_i5.done) break; + _ref5 = _i5.value; + } + + var _key2 = _ref5; + + if (child[_key2] == null) { + child[_key2] = parent[_key2]; + } + } + + for (var key in parent) { + if (key[0] === "_") child[key] = parent[key]; + } + + for (var _iterator6 = t.INHERIT_KEYS.force, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : (0, _getIterator3.default)(_iterator6);;) { + var _ref6; + + if (_isArray6) { + if (_i6 >= _iterator6.length) break; + _ref6 = _iterator6[_i6++]; + } else { + _i6 = _iterator6.next(); + if (_i6.done) break; + _ref6 = _i6.value; + } + + var _key3 = _ref6; + + child[_key3] = parent[_key3]; + } + + t.inheritsComments(child, parent); + + return child; +} + +function assertNode(node) { + if (!isNode(node)) { + throw new TypeError("Not a valid node " + (node && node.type)); + } +} + +function isNode(node) { + return !!(node && _definitions.VISITOR_KEYS[node.type]); +} + +(0, _toFastProperties2.default)(t); +(0, _toFastProperties2.default)(t.VISITOR_KEYS); + +function traverseFast(node, enter, opts) { + if (!node) return; + + var keys = t.VISITOR_KEYS[node.type]; + if (!keys) return; + + opts = opts || {}; + enter(node, opts); + + for (var _iterator7 = keys, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : (0, _getIterator3.default)(_iterator7);;) { + var _ref7; + + if (_isArray7) { + if (_i7 >= _iterator7.length) break; + _ref7 = _iterator7[_i7++]; + } else { + _i7 = _iterator7.next(); + if (_i7.done) break; + _ref7 = _i7.value; + } + + var key = _ref7; + + var subNode = node[key]; + + if (Array.isArray(subNode)) { + for (var _iterator8 = subNode, _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : (0, _getIterator3.default)(_iterator8);;) { + var _ref8; + + if (_isArray8) { + if (_i8 >= _iterator8.length) break; + _ref8 = _iterator8[_i8++]; + } else { + _i8 = _iterator8.next(); + if (_i8.done) break; + _ref8 = _i8.value; + } + + var _node = _ref8; + + traverseFast(_node, enter, opts); + } + } else { + traverseFast(subNode, enter, opts); + } + } +} + +var CLEAR_KEYS = ["tokens", "start", "end", "loc", "raw", "rawValue"]; + +var CLEAR_KEYS_PLUS_COMMENTS = t.COMMENT_KEYS.concat(["comments"]).concat(CLEAR_KEYS); + +function removeProperties(node, opts) { + opts = opts || {}; + var map = opts.preserveComments ? CLEAR_KEYS : CLEAR_KEYS_PLUS_COMMENTS; + for (var _iterator9 = map, _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : (0, _getIterator3.default)(_iterator9);;) { + var _ref9; + + if (_isArray9) { + if (_i9 >= _iterator9.length) break; + _ref9 = _iterator9[_i9++]; + } else { + _i9 = _iterator9.next(); + if (_i9.done) break; + _ref9 = _i9.value; + } + + var _key4 = _ref9; + + if (node[_key4] != null) node[_key4] = undefined; + } + + for (var key in node) { + if (key[0] === "_" && node[key] != null) node[key] = undefined; + } + + var syms = (0, _getOwnPropertySymbols2.default)(node); + for (var _iterator10 = syms, _isArray10 = Array.isArray(_iterator10), _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : (0, _getIterator3.default)(_iterator10);;) { + var _ref10; + + if (_isArray10) { + if (_i10 >= _iterator10.length) break; + _ref10 = _iterator10[_i10++]; + } else { + _i10 = _iterator10.next(); + if (_i10.done) break; + _ref10 = _i10.value; + } + + var sym = _ref10; + + node[sym] = null; + } +} + +function removePropertiesDeep(tree, opts) { + traverseFast(tree, removeProperties, opts); + return tree; +} +},{"./constants":101,"./converters":102,"./definitions":107,"./definitions/init":108,"./flow":111,"./react":113,"./retrievers":114,"./validators":115,"babel-runtime/core-js/get-iterator":56,"babel-runtime/core-js/json/stringify":57,"babel-runtime/core-js/object/get-own-property-symbols":62,"babel-runtime/core-js/object/keys":63,"lodash/clone":416,"lodash/uniq":464,"to-fast-properties":487}],113:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.isReactComponent = undefined; +exports.isCompatTag = isCompatTag; +exports.buildChildren = buildChildren; + +var _index = require("./index"); + +var t = _interopRequireWildcard(_index); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var isReactComponent = exports.isReactComponent = t.buildMatchMemberExpression("React.Component"); + +function isCompatTag(tagName) { + return !!tagName && /^[a-z]|\-/.test(tagName); +} + +function cleanJSXElementLiteralChild(child, args) { + var lines = child.value.split(/\r\n|\n|\r/); + + var lastNonEmptyLine = 0; + + for (var i = 0; i < lines.length; i++) { + if (lines[i].match(/[^ \t]/)) { + lastNonEmptyLine = i; + } + } + + var str = ""; + + for (var _i = 0; _i < lines.length; _i++) { + var line = lines[_i]; + + var isFirstLine = _i === 0; + var isLastLine = _i === lines.length - 1; + var isLastNonEmptyLine = _i === lastNonEmptyLine; + + var trimmedLine = line.replace(/\t/g, " "); + + if (!isFirstLine) { + trimmedLine = trimmedLine.replace(/^[ ]+/, ""); + } + + if (!isLastLine) { + trimmedLine = trimmedLine.replace(/[ ]+$/, ""); + } + + if (trimmedLine) { + if (!isLastNonEmptyLine) { + trimmedLine += " "; + } + + str += trimmedLine; + } + } + + if (str) args.push(t.stringLiteral(str)); +} + +function buildChildren(node) { + var elems = []; + + for (var i = 0; i < node.children.length; i++) { + var child = node.children[i]; + + if (t.isJSXText(child)) { + cleanJSXElementLiteralChild(child, elems); + continue; + } + + if (t.isJSXExpressionContainer(child)) child = child.expression; + if (t.isJSXEmptyExpression(child)) continue; + + elems.push(child); + } + + return elems; +} +},{"./index":112}],114:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _create = require("babel-runtime/core-js/object/create"); + +var _create2 = _interopRequireDefault(_create); + +exports.getBindingIdentifiers = getBindingIdentifiers; +exports.getOuterBindingIdentifiers = getOuterBindingIdentifiers; + +var _index = require("./index"); + +var t = _interopRequireWildcard(_index); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getBindingIdentifiers(node, duplicates, outerOnly) { + var search = [].concat(node); + var ids = (0, _create2.default)(null); + + while (search.length) { + var id = search.shift(); + if (!id) continue; + + var keys = t.getBindingIdentifiers.keys[id.type]; + + if (t.isIdentifier(id)) { + if (duplicates) { + var _ids = ids[id.name] = ids[id.name] || []; + _ids.push(id); + } else { + ids[id.name] = id; + } + continue; + } + + if (t.isExportDeclaration(id)) { + if (t.isDeclaration(id.declaration)) { + search.push(id.declaration); + } + continue; + } + + if (outerOnly) { + if (t.isFunctionDeclaration(id)) { + search.push(id.id); + continue; + } + + if (t.isFunctionExpression(id)) { + continue; + } + } + + if (keys) { + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (id[key]) { + search = search.concat(id[key]); + } + } + } + } + + return ids; +} + +getBindingIdentifiers.keys = { + DeclareClass: ["id"], + DeclareFunction: ["id"], + DeclareModule: ["id"], + DeclareVariable: ["id"], + InterfaceDeclaration: ["id"], + TypeAlias: ["id"], + + CatchClause: ["param"], + LabeledStatement: ["label"], + UnaryExpression: ["argument"], + AssignmentExpression: ["left"], + + ImportSpecifier: ["local"], + ImportNamespaceSpecifier: ["local"], + ImportDefaultSpecifier: ["local"], + ImportDeclaration: ["specifiers"], + + ExportSpecifier: ["exported"], + ExportNamespaceSpecifier: ["exported"], + ExportDefaultSpecifier: ["exported"], + + FunctionDeclaration: ["id", "params"], + FunctionExpression: ["id", "params"], + + ClassDeclaration: ["id"], + ClassExpression: ["id"], + + RestElement: ["argument"], + UpdateExpression: ["argument"], + + RestProperty: ["argument"], + ObjectProperty: ["value"], + + AssignmentPattern: ["left"], + ArrayPattern: ["elements"], + ObjectPattern: ["properties"], + + VariableDeclaration: ["declarations"], + VariableDeclarator: ["id"] +}; + +function getOuterBindingIdentifiers(node, duplicates) { + return getBindingIdentifiers(node, duplicates, true); +} +},{"./index":112,"babel-runtime/core-js/object/create":61}],115:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _keys = require("babel-runtime/core-js/object/keys"); + +var _keys2 = _interopRequireDefault(_keys); + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.isBinding = isBinding; +exports.isReferenced = isReferenced; +exports.isValidIdentifier = isValidIdentifier; +exports.isLet = isLet; +exports.isBlockScoped = isBlockScoped; +exports.isVar = isVar; +exports.isSpecifierDefault = isSpecifierDefault; +exports.isScope = isScope; +exports.isImmutable = isImmutable; +exports.isNodesEquivalent = isNodesEquivalent; + +var _retrievers = require("./retrievers"); + +var _esutils = require("esutils"); + +var _esutils2 = _interopRequireDefault(_esutils); + +var _index = require("./index"); + +var t = _interopRequireWildcard(_index); + +var _constants = require("./constants"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function isBinding(node, parent) { + var keys = _retrievers.getBindingIdentifiers.keys[parent.type]; + if (keys) { + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var val = parent[key]; + if (Array.isArray(val)) { + if (val.indexOf(node) >= 0) return true; + } else { + if (val === node) return true; + } + } + } + + return false; +} + +function isReferenced(node, parent) { + switch (parent.type) { + case "BindExpression": + return parent.object === node || parent.callee === node; + + case "MemberExpression": + case "JSXMemberExpression": + if (parent.property === node && parent.computed) { + return true; + } else if (parent.object === node) { + return true; + } else { + return false; + } + + case "MetaProperty": + return false; + + case "ObjectProperty": + if (parent.key === node) { + return parent.computed; + } + + case "VariableDeclarator": + return parent.id !== node; + + case "ArrowFunctionExpression": + case "FunctionDeclaration": + case "FunctionExpression": + for (var _iterator = parent.params, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var param = _ref; + + if (param === node) return false; + } + + return parent.id !== node; + + case "ExportSpecifier": + if (parent.source) { + return false; + } else { + return parent.local === node; + } + + case "ExportNamespaceSpecifier": + case "ExportDefaultSpecifier": + return false; + + case "JSXAttribute": + return parent.name !== node; + + case "ClassProperty": + if (parent.key === node) { + return parent.computed; + } else { + return parent.value === node; + } + + case "ImportDefaultSpecifier": + case "ImportNamespaceSpecifier": + case "ImportSpecifier": + return false; + + case "ClassDeclaration": + case "ClassExpression": + return parent.id !== node; + + case "ClassMethod": + case "ObjectMethod": + return parent.key === node && parent.computed; + + case "LabeledStatement": + return false; + + case "CatchClause": + return parent.param !== node; + + case "RestElement": + return false; + + case "AssignmentExpression": + return parent.right === node; + + case "AssignmentPattern": + return parent.right === node; + + case "ObjectPattern": + case "ArrayPattern": + return false; + } + + return true; +} + +function isValidIdentifier(name) { + if (typeof name !== "string" || _esutils2.default.keyword.isReservedWordES6(name, true)) { + return false; + } else { + return _esutils2.default.keyword.isIdentifierNameES6(name); + } +} + +function isLet(node) { + return t.isVariableDeclaration(node) && (node.kind !== "var" || node[_constants.BLOCK_SCOPED_SYMBOL]); +} + +function isBlockScoped(node) { + return t.isFunctionDeclaration(node) || t.isClassDeclaration(node) || t.isLet(node); +} + +function isVar(node) { + return t.isVariableDeclaration(node, { kind: "var" }) && !node[_constants.BLOCK_SCOPED_SYMBOL]; +} + +function isSpecifierDefault(specifier) { + return t.isImportDefaultSpecifier(specifier) || t.isIdentifier(specifier.imported || specifier.exported, { name: "default" }); +} + +function isScope(node, parent) { + if (t.isBlockStatement(node) && t.isFunction(parent, { body: node })) { + return false; + } + + return t.isScopable(node); +} + +function isImmutable(node) { + if (t.isType(node.type, "Immutable")) return true; + + if (t.isIdentifier(node)) { + if (node.name === "undefined") { + return true; + } else { + return false; + } + } + + return false; +} + +function isNodesEquivalent(a, b) { + if ((typeof a === "undefined" ? "undefined" : (0, _typeof3.default)(a)) !== "object" || (typeof a === "undefined" ? "undefined" : (0, _typeof3.default)(a)) !== "object" || a == null || b == null) { + return a === b; + } + + if (a.type !== b.type) { + return false; + } + + var fields = (0, _keys2.default)(t.NODE_FIELDS[a.type] || a.type); + + for (var _iterator2 = fields, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var field = _ref2; + + if ((0, _typeof3.default)(a[field]) !== (0, _typeof3.default)(b[field])) { + return false; + } + + if (Array.isArray(a[field])) { + if (!Array.isArray(b[field])) { + return false; + } + if (a[field].length !== b[field].length) { + return false; + } + + for (var i = 0; i < a[field].length; i++) { + if (!isNodesEquivalent(a[field][i], b[field][i])) { + return false; + } + } + continue; + } + + if (!isNodesEquivalent(a[field], b[field])) { + return false; + } + } + + return true; +} +},{"./constants":101,"./index":112,"./retrievers":114,"babel-runtime/core-js/get-iterator":56,"babel-runtime/core-js/object/keys":63,"babel-runtime/helpers/typeof":74,"esutils":240}],116:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +/* eslint max-len: 0 */ + +// 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(" "); + return function (str) { + return words.indexOf(str) >= 0; + }; +} + +// Reserved word lists for various dialects of the language + +var reservedWords = { + 6: makePredicate("enum await"), + strict: makePredicate("implements interface let package private protected public static yield"), + strictBind: makePredicate("eval arguments") +}; + +// And the keywords + +var isKeyword = makePredicate("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 let const class extends export import yield super"); + +// ## 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 `bin/generate-identifier-regex.js`. + +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-\u08B4\u08B6-\u08BD\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\u0AF9\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-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\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-\u13F5\u13F8-\u13FD\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\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\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\u2118-\u211D\u2124\u2126\u2128\u212A-\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\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\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-\uAB65\uAB70-\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 = "\u200C\u200D\xB7\u0300-\u036F\u0387\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\u08D4-\u08E1\u08E3-\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\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19D0-\u19DA\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\u1DFB-\u1DFF\u203F\u2040\u2054\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA620-\uA629\uA66F\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\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-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFF10-\uFF19\uFF3F"; + +var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); +var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); + +nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; + +// These are a run-length and offset encoded representation of the +// >0xffff code points that are a valid part of identifiers. The +// offset starts at 0x10000, and each pair of numbers represents an +// offset to the next range, and then a size of the range. They were +// generated by `bin/generate-identifier-regex.js`. +// eslint-disable-next-line comma-spacing +var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 17, 26, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 26, 45, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 785, 52, 76, 44, 33, 24, 27, 35, 42, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 54, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 86, 25, 391, 63, 32, 0, 449, 56, 264, 8, 2, 36, 18, 0, 50, 29, 881, 921, 103, 110, 18, 195, 2749, 1070, 4050, 582, 8634, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 881, 68, 12, 0, 67, 12, 65, 0, 32, 6124, 20, 754, 9486, 1, 3071, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 4149, 196, 60, 67, 1213, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42710, 42, 4148, 12, 221, 3, 5761, 10591, 541]; +// eslint-disable-next-line comma-spacing +var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 1306, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 52, 0, 13, 2, 49, 13, 10, 2, 4, 9, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 57, 0, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 87, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 423, 9, 838, 7, 2, 7, 17, 9, 57, 21, 2, 13, 19882, 9, 135, 4, 60, 6, 26, 9, 1016, 45, 17, 3, 19723, 1, 5319, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 2214, 6, 110, 6, 6, 9, 792487, 239]; + +// This has a complexity linear to the value of the code. The +// assumption is that looking up astral identifier characters is +// rare. +function isInAstralSet(code, set) { + var pos = 0x10000; + for (var i = 0; i < set.length; i += 2) { + pos += set[i]; + if (pos > code) return false; + + pos += set[i + 1]; + if (pos >= code) return true; + } +} + +// Test whether a given character code starts an identifier. + +function isIdentifierStart(code) { + if (code < 65) return code === 36; + if (code < 91) return true; + if (code < 97) return code === 95; + if (code < 123) return true; + if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); + return isInAstralSet(code, astralIdentifierStartCodes); +} + +// Test whether a given character is part of an identifier. + +function isIdentifierChar(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; + if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); + return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes); +} + +// A second optional argument can be given to further configure +var defaultOptions = { + // Source type ("script" or "module") for different semantics + sourceType: "script", + // Source filename. + sourceFilename: undefined, + // Line from which to start counting source. Useful for + // integration with other tools. + startLine: 1, + // 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, + // TODO + allowSuperOutsideMethod: false, + // An array of plugins to enable + plugins: [], + // TODO + strictMode: null +}; + +// Interpret and default an options object + +function getOptions(opts) { + var options = {}; + for (var key in defaultOptions) { + options[key] = opts && key in opts ? opts[key] : defaultOptions[key]; + } + return options; +} + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; +} : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; +}; + + + + + + + + + + + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; + + + + + + + + + + + +var inherits = function (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 possibleConstructorReturn = function (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; +}; + +// ## 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. + +// 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 beforeExpr = true; +var startsExpr = true; +var isLoop = true; +var isAssign = true; +var prefix = true; +var postfix = true; + +var TokenType = function TokenType(label) { + var conf = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + classCallCheck(this, TokenType); + + this.label = label; + this.keyword = conf.keyword; + this.beforeExpr = !!conf.beforeExpr; + this.startsExpr = !!conf.startsExpr; + this.rightAssociative = !!conf.rightAssociative; + this.isLoop = !!conf.isLoop; + this.isAssign = !!conf.isAssign; + this.prefix = !!conf.prefix; + this.postfix = !!conf.postfix; + this.binop = conf.binop || null; + this.updateContext = null; +}; + +var KeywordTokenType = function (_TokenType) { + inherits(KeywordTokenType, _TokenType); + + function KeywordTokenType(name) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + classCallCheck(this, KeywordTokenType); + + options.keyword = name; + + return possibleConstructorReturn(this, _TokenType.call(this, name, options)); + } + + return KeywordTokenType; +}(TokenType); + +var BinopTokenType = function (_TokenType2) { + inherits(BinopTokenType, _TokenType2); + + function BinopTokenType(name, prec) { + classCallCheck(this, BinopTokenType); + return possibleConstructorReturn(this, _TokenType2.call(this, name, { beforeExpr: beforeExpr, binop: prec })); + } + + return BinopTokenType; +}(TokenType); + +var types = { + num: new TokenType("num", { startsExpr: startsExpr }), + regexp: new TokenType("regexp", { startsExpr: startsExpr }), + string: new TokenType("string", { startsExpr: startsExpr }), + name: new TokenType("name", { startsExpr: startsExpr }), + eof: new TokenType("eof"), + + // Punctuation token types. + bracketL: new TokenType("[", { beforeExpr: beforeExpr, startsExpr: startsExpr }), + bracketR: new TokenType("]"), + braceL: new TokenType("{", { beforeExpr: beforeExpr, startsExpr: startsExpr }), + braceBarL: new TokenType("{|", { beforeExpr: beforeExpr, startsExpr: startsExpr }), + braceR: new TokenType("}"), + braceBarR: new TokenType("|}"), + parenL: new TokenType("(", { beforeExpr: beforeExpr, startsExpr: startsExpr }), + parenR: new TokenType(")"), + comma: new TokenType(",", { beforeExpr: beforeExpr }), + semi: new TokenType(";", { beforeExpr: beforeExpr }), + colon: new TokenType(":", { beforeExpr: beforeExpr }), + doubleColon: new TokenType("::", { beforeExpr: beforeExpr }), + dot: new TokenType("."), + question: new TokenType("?", { beforeExpr: beforeExpr }), + arrow: new TokenType("=>", { beforeExpr: beforeExpr }), + template: new TokenType("template"), + ellipsis: new TokenType("...", { beforeExpr: beforeExpr }), + backQuote: new TokenType("`", { startsExpr: startsExpr }), + dollarBraceL: new TokenType("${", { beforeExpr: beforeExpr, startsExpr: startsExpr }), + at: new TokenType("@"), + + // 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. + // + // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as + // binary operators with a very low precedence, that should result + // in AssignmentExpression nodes. + + eq: new TokenType("=", { beforeExpr: beforeExpr, isAssign: isAssign }), + assign: new TokenType("_=", { beforeExpr: beforeExpr, isAssign: isAssign }), + incDec: new TokenType("++/--", { prefix: prefix, postfix: postfix, startsExpr: startsExpr }), + prefix: new TokenType("prefix", { beforeExpr: beforeExpr, prefix: prefix, startsExpr: startsExpr }), + logicalOR: new BinopTokenType("||", 1), + logicalAND: new BinopTokenType("&&", 2), + bitwiseOR: new BinopTokenType("|", 3), + bitwiseXOR: new BinopTokenType("^", 4), + bitwiseAND: new BinopTokenType("&", 5), + equality: new BinopTokenType("==/!=", 6), + relational: new BinopTokenType("", 7), + bitShift: new BinopTokenType("<>", 8), + plusMin: new TokenType("+/-", { beforeExpr: beforeExpr, binop: 9, prefix: prefix, startsExpr: startsExpr }), + modulo: new BinopTokenType("%", 10), + star: new BinopTokenType("*", 10), + slash: new BinopTokenType("/", 10), + exponent: new TokenType("**", { beforeExpr: beforeExpr, binop: 11, rightAssociative: true }) +}; + +var keywords = { + "break": new KeywordTokenType("break"), + "case": new KeywordTokenType("case", { beforeExpr: beforeExpr }), + "catch": new KeywordTokenType("catch"), + "continue": new KeywordTokenType("continue"), + "debugger": new KeywordTokenType("debugger"), + "default": new KeywordTokenType("default", { beforeExpr: beforeExpr }), + "do": new KeywordTokenType("do", { isLoop: isLoop, beforeExpr: beforeExpr }), + "else": new KeywordTokenType("else", { beforeExpr: beforeExpr }), + "finally": new KeywordTokenType("finally"), + "for": new KeywordTokenType("for", { isLoop: isLoop }), + "function": new KeywordTokenType("function", { startsExpr: startsExpr }), + "if": new KeywordTokenType("if"), + "return": new KeywordTokenType("return", { beforeExpr: beforeExpr }), + "switch": new KeywordTokenType("switch"), + "throw": new KeywordTokenType("throw", { beforeExpr: beforeExpr }), + "try": new KeywordTokenType("try"), + "var": new KeywordTokenType("var"), + "let": new KeywordTokenType("let"), + "const": new KeywordTokenType("const"), + "while": new KeywordTokenType("while", { isLoop: isLoop }), + "with": new KeywordTokenType("with"), + "new": new KeywordTokenType("new", { beforeExpr: beforeExpr, startsExpr: startsExpr }), + "this": new KeywordTokenType("this", { startsExpr: startsExpr }), + "super": new KeywordTokenType("super", { startsExpr: startsExpr }), + "class": new KeywordTokenType("class"), + "extends": new KeywordTokenType("extends", { beforeExpr: beforeExpr }), + "export": new KeywordTokenType("export"), + "import": new KeywordTokenType("import"), + "yield": new KeywordTokenType("yield", { beforeExpr: beforeExpr, startsExpr: startsExpr }), + "null": new KeywordTokenType("null", { startsExpr: startsExpr }), + "true": new KeywordTokenType("true", { startsExpr: startsExpr }), + "false": new KeywordTokenType("false", { startsExpr: startsExpr }), + "in": new KeywordTokenType("in", { beforeExpr: beforeExpr, binop: 7 }), + "instanceof": new KeywordTokenType("instanceof", { beforeExpr: beforeExpr, binop: 7 }), + "typeof": new KeywordTokenType("typeof", { beforeExpr: beforeExpr, prefix: prefix, startsExpr: startsExpr }), + "void": new KeywordTokenType("void", { beforeExpr: beforeExpr, prefix: prefix, startsExpr: startsExpr }), + "delete": new KeywordTokenType("delete", { beforeExpr: beforeExpr, prefix: prefix, startsExpr: startsExpr }) +}; + +// Map keyword names to token types. +Object.keys(keywords).forEach(function (name) { + types["_" + name] = keywords[name]; +}); + +// Matches a whole line break (where CRLF is considered a single +// line break). Used to count lines. + +var lineBreak = /\r\n?|\n|\u2028|\u2029/; +var lineBreakG = new RegExp(lineBreak.source, "g"); + +function isNewLine(code) { + return code === 10 || code === 13 || code === 0x2028 || code === 0x2029; +} + +var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; + +// The algorithm used to determine whether a regexp can appear at a +// given point in the program is loosely based on sweet.js' approach. +// See https://github.com/mozilla/sweet.js/wiki/design + +var TokContext = function TokContext(token, isExpr, preserveSpace, override) { + classCallCheck(this, TokContext); + + this.token = token; + this.isExpr = !!isExpr; + this.preserveSpace = !!preserveSpace; + this.override = override; +}; + +var types$1 = { + braceStatement: new TokContext("{", false), + braceExpression: new TokContext("{", true), + templateQuasi: new TokContext("${", true), + parenStatement: new TokContext("(", false), + parenExpression: new TokContext("(", true), + template: new TokContext("`", true, true, function (p) { + return p.readTmplToken(); + }), + functionExpression: new TokContext("function", true) +}; + +// Token-specific context update code + +types.parenR.updateContext = types.braceR.updateContext = function () { + if (this.state.context.length === 1) { + this.state.exprAllowed = true; + return; + } + + var out = this.state.context.pop(); + if (out === types$1.braceStatement && this.curContext() === types$1.functionExpression) { + this.state.context.pop(); + this.state.exprAllowed = false; + } else if (out === types$1.templateQuasi) { + this.state.exprAllowed = true; + } else { + this.state.exprAllowed = !out.isExpr; + } +}; + +types.name.updateContext = function (prevType) { + this.state.exprAllowed = false; + + if (prevType === types._let || prevType === types._const || prevType === types._var) { + if (lineBreak.test(this.input.slice(this.state.end))) { + this.state.exprAllowed = true; + } + } +}; + +types.braceL.updateContext = function (prevType) { + this.state.context.push(this.braceIsBlock(prevType) ? types$1.braceStatement : types$1.braceExpression); + this.state.exprAllowed = true; +}; + +types.dollarBraceL.updateContext = function () { + this.state.context.push(types$1.templateQuasi); + this.state.exprAllowed = true; +}; + +types.parenL.updateContext = function (prevType) { + var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; + this.state.context.push(statementParens ? types$1.parenStatement : types$1.parenExpression); + this.state.exprAllowed = true; +}; + +types.incDec.updateContext = function () { + // tokExprAllowed stays unchanged +}; + +types._function.updateContext = function () { + if (this.curContext() !== types$1.braceStatement) { + this.state.context.push(types$1.functionExpression); + } + + this.state.exprAllowed = false; +}; + +types.backQuote.updateContext = function () { + if (this.curContext() === types$1.template) { + this.state.context.pop(); + } else { + this.state.context.push(types$1.template); + } + this.state.exprAllowed = false; +}; + +// These are used when `options.locations` is on, for the +// `startLoc` and `endLoc` properties. + +var Position = function Position(line, col) { + classCallCheck(this, Position); + + this.line = line; + this.column = col; +}; + +var SourceLocation = function SourceLocation(start, end) { + classCallCheck(this, SourceLocation); + + this.start = start; + this.end = end; +}; + +// 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. + +function getLineInfo(input, offset) { + for (var line = 1, cur = 0;;) { + lineBreakG.lastIndex = cur; + var match = lineBreakG.exec(input); + if (match && match.index < offset) { + ++line; + cur = match.index + match[0].length; + } else { + return new Position(line, offset - cur); + } + } +} + +var State = function () { + function State() { + classCallCheck(this, State); + } + + State.prototype.init = function init(options, input) { + this.strict = options.strictMode === false ? false : options.sourceType === "module"; + + this.input = input; + + this.potentialArrowAt = -1; + + this.inMethod = this.inFunction = this.inGenerator = this.inAsync = this.inPropertyName = this.inType = this.noAnonFunctionType = false; + + this.labels = []; + + this.decorators = []; + + this.tokens = []; + + this.comments = []; + + this.trailingComments = []; + this.leadingComments = []; + this.commentStack = []; + + this.pos = this.lineStart = 0; + this.curLine = options.startLine; + + this.type = types.eof; + this.value = null; + this.start = this.end = this.pos; + this.startLoc = this.endLoc = this.curPosition(); + + this.lastTokEndLoc = this.lastTokStartLoc = null; + this.lastTokStart = this.lastTokEnd = this.pos; + + this.context = [types$1.braceStatement]; + this.exprAllowed = true; + + this.containsEsc = this.containsOctal = false; + this.octalPosition = null; + + this.exportedIdentifiers = []; + + return this; + }; + + // TODO + + + // TODO + + + // Used to signify the start of a potential arrow function + + + // Flags to track whether we are in a function, a generator. + + + // Labels in scope. + + + // Leading decorators. + + + // Token store. + + + // Comment store. + + + // Comment attachment store + + + // The current position of the tokenizer in the input. + + + // Properties of the current token: + // Its type + + + // For tokens that include more information than their type, the value + + + // Its start and end offset + + + // And, if locations are used, the {line, column} object + // corresponding to those offsets + + + // Position information for the previous token + + + // The context stack is used to superficially track syntactic + // context to predict whether a regular expression is allowed in a + // given position. + + + // 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. + + + // TODO + + + // Names of exports store. `default` is stored as a name for both + // `export default foo;` and `export { foo as default };`. + + + State.prototype.curPosition = function curPosition() { + return new Position(this.curLine, this.pos - this.lineStart); + }; + + State.prototype.clone = function clone(skipArrays) { + var state = new State(); + for (var key in this) { + var val = this[key]; + + if ((!skipArrays || key === "context") && Array.isArray(val)) { + val = val.slice(); + } + + state[key] = val; + } + return state; + }; + + return State; +}(); + +// Object type used to represent tokens. Note that normally, tokens +// simply exist as properties on the parser object. This is only +// used for the onToken callback and the external tokenizer. + +var Token = function Token(state) { + classCallCheck(this, Token); + + this.type = state.type; + this.value = state.value; + this.start = state.start; + this.end = state.end; + this.loc = new SourceLocation(state.startLoc, state.endLoc); +}; + +// ## Tokenizer + +function codePointToString(code) { + // UTF-16 Decoding + if (code <= 0xFFFF) { + return String.fromCharCode(code); + } else { + return String.fromCharCode((code - 0x10000 >> 10) + 0xD800, (code - 0x10000 & 1023) + 0xDC00); + } +} + +var Tokenizer = function () { + function Tokenizer(options, input) { + classCallCheck(this, Tokenizer); + + this.state = new State(); + this.state.init(options, input); + } + + // Move to the next token + + Tokenizer.prototype.next = function next() { + if (!this.isLookahead) { + this.state.tokens.push(new Token(this.state)); + } + + this.state.lastTokEnd = this.state.end; + this.state.lastTokStart = this.state.start; + this.state.lastTokEndLoc = this.state.endLoc; + this.state.lastTokStartLoc = this.state.startLoc; + this.nextToken(); + }; + + // TODO + + Tokenizer.prototype.eat = function eat(type) { + if (this.match(type)) { + this.next(); + return true; + } else { + return false; + } + }; + + // TODO + + Tokenizer.prototype.match = function match(type) { + return this.state.type === type; + }; + + // TODO + + Tokenizer.prototype.isKeyword = function isKeyword$$1(word) { + return isKeyword(word); + }; + + // TODO + + Tokenizer.prototype.lookahead = function lookahead() { + var old = this.state; + this.state = old.clone(true); + + this.isLookahead = true; + this.next(); + this.isLookahead = false; + + var curr = this.state.clone(true); + this.state = old; + return curr; + }; + + // Toggle strict mode. Re-reads the next number or string to please + // pedantic tests (`"use strict"; 010;` should fail). + + Tokenizer.prototype.setStrict = function setStrict(strict) { + this.state.strict = strict; + if (!this.match(types.num) && !this.match(types.string)) return; + this.state.pos = this.state.start; + while (this.state.pos < this.state.lineStart) { + this.state.lineStart = this.input.lastIndexOf("\n", this.state.lineStart - 2) + 1; + --this.state.curLine; + } + this.nextToken(); + }; + + Tokenizer.prototype.curContext = function curContext() { + return this.state.context[this.state.context.length - 1]; + }; + + // Read a single token, updating the parser object's token-related + // properties. + + Tokenizer.prototype.nextToken = function nextToken() { + var curContext = this.curContext(); + if (!curContext || !curContext.preserveSpace) this.skipSpace(); + + this.state.containsOctal = false; + this.state.octalPosition = null; + this.state.start = this.state.pos; + this.state.startLoc = this.state.curPosition(); + if (this.state.pos >= this.input.length) return this.finishToken(types.eof); + + if (curContext.override) { + return curContext.override(this); + } else { + return this.readToken(this.fullCharCodeAtPos()); + } + }; + + Tokenizer.prototype.readToken = function readToken(code) { + // Identifier or keyword. '\uXXXX' sequences are allowed in + // identifiers, so '\' also dispatches to that. + if (isIdentifierStart(code) || code === 92 /* '\' */) { + return this.readWord(); + } else { + return this.getTokenFromCode(code); + } + }; + + Tokenizer.prototype.fullCharCodeAtPos = function fullCharCodeAtPos() { + var code = this.input.charCodeAt(this.state.pos); + if (code <= 0xd7ff || code >= 0xe000) return code; + + var next = this.input.charCodeAt(this.state.pos + 1); + return (code << 10) + next - 0x35fdc00; + }; + + Tokenizer.prototype.pushComment = function pushComment(block, text, start, end, startLoc, endLoc) { + var comment = { + type: block ? "CommentBlock" : "CommentLine", + value: text, + start: start, + end: end, + loc: new SourceLocation(startLoc, endLoc) + }; + + if (!this.isLookahead) { + this.state.tokens.push(comment); + this.state.comments.push(comment); + this.addComment(comment); + } + }; + + Tokenizer.prototype.skipBlockComment = function skipBlockComment() { + var startLoc = this.state.curPosition(); + var start = this.state.pos; + var end = this.input.indexOf("*/", this.state.pos += 2); + if (end === -1) this.raise(this.state.pos - 2, "Unterminated comment"); + + this.state.pos = end + 2; + lineBreakG.lastIndex = start; + var match = void 0; + while ((match = lineBreakG.exec(this.input)) && match.index < this.state.pos) { + ++this.state.curLine; + this.state.lineStart = match.index + match[0].length; + } + + this.pushComment(true, this.input.slice(start + 2, end), start, this.state.pos, startLoc, this.state.curPosition()); + }; + + Tokenizer.prototype.skipLineComment = function skipLineComment(startSkip) { + var start = this.state.pos; + var startLoc = this.state.curPosition(); + var ch = this.input.charCodeAt(this.state.pos += startSkip); + while (this.state.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { + ++this.state.pos; + ch = this.input.charCodeAt(this.state.pos); + } + + this.pushComment(false, this.input.slice(start + startSkip, this.state.pos), start, this.state.pos, startLoc, this.state.curPosition()); + }; + + // Called at the start of the parse and after every token. Skips + // whitespace and comments, and. + + Tokenizer.prototype.skipSpace = function skipSpace() { + loop: while (this.state.pos < this.input.length) { + var ch = this.input.charCodeAt(this.state.pos); + switch (ch) { + case 32:case 160: + // ' ' + ++this.state.pos; + break; + + case 13: + if (this.input.charCodeAt(this.state.pos + 1) === 10) { + ++this.state.pos; + } + + case 10:case 8232:case 8233: + ++this.state.pos; + ++this.state.curLine; + this.state.lineStart = this.state.pos; + break; + + case 47: + // '/' + switch (this.input.charCodeAt(this.state.pos + 1)) { + case 42: + // '*' + this.skipBlockComment(); + break; + + case 47: + this.skipLineComment(2); + break; + + default: + break loop; + } + break; + + default: + if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { + ++this.state.pos; + } else { + break loop; + } + } + } + }; + + // Called at the end of every token. Sets `end`, `val`, and + // maintains `context` and `exprAllowed`, and skips the space after + // the token, so that the next one's `start` will point at the + // right position. + + Tokenizer.prototype.finishToken = function finishToken(type, val) { + this.state.end = this.state.pos; + this.state.endLoc = this.state.curPosition(); + var prevType = this.state.type; + this.state.type = type; + this.state.value = val; + + this.updateContext(prevType); + }; + + // ### 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. + // + + + Tokenizer.prototype.readToken_dot = function readToken_dot() { + var next = this.input.charCodeAt(this.state.pos + 1); + if (next >= 48 && next <= 57) { + return this.readNumber(true); + } + + var next2 = this.input.charCodeAt(this.state.pos + 2); + if (next === 46 && next2 === 46) { + // 46 = dot '.' + this.state.pos += 3; + return this.finishToken(types.ellipsis); + } else { + ++this.state.pos; + return this.finishToken(types.dot); + } + }; + + Tokenizer.prototype.readToken_slash = function readToken_slash() { + // '/' + if (this.state.exprAllowed) { + ++this.state.pos; + return this.readRegexp(); + } + + var next = this.input.charCodeAt(this.state.pos + 1); + if (next === 61) { + return this.finishOp(types.assign, 2); + } else { + return this.finishOp(types.slash, 1); + } + }; + + Tokenizer.prototype.readToken_mult_modulo = function readToken_mult_modulo(code) { + // '%*' + var type = code === 42 ? types.star : types.modulo; + var width = 1; + var next = this.input.charCodeAt(this.state.pos + 1); + + if (next === 42) { + // '*' + width++; + next = this.input.charCodeAt(this.state.pos + 2); + type = types.exponent; + } + + if (next === 61) { + width++; + type = types.assign; + } + + return this.finishOp(type, width); + }; + + Tokenizer.prototype.readToken_pipe_amp = function readToken_pipe_amp(code) { + // '|&' + var next = this.input.charCodeAt(this.state.pos + 1); + if (next === code) return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2); + if (next === 61) return this.finishOp(types.assign, 2); + if (code === 124 && next === 125 && this.hasPlugin("flow")) return this.finishOp(types.braceBarR, 2); + return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1); + }; + + Tokenizer.prototype.readToken_caret = function readToken_caret() { + // '^' + var next = this.input.charCodeAt(this.state.pos + 1); + if (next === 61) { + return this.finishOp(types.assign, 2); + } else { + return this.finishOp(types.bitwiseXOR, 1); + } + }; + + Tokenizer.prototype.readToken_plus_min = function readToken_plus_min(code) { + // '+-' + var next = this.input.charCodeAt(this.state.pos + 1); + + if (next === code) { + if (next === 45 && this.input.charCodeAt(this.state.pos + 2) === 62 && lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.pos))) { + // A `-->` line comment + this.skipLineComment(3); + this.skipSpace(); + return this.nextToken(); + } + return this.finishOp(types.incDec, 2); + } + + if (next === 61) { + return this.finishOp(types.assign, 2); + } else { + return this.finishOp(types.plusMin, 1); + } + }; + + Tokenizer.prototype.readToken_lt_gt = function readToken_lt_gt(code) { + // '<>' + var next = this.input.charCodeAt(this.state.pos + 1); + var size = 1; + + if (next === code) { + size = code === 62 && this.input.charCodeAt(this.state.pos + 2) === 62 ? 3 : 2; + if (this.input.charCodeAt(this.state.pos + size) === 61) return this.finishOp(types.assign, size + 1); + return this.finishOp(types.bitShift, size); + } + + if (next === 33 && code === 60 && this.input.charCodeAt(this.state.pos + 2) === 45 && this.input.charCodeAt(this.state.pos + 3) === 45) { + if (this.inModule) this.unexpected(); + // ` regexps + set = set.map(function (s, si, set) { + return s.map(this.parse, this) + }, this) + + this.debug(this.pattern, set) + + // filter out everything that didn't compile properly. + set = set.filter(function (s) { + return s.indexOf(false) === -1 + }) + + this.debug(this.pattern, set) + + this.set = set +} + +Minimatch.prototype.parseNegate = parseNegate +function parseNegate () { + var pattern = this.pattern + var negate = false + var options = this.options + var negateOffset = 0 + + if (options.nonegate) return + + for (var i = 0, l = pattern.length + ; i < l && pattern.charAt(i) === '!' + ; i++) { + negate = !negate + negateOffset++ + } + + if (negateOffset) this.pattern = pattern.substr(negateOffset) + this.negate = negate +} + +// Brace expansion: +// a{b,c}d -> abd acd +// a{b,}c -> abc ac +// a{0..3}d -> a0d a1d a2d a3d +// a{b,c{d,e}f}g -> abg acdfg acefg +// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg +// +// Invalid sets are not expanded. +// a{2..}b -> a{2..}b +// a{b}c -> a{b}c +minimatch.braceExpand = function (pattern, options) { + return braceExpand(pattern, options) +} + +Minimatch.prototype.braceExpand = braceExpand + +function braceExpand (pattern, options) { + if (!options) { + if (this instanceof Minimatch) { + options = this.options + } else { + options = {} + } + } + + pattern = typeof pattern === 'undefined' + ? this.pattern : pattern + + if (typeof pattern === 'undefined') { + throw new TypeError('undefined pattern') + } + + if (options.nobrace || + !pattern.match(/\{.*\}/)) { + // shortcut. no need to expand. + return [pattern] + } + + return expand(pattern) +} + +// parse a component of the expanded set. +// At this point, no pattern may contain "/" in it +// so we're going to return a 2d array, where each entry is the full +// pattern, split on '/', and then turned into a regular expression. +// A regexp is made at the end which joins each array with an +// escaped /, and another full one which joins each regexp with |. +// +// Following the lead of Bash 4.1, note that "**" only has special meaning +// when it is the *only* thing in a path portion. Otherwise, any series +// of * is equivalent to a single *. Globstar behavior is enabled by +// default, and can be disabled by setting options.noglobstar. +Minimatch.prototype.parse = parse +var SUBPARSE = {} +function parse (pattern, isSub) { + if (pattern.length > 1024 * 64) { + throw new TypeError('pattern is too long') + } + + var options = this.options + + // shortcuts + if (!options.noglobstar && pattern === '**') return GLOBSTAR + if (pattern === '') return '' + + var re = '' + var hasMagic = !!options.nocase + var escaping = false + // ? => one single character + var patternListStack = [] + var negativeLists = [] + var stateChar + var inClass = false + var reClassStart = -1 + var classStart = -1 + // . and .. never match anything that doesn't start with ., + // even when options.dot is set. + var patternStart = pattern.charAt(0) === '.' ? '' // anything + // not (start or / followed by . or .. followed by / or end) + : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))' + : '(?!\\.)' + var self = this + + function clearStateChar () { + if (stateChar) { + // we had some state-tracking character + // that wasn't consumed by this pass. + switch (stateChar) { + case '*': + re += star + hasMagic = true + break + case '?': + re += qmark + hasMagic = true + break + default: + re += '\\' + stateChar + break + } + self.debug('clearStateChar %j %j', stateChar, re) + stateChar = false + } + } + + for (var i = 0, len = pattern.length, c + ; (i < len) && (c = pattern.charAt(i)) + ; i++) { + this.debug('%s\t%s %s %j', pattern, i, re, c) + + // skip over any that are escaped. + if (escaping && reSpecials[c]) { + re += '\\' + c + escaping = false + continue + } + + switch (c) { + case '/': + // completely not allowed, even escaped. + // Should already be path-split by now. + return false + + case '\\': + clearStateChar() + escaping = true + continue + + // the various stateChar values + // for the "extglob" stuff. + case '?': + case '*': + case '+': + case '@': + case '!': + this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c) + + // all of those are literals inside a class, except that + // the glob [!a] means [^a] in regexp + if (inClass) { + this.debug(' in class') + if (c === '!' && i === classStart + 1) c = '^' + re += c + continue + } + + // if we already have a stateChar, then it means + // that there was something like ** or +? in there. + // Handle the stateChar, then proceed with this one. + self.debug('call clearStateChar %j', stateChar) + clearStateChar() + stateChar = c + // if extglob is disabled, then +(asdf|foo) isn't a thing. + // just clear the statechar *now*, rather than even diving into + // the patternList stuff. + if (options.noext) clearStateChar() + continue + + case '(': + if (inClass) { + re += '(' + continue + } + + if (!stateChar) { + re += '\\(' + continue + } + + patternListStack.push({ + type: stateChar, + start: i - 1, + reStart: re.length, + open: plTypes[stateChar].open, + close: plTypes[stateChar].close + }) + // negation is (?:(?!js)[^/]*) + re += stateChar === '!' ? '(?:(?!(?:' : '(?:' + this.debug('plType %j %j', stateChar, re) + stateChar = false + continue + + case ')': + if (inClass || !patternListStack.length) { + re += '\\)' + continue + } + + clearStateChar() + hasMagic = true + var pl = patternListStack.pop() + // negation is (?:(?!js)[^/]*) + // The others are (?:) + re += pl.close + if (pl.type === '!') { + negativeLists.push(pl) + } + pl.reEnd = re.length + continue + + case '|': + if (inClass || !patternListStack.length || escaping) { + re += '\\|' + escaping = false + continue + } + + clearStateChar() + re += '|' + continue + + // these are mostly the same in regexp and glob + case '[': + // swallow any state-tracking char before the [ + clearStateChar() + + if (inClass) { + re += '\\' + c + continue + } + + inClass = true + classStart = i + reClassStart = re.length + re += c + continue + + case ']': + // a right bracket shall lose its special + // meaning and represent itself in + // a bracket expression if it occurs + // first in the list. -- POSIX.2 2.8.3.2 + if (i === classStart + 1 || !inClass) { + re += '\\' + c + escaping = false + continue + } + + // handle the case where we left a class open. + // "[z-a]" is valid, equivalent to "\[z-a\]" + if (inClass) { + // split where the last [ was, make sure we don't have + // an invalid re. if so, re-walk the contents of the + // would-be class to re-translate any characters that + // were passed through as-is + // TODO: It would probably be faster to determine this + // without a try/catch and a new RegExp, but it's tricky + // to do safely. For now, this is safe and works. + var cs = pattern.substring(classStart + 1, i) + try { + RegExp('[' + cs + ']') + } catch (er) { + // not a valid class! + var sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]' + hasMagic = hasMagic || sp[1] + inClass = false + continue + } + } + + // finish up the class. + hasMagic = true + inClass = false + re += c + continue + + default: + // swallow any state char that wasn't consumed + clearStateChar() + + if (escaping) { + // no need + escaping = false + } else if (reSpecials[c] + && !(c === '^' && inClass)) { + re += '\\' + } + + re += c + + } // switch + } // for + + // handle the case where we left a class open. + // "[abc" is valid, equivalent to "\[abc" + if (inClass) { + // split where the last [ was, and escape it + // this is a huge pita. We now have to re-walk + // the contents of the would-be class to re-translate + // any characters that were passed through as-is + cs = pattern.substr(classStart + 1) + sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + '\\[' + sp[0] + hasMagic = hasMagic || sp[1] + } + + // handle the case where we had a +( thing at the *end* + // of the pattern. + // each pattern list stack adds 3 chars, and we need to go through + // and escape any | chars that were passed through as-is for the regexp. + // Go through and escape them, taking care not to double-escape any + // | chars that were already escaped. + for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) { + var tail = re.slice(pl.reStart + pl.open.length) + this.debug('setting tail', re, pl) + // maybe some even number of \, then maybe 1 \, followed by a | + tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) { + if (!$2) { + // the | isn't already escaped, so escape it. + $2 = '\\' + } + + // need to escape all those slashes *again*, without escaping the + // one that we need for escaping the | character. As it works out, + // escaping an even number of slashes can be done by simply repeating + // it exactly after itself. That's why this trick works. + // + // I am sorry that you have to see this. + return $1 + $1 + $2 + '|' + }) + + this.debug('tail=%j\n %s', tail, tail, pl, re) + var t = pl.type === '*' ? star + : pl.type === '?' ? qmark + : '\\' + pl.type + + hasMagic = true + re = re.slice(0, pl.reStart) + t + '\\(' + tail + } + + // handle trailing things that only matter at the very end. + clearStateChar() + if (escaping) { + // trailing \\ + re += '\\\\' + } + + // only need to apply the nodot start if the re starts with + // something that could conceivably capture a dot + var addPatternStart = false + switch (re.charAt(0)) { + case '.': + case '[': + case '(': addPatternStart = true + } + + // Hack to work around lack of negative lookbehind in JS + // A pattern like: *.!(x).!(y|z) needs to ensure that a name + // like 'a.xyz.yz' doesn't match. So, the first negative + // lookahead, has to look ALL the way ahead, to the end of + // the pattern. + for (var n = negativeLists.length - 1; n > -1; n--) { + var nl = negativeLists[n] + + var nlBefore = re.slice(0, nl.reStart) + var nlFirst = re.slice(nl.reStart, nl.reEnd - 8) + var nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + var nlAfter = re.slice(nl.reEnd) + + nlLast += nlAfter + + // Handle nested stuff like *(*.js|!(*.json)), where open parens + // mean that we should *not* include the ) in the bit that is considered + // "after" the negated section. + var openParensBefore = nlBefore.split('(').length - 1 + var cleanAfter = nlAfter + for (i = 0; i < openParensBefore; i++) { + cleanAfter = cleanAfter.replace(/\)[+*?]?/, '') + } + nlAfter = cleanAfter + + var dollar = '' + if (nlAfter === '' && isSub !== SUBPARSE) { + dollar = '$' + } + var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast + re = newRe + } + + // if the re is not "" at this point, then we need to make sure + // it doesn't match against an empty path part. + // Otherwise a/* will match a/, which it should not. + if (re !== '' && hasMagic) { + re = '(?=.)' + re + } + + if (addPatternStart) { + re = patternStart + re + } + + // parsing just a piece of a larger pattern. + if (isSub === SUBPARSE) { + return [re, hasMagic] + } + + // skip the regexp for non-magical patterns + // unescape anything in it, though, so that it'll be + // an exact match against a file etc. + if (!hasMagic) { + return globUnescape(pattern) + } + + var flags = options.nocase ? 'i' : '' + try { + var regExp = new RegExp('^' + re + '$', flags) + } catch (er) { + // If it was an invalid regular expression, then it can't match + // anything. This trick looks for a character after the end of + // the string, which is of course impossible, except in multi-line + // mode, but it's not a /m regex. + return new RegExp('$.') + } + + regExp._glob = pattern + regExp._src = re + + return regExp +} + +minimatch.makeRe = function (pattern, options) { + return new Minimatch(pattern, options || {}).makeRe() +} + +Minimatch.prototype.makeRe = makeRe +function makeRe () { + if (this.regexp || this.regexp === false) return this.regexp + + // at this point, this.set is a 2d array of partial + // pattern strings, or "**". + // + // It's better to use .match(). This function shouldn't + // be used, really, but it's pretty convenient sometimes, + // when you just want to work with a regex. + var set = this.set + + if (!set.length) { + this.regexp = false + return this.regexp + } + var options = this.options + + var twoStar = options.noglobstar ? star + : options.dot ? twoStarDot + : twoStarNoDot + var flags = options.nocase ? 'i' : '' + + var re = set.map(function (pattern) { + return pattern.map(function (p) { + return (p === GLOBSTAR) ? twoStar + : (typeof p === 'string') ? regExpEscape(p) + : p._src + }).join('\\\/') + }).join('|') + + // must match entire pattern + // ending in a * or ** will make it less strict. + re = '^(?:' + re + ')$' + + // can match anything, as long as it's not this. + if (this.negate) re = '^(?!' + re + ').*$' + + try { + this.regexp = new RegExp(re, flags) + } catch (ex) { + this.regexp = false + } + return this.regexp +} + +minimatch.match = function (list, pattern, options) { + options = options || {} + var mm = new Minimatch(pattern, options) + list = list.filter(function (f) { + return mm.match(f) + }) + if (mm.options.nonull && !list.length) { + list.push(pattern) + } + return list +} + +Minimatch.prototype.match = match +function match (f, partial) { + this.debug('match', f, this.pattern) + // short-circuit in the case of busted things. + // comments, etc. + if (this.comment) return false + if (this.empty) return f === '' + + if (f === '/' && partial) return true + + var options = this.options + + // windows: need to use /, not \ + if (path.sep !== '/') { + f = f.split(path.sep).join('/') + } + + // treat the test path as a set of pathparts. + f = f.split(slashSplit) + this.debug(this.pattern, 'split', f) + + // just ONE of the pattern sets in this.set needs to match + // in order for it to be valid. If negating, then just one + // match means that we have failed. + // Either way, return on the first hit. + + var set = this.set + this.debug(this.pattern, 'set', set) + + // Find the basename of the path by looking for the last non-empty segment + var filename + var i + for (i = f.length - 1; i >= 0; i--) { + filename = f[i] + if (filename) break + } + + for (i = 0; i < set.length; i++) { + var pattern = set[i] + var file = f + if (options.matchBase && pattern.length === 1) { + file = [filename] + } + var hit = this.matchOne(file, pattern, partial) + if (hit) { + if (options.flipNegate) return true + return !this.negate + } + } + + // didn't get any hits. this is success if it's a negative + // pattern, failure otherwise. + if (options.flipNegate) return false + return this.negate +} + +// set partial to true to test if, for example, +// "/a/b" matches the start of "/*/b/*/d" +// Partial means, if you run out of file before you run +// out of pattern, then that's fine, as long as all +// the parts match. +Minimatch.prototype.matchOne = function (file, pattern, partial) { + var options = this.options + + this.debug('matchOne', + { 'this': this, file: file, pattern: pattern }) + + this.debug('matchOne', file.length, pattern.length) + + for (var fi = 0, + pi = 0, + fl = file.length, + pl = pattern.length + ; (fi < fl) && (pi < pl) + ; fi++, pi++) { + this.debug('matchOne loop') + var p = pattern[pi] + var f = file[fi] + + this.debug(pattern, p, f) + + // should be impossible. + // some invalid regexp stuff in the set. + if (p === false) return false + + if (p === GLOBSTAR) { + this.debug('GLOBSTAR', [pattern, p, f]) + + // "**" + // a/**/b/**/c would match the following: + // a/b/x/y/z/c + // a/x/y/z/b/c + // a/b/x/b/x/c + // a/b/c + // To do this, take the rest of the pattern after + // the **, and see if it would match the file remainder. + // If so, return success. + // If not, the ** "swallows" a segment, and try again. + // This is recursively awful. + // + // a/**/b/**/c matching a/b/x/y/z/c + // - a matches a + // - doublestar + // - matchOne(b/x/y/z/c, b/**/c) + // - b matches b + // - doublestar + // - matchOne(x/y/z/c, c) -> no + // - matchOne(y/z/c, c) -> no + // - matchOne(z/c, c) -> no + // - matchOne(c, c) yes, hit + var fr = fi + var pr = pi + 1 + if (pr === pl) { + this.debug('** at the end') + // a ** at the end will just swallow the rest. + // We have found a match. + // however, it will not swallow /.x, unless + // options.dot is set. + // . and .. are *never* matched by **, for explosively + // exponential reasons. + for (; fi < fl; fi++) { + if (file[fi] === '.' || file[fi] === '..' || + (!options.dot && file[fi].charAt(0) === '.')) return false + } + return true + } + + // ok, let's see if we can swallow whatever we can. + while (fr < fl) { + var swallowee = file[fr] + + this.debug('\nglobstar while', file, fr, pattern, pr, swallowee) + + // XXX remove this slice. Just pass the start index. + if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { + this.debug('globstar found match!', fr, fl, swallowee) + // found a match. + return true + } else { + // can't swallow "." or ".." ever. + // can only swallow ".foo" when explicitly asked. + if (swallowee === '.' || swallowee === '..' || + (!options.dot && swallowee.charAt(0) === '.')) { + this.debug('dot detected!', file, fr, pattern, pr) + break + } + + // ** swallows a segment, and continue. + this.debug('globstar swallow a segment, and continue') + fr++ + } + } + + // no match was found. + // However, in partial mode, we can't say this is necessarily over. + // If there's more *pattern* left, then + if (partial) { + // ran out of file + this.debug('\n>>> no match, partial?', file, fr, pattern, pr) + if (fr === fl) return true + } + return false + } + + // something other than ** + // non-magic patterns just have to match exactly + // patterns with magic have been turned into regexps. + var hit + if (typeof p === 'string') { + if (options.nocase) { + hit = f.toLowerCase() === p.toLowerCase() + } else { + hit = f === p + } + this.debug('string match', p, f, hit) + } else { + hit = f.match(p) + this.debug('pattern match', p, f, hit) + } + + if (!hit) return false + } + + // Note: ending in / means that we'll get a final "" + // at the end of the pattern. This can only match a + // corresponding "" at the end of the file. + // If the file ends in /, then it can only match a + // a pattern that ends in /, unless the pattern just + // doesn't have any more for it. But, a/b/ should *not* + // match "a/b/*", even though "" matches against the + // [^/]*? pattern, except in partial mode, where it might + // simply not be reached yet. + // However, a/b/ should still satisfy a/* + + // now either we fell off the end of the pattern, or we're done. + if (fi === fl && pi === pl) { + // ran out of pattern and filename at the same time. + // an exact hit! + return true + } else if (fi === fl) { + // ran out of file, but still had pattern left. + // this is ok if we're doing the match as part of + // a glob fs traversal. + return partial + } else if (pi === pl) { + // ran out of pattern, still have file left. + // this is only acceptable if we're on the very last + // empty segment of a file with a trailing slash. + // a/* should match a/b/ + var emptyFileEnd = (fi === fl - 1) && (file[fi] === '') + return emptyFileEnd + } + + // should be unreachable. + throw new Error('wtf?') +} + +// replace stuff like \* with * +function globUnescape (s) { + return s.replace(/\\(.)/g, '$1') +} + +function regExpEscape (s) { + return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') +} + +},{"brace-expansion":119,"path":469}],467:[function(require,module,exports){ +/** + * Helpers. + */ + +var s = 1000 +var m = s * 60 +var h = m * 60 +var d = h * 24 +var y = d * 365.25 + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} options + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function (val, options) { + options = options || {} + var type = typeof val + if (type === 'string' && val.length > 0) { + return parse(val) + } else if (type === 'number' && isNaN(val) === false) { + return options.long ? + fmtLong(val) : + fmtShort(val) + } + throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val)) +} + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str) + if (str.length > 10000) { + return + } + var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str) + if (!match) { + return + } + var n = parseFloat(match[1]) + var type = (match[2] || 'ms').toLowerCase() + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y + case 'days': + case 'day': + case 'd': + return n * d + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n + default: + return undefined + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + if (ms >= d) { + return Math.round(ms / d) + 'd' + } + if (ms >= h) { + return Math.round(ms / h) + 'h' + } + if (ms >= m) { + return Math.round(ms / m) + 'm' + } + if (ms >= s) { + return Math.round(ms / s) + 's' + } + return ms + 'ms' +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + return plural(ms, d, 'day') || + plural(ms, h, 'hour') || + plural(ms, m, 'minute') || + plural(ms, s, 'second') || + ms + ' ms' +} + +/** + * Pluralization helper. + */ + +function plural(ms, n, name) { + if (ms < n) { + return + } + if (ms < n * 1.5) { + return Math.floor(ms / n) + ' ' + name + } + return Math.ceil(ms / n) + ' ' + name + 's' +} + +},{}],468:[function(require,module,exports){ +'use strict'; +module.exports = Number.isNaN || function (x) { + return x !== x; +}; + +},{}],469:[function(require,module,exports){ +(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); + } +; + +}).call(this,require('_process')) +},{"_process":471}],470:[function(require,module,exports){ +(function (process){ +'use strict'; + +function posix(path) { + return path.charAt(0) === '/'; +} + +function win32(path) { + // https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56 + var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; + var result = splitDeviceRe.exec(path); + var device = result[1] || ''; + var isUnc = Boolean(device && device.charAt(1) !== ':'); + + // UNC paths are always absolute + return Boolean(result[2] || isUnc); +} + +module.exports = process.platform === 'win32' ? win32 : posix; +module.exports.posix = posix; +module.exports.win32 = win32; + +}).call(this,require('_process')) +},{"_process":471}],471:[function(require,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; }; + +},{}],472:[function(require,module,exports){ +'use strict'; +var isFinite = require('is-finite'); + +module.exports = function (str, n) { + if (typeof str !== 'string') { + throw new TypeError('Expected `input` to be a string'); + } + + if (n < 0 || !isFinite(n)) { + throw new TypeError('Expected `count` to be a positive finite number'); + } + + var ret = ''; + + do { + if (n & 1) { + ret += str; + } + + str += str; + } while ((n >>= 1)); + + return ret; +}; + +},{"is-finite":246}],473:[function(require,module,exports){ +'use strict'; +module.exports = function (str) { + var isExtendedLengthPath = /^\\\\\?\\/.test(str); + var hasNonAscii = /[^\x00-\x80]+/.test(str); + + if (isExtendedLengthPath || hasNonAscii) { + return str; + } + + return str.replace(/\\/g, '/'); +}; + +},{}],474:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +var util = require('./util'); +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; + +},{"./util":483}],475:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * 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 = require('./base64'); + +// 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; +}; + +},{"./base64":476}],476:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +var 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; +}; + +},{}],477:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +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; +}; + +},{}],478:[function(require,module,exports){ +/* -*- 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 = require('./util'); + +/** + * 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; + +},{"./util":483}],479:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +// 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); +}; + +},{}],480:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +var util = require('./util'); +var binarySearch = require('./binary-search'); +var ArraySet = require('./array-set').ArraySet; +var base64VLQ = require('./base64-vlq'); +var quickSort = require('./quick-sort').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; + +},{"./array-set":474,"./base64-vlq":475,"./binary-search":477,"./quick-sort":479,"./util":483}],481:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +var base64VLQ = require('./base64-vlq'); +var util = require('./util'); +var ArraySet = require('./array-set').ArraySet; +var MappingList = require('./mapping-list').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; + +},{"./array-set":474,"./base64-vlq":475,"./mapping-list":478,"./util":483}],482:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; +var util = require('./util'); + +// 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; + +},{"./source-map-generator":481,"./util":483}],483:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/** + * 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 '/..' 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; + +},{}],484:[function(require,module,exports){ +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = require('./lib/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = require('./lib/source-map-consumer').SourceMapConsumer; +exports.SourceNode = require('./lib/source-node').SourceNode; + +},{"./lib/source-map-consumer":480,"./lib/source-map-generator":481,"./lib/source-node":482}],485:[function(require,module,exports){ +'use strict'; +var ansiRegex = require('ansi-regex')(); + +module.exports = function (str) { + return typeof str === 'string' ? str.replace(ansiRegex, '') : str; +}; + +},{"ansi-regex":1}],486:[function(require,module,exports){ +(function (process){ +'use strict'; +var argv = process.argv; + +var terminator = argv.indexOf('--'); +var hasFlag = function (flag) { + flag = '--' + flag; + var pos = argv.indexOf(flag); + return pos !== -1 && (terminator !== -1 ? pos < terminator : true); +}; + +module.exports = (function () { + if ('FORCE_COLOR' in process.env) { + return true; + } + + if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false')) { + return false; + } + + if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + return true; + } + + if (process.stdout && !process.stdout.isTTY) { + return false; + } + + if (process.platform === 'win32') { + return true; + } + + if ('COLORTERM' in process.env) { + return true; + } + + if (process.env.TERM === 'dumb') { + return false; + } + + if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(process.env.TERM)) { + return true; + } + + return false; +})(); + +}).call(this,require('_process')) +},{"_process":471}],487:[function(require,module,exports){ +'use strict'; +module.exports = function toFastProperties(obj) { + function f() {} + f.prototype = obj; + new f(); + return; + eval(obj); +}; + +},{}],488:[function(require,module,exports){ +'use strict'; +module.exports = function (str) { + var tail = str.length; + + while (/[\s\uFEFF\u00A0]/.test(str[tail - 1])) { + tail--; + } + + return str.slice(0, tail); +}; + +},{}],489:[function(require,module,exports){ +exports.isatty = function () { return false; }; + +function ReadStream() { + throw new Error('tty.ReadStream is not implemented'); +} +exports.ReadStream = ReadStream; + +function WriteStream() { + throw new Error('tty.ReadStream is not implemented'); +} +exports.WriteStream = WriteStream; + +},{}],490:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],491:[function(require,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],492:[function(require,module,exports){ +(function (process,global){ +// 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 formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = require('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = require('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":491,"_process":471,"inherits":490}],493:[function(require,module,exports){ +/*import { transform as babelTransform } from 'babel-core'; +import babelTransformDynamicImport from 'babel-plugin-syntax-dynamic-import'; +import babelTransformES2015ModulesSystemJS from 'babel-plugin-transform-es2015-modules-systemjs';*/ + +// sadly, due to how rollup works, we can't use es6 imports here +var babelTransform = require('babel-core').transform; +var babelTransformDynamicImport = require('babel-plugin-syntax-dynamic-import'); +var babelTransformES2015ModulesSystemJS = require('babel-plugin-transform-es2015-modules-systemjs'); + +self.onmessage = function (evt) { + // transform source with Babel + var output = babelTransform(evt.data.source, { + compact: false, + filename: evt.data.key + '!transpiled', + sourceFileName: evt.data.key, + moduleIds: false, + sourceMaps: 'inline', + babelrc: false, + plugins: [babelTransformDynamicImport, babelTransformES2015ModulesSystemJS], + }); + + self.postMessage({key: evt.data.key, code: output.code, source: evt.data.source}); +}; + +},{"babel-core":4,"babel-plugin-syntax-dynamic-import":54,"babel-plugin-transform-es2015-modules-systemjs":55}]},{},[493]); diff --git a/vendor/browser-es-module-loader/dist/browser-es-module-loader.js b/vendor/browser-es-module-loader/dist/browser-es-module-loader.js new file mode 100644 index 00000000..f191d1a5 --- /dev/null +++ b/vendor/browser-es-module-loader/dist/browser-es-module-loader.js @@ -0,0 +1,1409 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.BrowserESModuleLoader = factory()); +}(this, (function () { 'use strict'; + +/* + * Environment + */ +var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined'; +var isNode = typeof process !== 'undefined' && process.versions && process.versions.node; +var isWindows = typeof process !== 'undefined' && typeof process.platform === 'string' && process.platform.match(/^win/); + +var envGlobal = typeof self !== 'undefined' ? self : global; +/* + * Simple Symbol() shim + */ +var hasSymbol = typeof Symbol !== 'undefined'; +function createSymbol (name) { + return hasSymbol ? Symbol() : '@@' + name; +} + + + + + +/* + * Environment baseURI + */ +var baseURI; + +// environent baseURI detection +if (typeof document != 'undefined' && document.getElementsByTagName) { + baseURI = document.baseURI; + + if (!baseURI) { + var bases = document.getElementsByTagName('base'); + baseURI = bases[0] && bases[0].href || window.location.href; + } +} +else if (typeof location != 'undefined') { + baseURI = location.href; +} + +// sanitize out the hash and querystring +if (baseURI) { + baseURI = baseURI.split('#')[0].split('?')[0]; + var slashIndex = baseURI.lastIndexOf('/'); + if (slashIndex !== -1) + baseURI = baseURI.substr(0, slashIndex + 1); +} +else if (typeof process !== 'undefined' && process.cwd) { + baseURI = 'file://' + (isWindows ? '/' : '') + process.cwd(); + if (isWindows) + baseURI = baseURI.replace(/\\/g, '/'); +} +else { + throw new TypeError('No environment baseURI'); +} + +// ensure baseURI has trailing "/" +if (baseURI[baseURI.length - 1] !== '/') + baseURI += '/'; + +/* + * LoaderError with chaining for loader stacks + */ +var errArgs = new Error(0, '_').fileName == '_'; +function LoaderError__Check_error_message_for_loader_stack (childErr, newMessage) { + // Convert file:/// URLs to paths in Node + if (!isBrowser) + newMessage = newMessage.replace(isWindows ? /file:\/\/\//g : /file:\/\//g, ''); + + var message = (childErr.message || childErr) + '\n ' + newMessage; + + var err; + if (errArgs && childErr.fileName) + err = new Error(message, childErr.fileName, childErr.lineNumber); + else + err = new Error(message); + + + var stack = childErr.originalErr ? childErr.originalErr.stack : childErr.stack; + + if (isNode) + // node doesn't show the message otherwise + err.stack = message + '\n ' + stack; + else + err.stack = stack; + + err.originalErr = childErr.originalErr || childErr; + + return err; +} + +var resolvedPromise = Promise.resolve(); + +/* + * Simple Array values shim + */ +function arrayValues (arr) { + if (arr.values) + return arr.values(); + + if (typeof Symbol === 'undefined' || !Symbol.iterator) + throw new Error('Symbol.iterator not supported in this browser'); + + var iterable = {}; + iterable[Symbol.iterator] = function () { + var keys = Object.keys(arr); + var keyIndex = 0; + return { + next: function () { + if (keyIndex < keys.length) + return { + value: arr[keys[keyIndex++]], + done: false + }; + else + return { + value: undefined, + done: true + }; + } + }; + }; + return iterable; +} + +/* + * 3. Reflect.Loader + * + * We skip the entire native internal pipeline, just providing the bare API + */ +// 3.1.1 +function Loader () { + this.registry = new Registry(); +} +// 3.3.1 +Loader.prototype.constructor = Loader; + +function ensureInstantiated (module) { + if (!(module instanceof ModuleNamespace)) + throw new TypeError('Module instantiation did not return a valid namespace object.'); + return module; +} + +// 3.3.2 +Loader.prototype.import = function (key, parent) { + if (typeof key !== 'string') + throw new TypeError('Loader import method must be passed a module key string'); + // custom resolveInstantiate combined hook for better perf + var loader = this; + return resolvedPromise + .then(function () { + return loader[RESOLVE_INSTANTIATE](key, parent); + }) + .then(ensureInstantiated) + //.then(Module.evaluate) + .catch(function (err) { + throw LoaderError__Check_error_message_for_loader_stack(err, 'Loading ' + key + (parent ? ' from ' + parent : '')); + }); +}; +// 3.3.3 +var RESOLVE = Loader.resolve = createSymbol('resolve'); + +/* + * Combined resolve / instantiate hook + * + * Not in current reduced spec, but necessary to separate RESOLVE from RESOLVE + INSTANTIATE as described + * in the spec notes of this repo to ensure that loader.resolve doesn't instantiate when not wanted. + * + * We implement RESOLVE_INSTANTIATE as a single hook instead of a separate INSTANTIATE in order to avoid + * the need for double registry lookups as a performance optimization. + */ +var RESOLVE_INSTANTIATE = Loader.resolveInstantiate = createSymbol('resolveInstantiate'); + +// default resolveInstantiate is just to call resolve and then get from the registry +// this provides compatibility for the resolveInstantiate optimization +Loader.prototype[RESOLVE_INSTANTIATE] = function (key, parent) { + var loader = this; + return loader.resolve(key, parent) + .then(function (resolved) { + return loader.registry.get(resolved); + }); +}; + +function ensureResolution (resolvedKey) { + if (resolvedKey === undefined) + throw new RangeError('No resolution found.'); + return resolvedKey; +} + +Loader.prototype.resolve = function (key, parent) { + var loader = this; + return resolvedPromise + .then(function() { + return loader[RESOLVE](key, parent); + }) + .then(ensureResolution) + .catch(function (err) { + throw LoaderError__Check_error_message_for_loader_stack(err, 'Resolving ' + key + (parent ? ' to ' + parent : '')); + }); +}; + +// 3.3.4 (import without evaluate) +// this is not documented because the use of deferred evaluation as in Module.evaluate is not +// documented, as it is not considered a stable feature to be encouraged +// Loader.prototype.load may well be deprecated if this stays disabled +/* Loader.prototype.load = function (key, parent) { + return Promise.resolve(this[RESOLVE_INSTANTIATE](key, parent || this.key)) + .catch(function (err) { + throw addToError(err, 'Loading ' + key + (parent ? ' from ' + parent : '')); + }); +}; */ + +/* + * 4. Registry + * + * Instead of structuring through a Map, just use a dictionary object + * We throw for construction attempts so this doesn't affect the public API + * + * Registry has been adjusted to use Namespace objects over ModuleStatus objects + * as part of simplifying loader API implementation + */ +var iteratorSupport = typeof Symbol !== 'undefined' && Symbol.iterator; +var REGISTRY = createSymbol('registry'); +function Registry() { + this[REGISTRY] = {}; + this._registry = REGISTRY; +} +// 4.4.1 +if (iteratorSupport) { + // 4.4.2 + Registry.prototype[Symbol.iterator] = function () { + return this.entries()[Symbol.iterator](); + }; + + // 4.4.3 + Registry.prototype.entries = function () { + var registry = this[REGISTRY]; + return arrayValues(Object.keys(registry).map(function (key) { + return [key, registry[key]]; + })); + }; +} + +// 4.4.4 +Registry.prototype.keys = function () { + return arrayValues(Object.keys(this[REGISTRY])); +}; +// 4.4.5 +Registry.prototype.values = function () { + var registry = this[REGISTRY]; + return arrayValues(Object.keys(registry).map(function (key) { + return registry[key]; + })); +}; +// 4.4.6 +Registry.prototype.get = function (key) { + return this[REGISTRY][key]; +}; +// 4.4.7 +Registry.prototype.set = function (key, namespace) { + if (!(namespace instanceof ModuleNamespace)) + throw new Error('Registry must be set with an instance of Module Namespace'); + this[REGISTRY][key] = namespace; + return this; +}; +// 4.4.8 +Registry.prototype.has = function (key) { + return Object.hasOwnProperty.call(this[REGISTRY], key); +}; +// 4.4.9 +Registry.prototype.delete = function (key) { + if (Object.hasOwnProperty.call(this[REGISTRY], key)) { + delete this[REGISTRY][key]; + return true; + } + return false; +}; + +/* + * Simple ModuleNamespace Exotic object based on a baseObject + * We export this for allowing a fast-path for module namespace creation over Module descriptors + */ +// var EVALUATE = createSymbol('evaluate'); +var BASE_OBJECT = createSymbol('baseObject'); + +// 8.3.1 Reflect.Module +/* + * Best-effort simplified non-spec implementation based on + * a baseObject referenced via getters. + * + * Allows: + * + * loader.registry.set('x', new Module({ default: 'x' })); + * + * Optional evaluation function provides experimental Module.evaluate + * support for non-executed modules in registry. + */ +function ModuleNamespace (baseObject/*, evaluate*/) { + Object.defineProperty(this, BASE_OBJECT, { + value: baseObject + }); + + // evaluate defers namespace population + /* if (evaluate) { + Object.defineProperty(this, EVALUATE, { + value: evaluate, + configurable: true, + writable: true + }); + } + else { */ + Object.keys(baseObject).forEach(extendNamespace, this); + //} +} +// 8.4.2 +ModuleNamespace.prototype = Object.create(null); + +if (typeof Symbol !== 'undefined' && Symbol.toStringTag) + Object.defineProperty(ModuleNamespace.prototype, Symbol.toStringTag, { + value: 'Module' + }); + +function extendNamespace (key) { + Object.defineProperty(this, key, { + enumerable: true, + get: function () { + return this[BASE_OBJECT][key]; + } + }); +} + +/* function doEvaluate (evaluate, context) { + try { + evaluate.call(context); + } + catch (e) { + return e; + } +} + +// 8.4.1 Module.evaluate... not documented or used because this is potentially unstable +Module.evaluate = function (ns) { + var evaluate = ns[EVALUATE]; + if (evaluate) { + ns[EVALUATE] = undefined; + var err = doEvaluate(evaluate); + if (err) { + // cache the error + ns[EVALUATE] = function () { + throw err; + }; + throw err; + } + Object.keys(ns[BASE_OBJECT]).forEach(extendNamespace, ns); + } + // make chainable + return ns; +}; */ + +/* + * Optimized URL normalization assuming a syntax-valid URL parent + */ +function throwResolveError (relUrl, parentUrl) { + throw new RangeError('Unable to resolve "' + relUrl + '" to ' + parentUrl); +} +function resolveIfNotPlain (relUrl, parentUrl) { + relUrl = relUrl.trim(); + var parentProtocol = parentUrl && parentUrl.substr(0, parentUrl.indexOf(':') + 1); + + var firstChar = relUrl[0]; + var secondChar = relUrl[1]; + + // protocol-relative + if (firstChar === '/' && secondChar === '/') { + if (!parentProtocol) + throwResolveError(relUrl, parentUrl); + return parentProtocol + relUrl; + } + // relative-url + else if (firstChar === '.' && (secondChar === '/' || secondChar === '.' && (relUrl[2] === '/' || relUrl.length === 2) || relUrl.length === 1) + || firstChar === '/') { + var parentIsPlain = !parentProtocol || parentUrl[parentProtocol.length] !== '/'; + + // read pathname from parent if a URL + // pathname taken to be part after leading "/" + var pathname; + if (parentIsPlain) { + // resolving to a plain parent -> skip standard URL prefix, and treat entire parent as pathname + if (parentUrl === undefined) + throwResolveError(relUrl, parentUrl); + pathname = parentUrl; + } + else if (parentUrl[parentProtocol.length + 1] === '/') { + // resolving to a :// so we need to read out the auth and host + if (parentProtocol !== 'file:') { + pathname = parentUrl.substr(parentProtocol.length + 2); + pathname = pathname.substr(pathname.indexOf('/') + 1); + } + else { + pathname = parentUrl.substr(8); + } + } + else { + // resolving to :/ so pathname is the /... part + pathname = parentUrl.substr(parentProtocol.length + 1); + } + + if (firstChar === '/') { + if (parentIsPlain) + throwResolveError(relUrl, parentUrl); + else + return parentUrl.substr(0, parentUrl.length - pathname.length - 1) + relUrl; + } + + // join together and split for removal of .. and . segments + // looping the string instead of anything fancy for perf reasons + // '../../../../../z' resolved to 'x/y' is just 'z' regardless of parentIsPlain + var segmented = pathname.substr(0, pathname.lastIndexOf('/') + 1) + relUrl; + + var output = []; + var segmentIndex = undefined; + + for (var i = 0; i < segmented.length; i++) { + // busy reading a segment - only terminate on '/' + if (segmentIndex !== undefined) { + if (segmented[i] === '/') { + output.push(segmented.substr(segmentIndex, i - segmentIndex + 1)); + segmentIndex = undefined; + } + continue; + } + + // new segment - check if it is relative + if (segmented[i] === '.') { + // ../ segment + if (segmented[i + 1] === '.' && (segmented[i + 2] === '/' || i === segmented.length - 2)) { + output.pop(); + i += 2; + } + // ./ segment + else if (segmented[i + 1] === '/' || i === segmented.length - 1) { + i += 1; + } + else { + // the start of a new segment as below + segmentIndex = i; + continue; + } + + // this is the plain URI backtracking error (../, package:x -> error) + if (parentIsPlain && output.length === 0) + throwResolveError(relUrl, parentUrl); + + // trailing . or .. segment + if (i === segmented.length) + output.push(''); + continue; + } + + // it is the start of a new segment + segmentIndex = i; + } + // finish reading out the last segment + if (segmentIndex !== undefined) + output.push(segmented.substr(segmentIndex, segmented.length - segmentIndex)); + + return parentUrl.substr(0, parentUrl.length - pathname.length) + output.join(''); + } + + // sanitizes and verifies (by returning undefined if not a valid URL-like form) + // Windows filepath compatibility is an added convenience here + var protocolIndex = relUrl.indexOf(':'); + if (protocolIndex !== -1) { + if (isNode) { + // C:\x becomes file:///c:/x (we don't support C|\x) + if (relUrl[1] === ':' && relUrl[2] === '\\' && relUrl[0].match(/[a-z]/i)) + return 'file:///' + relUrl.replace(/\\/g, '/'); + } + return relUrl; + } +} + +/* + * Register Loader + * + * Builds directly on top of loader polyfill to provide: + * - loader.register support + * - hookable higher-level resolve + * - instantiate hook returning a ModuleNamespace or undefined for es module loading + * - loader error behaviour as in HTML and loader specs, clearing failed modules from registration cache synchronously + * - build tracing support by providing a .trace=true and .loads object format + */ + +var REGISTER_INTERNAL = createSymbol('register-internal'); + +function RegisterLoader$1 () { + Loader.call(this); + + var registryDelete = this.registry.delete; + this.registry.delete = function (key) { + var deleted = registryDelete.call(this, key); + + // also delete from register registry if linked + if (records.hasOwnProperty(key) && !records[key].linkRecord) + delete records[key]; + + return deleted; + }; + + var records = {}; + + this[REGISTER_INTERNAL] = { + // last anonymous System.register call + lastRegister: undefined, + // in-flight es module load records + records: records + }; + + // tracing + this.trace = false; +} + +RegisterLoader$1.prototype = Object.create(Loader.prototype); +RegisterLoader$1.prototype.constructor = RegisterLoader$1; + +var INSTANTIATE = RegisterLoader$1.instantiate = createSymbol('instantiate'); + +// default normalize is the WhatWG style normalizer +RegisterLoader$1.prototype[RegisterLoader$1.resolve = Loader.resolve] = function (key, parentKey) { + return resolveIfNotPlain(key, parentKey || baseURI); +}; + +RegisterLoader$1.prototype[INSTANTIATE] = function (key, processAnonRegister) {}; + +// once evaluated, the linkRecord is set to undefined leaving just the other load record properties +// this allows tracking new binding listeners for es modules through importerSetters +// for dynamic modules, the load record is removed entirely. +function createLoadRecord (state, key, registration) { + return state.records[key] = { + key: key, + + // defined System.register cache + registration: registration, + + // module namespace object + module: undefined, + + // es-only + // this sticks around so new module loads can listen to binding changes + // for already-loaded modules by adding themselves to their importerSetters + importerSetters: undefined, + + // in-flight linking record + linkRecord: { + // promise for instantiated + instantiatePromise: undefined, + dependencies: undefined, + execute: undefined, + executingRequire: false, + + // underlying module object bindings + moduleObj: undefined, + + // es only, also indicates if es or not + setters: undefined, + + // promise for instantiated dependencies (dependencyInstantiations populated) + depsInstantiatePromise: undefined, + // will be the array of dependency load record or a module namespace + dependencyInstantiations: undefined, + + // indicates if the load and all its dependencies are instantiated and linked + // but not yet executed + // mostly just a performance shortpath to avoid rechecking the promises above + linked: false, + + error: undefined + // NB optimization and way of ensuring module objects in setters + // indicates setters which should run pre-execution of that dependency + // setters is then just for completely executed module objects + // alternatively we just pass the partially filled module objects as + // arguments into the execute function + // hoisted: undefined + } + }; +} + +RegisterLoader$1.prototype[Loader.resolveInstantiate] = function (key, parentKey) { + var loader = this; + var state = this[REGISTER_INTERNAL]; + var registry = loader.registry[loader.registry._registry]; + + return resolveInstantiate(loader, key, parentKey, registry, state) + .then(function (instantiated) { + if (instantiated instanceof ModuleNamespace) + return instantiated; + + // if already beaten to linked, return + if (instantiated.module) + return instantiated.module; + + // resolveInstantiate always returns a load record with a link record and no module value + if (instantiated.linkRecord.linked) + return ensureEvaluate(loader, instantiated, instantiated.linkRecord, registry, state, undefined); + + return instantiateDeps(loader, instantiated, instantiated.linkRecord, registry, state, [instantiated]) + .then(function () { + return ensureEvaluate(loader, instantiated, instantiated.linkRecord, registry, state, undefined); + }) + .catch(function (err) { + clearLoadErrors(loader, instantiated); + throw err; + }); + }); +}; + +function resolveInstantiate (loader, key, parentKey, registry, state) { + // normalization shortpath for already-normalized key + // could add a plain name filter, but doesn't yet seem necessary for perf + var module = registry[key]; + if (module) + return Promise.resolve(module); + + var load = state.records[key]; + + // already linked but not in main registry is ignored + if (load && !load.module) + return instantiate(loader, load, load.linkRecord, registry, state); + + return loader.resolve(key, parentKey) + .then(function (resolvedKey) { + // main loader registry always takes preference + module = registry[resolvedKey]; + if (module) + return module; + + load = state.records[resolvedKey]; + + // already has a module value but not already in the registry (load.module) + // means it was removed by registry.delete, so we should + // disgard the current load record creating a new one over it + // but keep any existing registration + if (!load || load.module) + load = createLoadRecord(state, resolvedKey, load && load.registration); + + var link = load.linkRecord; + if (!link) + return load; + + return instantiate(loader, load, link, registry, state); + }); +} + +function createProcessAnonRegister (loader, load, state) { + return function () { + var lastRegister = state.lastRegister; + + if (!lastRegister) + return !!load.registration; + + state.lastRegister = undefined; + load.registration = lastRegister; + + return true; + }; +} + +function instantiate (loader, load, link, registry, state) { + return link.instantiatePromise || (link.instantiatePromise = + // if there is already an existing registration, skip running instantiate + (load.registration ? Promise.resolve() : Promise.resolve().then(function () { + state.lastRegister = undefined; + return loader[INSTANTIATE](load.key, loader[INSTANTIATE].length > 1 && createProcessAnonRegister(loader, load, state)); + })) + .then(function (instantiation) { + // direct module return from instantiate -> we're done + if (instantiation !== undefined) { + if (!(instantiation instanceof ModuleNamespace)) + throw new TypeError('Instantiate did not return a valid Module object.'); + + delete state.records[load.key]; + if (loader.trace) + traceLoad(loader, load, link); + return registry[load.key] = instantiation; + } + + // run the cached loader.register declaration if there is one + var registration = load.registration; + // clear to allow new registrations for future loads (combined with registry delete) + load.registration = undefined; + if (!registration) + throw new TypeError('Module instantiation did not call an anonymous or correctly named System.register.'); + + link.dependencies = registration[0]; + + load.importerSetters = []; + + link.moduleObj = {}; + + // process System.registerDynamic declaration + if (registration[2]) { + link.moduleObj.default = {}; + link.moduleObj.__useDefault = true; + link.executingRequire = registration[1]; + link.execute = registration[2]; + } + + // process System.register declaration + else { + registerDeclarative(loader, load, link, registration[1]); + } + + // shortpath to instantiateDeps + if (!link.dependencies.length) { + link.linked = true; + if (loader.trace) + traceLoad(loader, load, link); + } + + return load; + }) + .catch(function (err) { + throw link.error = LoaderError__Check_error_message_for_loader_stack(err, 'Instantiating ' + load.key); + })); +} + +// like resolveInstantiate, but returning load records for linking +function resolveInstantiateDep (loader, key, parentKey, registry, state, traceDepMap) { + // normalization shortpaths for already-normalized key + // DISABLED to prioritise consistent resolver calls + // could add a plain name filter, but doesn't yet seem necessary for perf + /* var load = state.records[key]; + var module = registry[key]; + + if (module) { + if (traceDepMap) + traceDepMap[key] = key; + + // registry authority check in case module was deleted or replaced in main registry + if (load && load.module && load.module === module) + return load; + else + return module; + } + + // already linked but not in main registry is ignored + if (load && !load.module) { + if (traceDepMap) + traceDepMap[key] = key; + return instantiate(loader, load, load.linkRecord, registry, state); + } */ + return loader.resolve(key, parentKey) + .then(function (resolvedKey) { + if (traceDepMap) + traceDepMap[key] = resolvedKey; + + // normalization shortpaths for already-normalized key + var load = state.records[resolvedKey]; + var module = registry[resolvedKey]; + + // main loader registry always takes preference + if (module && (!load || load.module && module !== load.module)) + return module; + + // already has a module value but not already in the registry (load.module) + // means it was removed by registry.delete, so we should + // disgard the current load record creating a new one over it + // but keep any existing registration + if (!load || !module && load.module) + load = createLoadRecord(state, resolvedKey, load && load.registration); + + var link = load.linkRecord; + if (!link) + return load; + + return instantiate(loader, load, link, registry, state); + }); +} + +function traceLoad (loader, load, link) { + loader.loads = loader.loads || {}; + loader.loads[load.key] = { + key: load.key, + deps: link.dependencies, + depMap: link.depMap || {} + }; +} + +/* + * Convert a CJS module.exports into a valid object for new Module: + * + * new Module(getEsModule(module.exports)) + * + * Sets the default value to the module, while also reading off named exports carefully. + */ +function registerDeclarative (loader, load, link, declare) { + var moduleObj = link.moduleObj; + var importerSetters = load.importerSetters; + + var locked = false; + + // closure especially not based on link to allow link record disposal + var declared = declare.call(envGlobal, function (name, value) { + // export setter propogation with locking to avoid cycles + if (locked) + return; + + if (typeof name === 'object') { + for (var p in name) + if (p !== '__useDefault') + moduleObj[p] = name[p]; + } + else { + moduleObj[name] = value; + } + + locked = true; + for (var i = 0; i < importerSetters.length; i++) + importerSetters[i](moduleObj); + locked = false; + + return value; + }, new ContextualLoader(loader, load.key)); + + link.setters = declared.setters; + link.execute = declared.execute; + if (declared.exports) + link.moduleObj = moduleObj = declared.exports; +} + +function instantiateDeps (loader, load, link, registry, state, seen) { + return (link.depsInstantiatePromise || (link.depsInstantiatePromise = Promise.resolve() + .then(function () { + var depsInstantiatePromises = Array(link.dependencies.length); + + for (var i = 0; i < link.dependencies.length; i++) + depsInstantiatePromises[i] = resolveInstantiateDep(loader, link.dependencies[i], load.key, registry, state, loader.trace && link.depMap || (link.depMap = {})); + + return Promise.all(depsInstantiatePromises); + }) + .then(function (dependencyInstantiations) { + link.dependencyInstantiations = dependencyInstantiations; + + // run setters to set up bindings to instantiated dependencies + if (link.setters) { + for (var i = 0; i < dependencyInstantiations.length; i++) { + var setter = link.setters[i]; + if (setter) { + var instantiation = dependencyInstantiations[i]; + + if (instantiation instanceof ModuleNamespace) { + setter(instantiation); + } + else { + setter(instantiation.module || instantiation.linkRecord.moduleObj); + // this applies to both es and dynamic registrations + if (instantiation.importerSetters) + instantiation.importerSetters.push(setter); + } + } + } + } + }))) + .then(function () { + // now deeply instantiateDeps on each dependencyInstantiation that is a load record + var deepDepsInstantiatePromises = []; + + for (var i = 0; i < link.dependencies.length; i++) { + var depLoad = link.dependencyInstantiations[i]; + var depLink = depLoad.linkRecord; + + if (!depLink || depLink.linked) + continue; + + if (seen.indexOf(depLoad) !== -1) + continue; + seen.push(depLoad); + + deepDepsInstantiatePromises.push(instantiateDeps(loader, depLoad, depLoad.linkRecord, registry, state, seen)); + } + + return Promise.all(deepDepsInstantiatePromises); + }) + .then(function () { + // as soon as all dependencies instantiated, we are ready for evaluation so can add to the registry + // this can run multiple times, but so what + link.linked = true; + if (loader.trace) + traceLoad(loader, load, link); + + return load; + }) + .catch(function (err) { + err = LoaderError__Check_error_message_for_loader_stack(err, 'Loading ' + load.key); + + // throw up the instantiateDeps stack + // loads are then synchonously cleared at the top-level through the clearLoadErrors helper below + // this then ensures avoiding partially unloaded tree states + link.error = link.error || err; + + throw err; + }); +} + +// clears an errored load and all its errored dependencies from the loads registry +function clearLoadErrors (loader, load) { + var state = loader[REGISTER_INTERNAL]; + + // clear from loads + if (state.records[load.key] === load) + delete state.records[load.key]; + + var link = load.linkRecord; + + if (!link) + return; + + if (link.dependencyInstantiations) + link.dependencyInstantiations.forEach(function (depLoad, index) { + if (!depLoad || depLoad instanceof ModuleNamespace) + return; + + if (depLoad.linkRecord) { + if (depLoad.linkRecord.error) { + // provides a circular reference check + if (state.records[depLoad.key] === depLoad) + clearLoadErrors(loader, depLoad); + } + + // unregister setters for es dependency load records that will remain + if (link.setters && depLoad.importerSetters) { + var setterIndex = depLoad.importerSetters.indexOf(link.setters[index]); + depLoad.importerSetters.splice(setterIndex, 1); + } + } + }); +} + +/* + * System.register + */ +RegisterLoader$1.prototype.register = function (key, deps, declare) { + var state = this[REGISTER_INTERNAL]; + + // anonymous modules get stored as lastAnon + if (declare === undefined) { + state.lastRegister = [key, deps, undefined]; + } + + // everything else registers into the register cache + else { + var load = state.records[key] || createLoadRecord(state, key, undefined); + load.registration = [deps, declare, undefined]; + } +}; + +/* + * System.registerDyanmic + */ +RegisterLoader$1.prototype.registerDynamic = function (key, deps, executingRequire, execute) { + var state = this[REGISTER_INTERNAL]; + + // anonymous modules get stored as lastAnon + if (typeof key !== 'string') { + state.lastRegister = [key, deps, executingRequire]; + } + + // everything else registers into the register cache + else { + var load = state.records[key] || createLoadRecord(state, key, undefined); + load.registration = [deps, executingRequire, execute]; + } +}; + +// ContextualLoader class +// backwards-compatible with previous System.register context argument by exposing .id +function ContextualLoader (loader, key) { + this.loader = loader; + this.key = this.id = key; +} +ContextualLoader.prototype.constructor = function () { + throw new TypeError('Cannot subclass the contextual loader only Reflect.Loader.'); +}; +ContextualLoader.prototype.import = function (key) { + return this.loader.import(key, this.key); +}; +ContextualLoader.prototype.resolve = function (key) { + return this.loader.resolve(key, this.key); +}; +ContextualLoader.prototype.load = function (key) { + return this.loader.load(key, this.key); +}; + +// this is the execution function bound to the Module namespace record +function ensureEvaluate (loader, load, link, registry, state, seen) { + if (load.module) + return load.module; + + if (link.error) + throw link.error; + + if (seen && seen.indexOf(load) !== -1) + return load.linkRecord.moduleObj; + + // for ES loads we always run ensureEvaluate on top-level, so empty seen is passed regardless + // for dynamic loads, we pass seen if also dynamic + var err = doEvaluate(loader, load, link, registry, state, link.setters ? [] : seen || []); + if (err) { + clearLoadErrors(loader, load); + throw err; + } + + return load.module; +} + +function makeDynamicRequire (loader, key, dependencies, dependencyInstantiations, registry, state, seen) { + // we can only require from already-known dependencies + return function (name) { + for (var i = 0; i < dependencies.length; i++) { + if (dependencies[i] === name) { + var depLoad = dependencyInstantiations[i]; + var module; + + if (depLoad instanceof ModuleNamespace) + module = depLoad; + else + module = ensureEvaluate(loader, depLoad, depLoad.linkRecord, registry, state, seen); + + return module.__useDefault ? module.default : module; + } + } + throw new Error('Module ' + name + ' not declared as a System.registerDynamic dependency of ' + key); + }; +} + +// ensures the given es load is evaluated +// returns the error if any +function doEvaluate (loader, load, link, registry, state, seen) { + seen.push(load); + + var err; + + // es modules evaluate dependencies first + // non es modules explicitly call moduleEvaluate through require + if (link.setters) { + var depLoad, depLink; + for (var i = 0; i < link.dependencies.length; i++) { + depLoad = link.dependencyInstantiations[i]; + + if (depLoad instanceof ModuleNamespace) + continue; + + // custom Module returned from instantiate + depLink = depLoad.linkRecord; + if (depLink && seen.indexOf(depLoad) === -1) { + if (depLink.error) + err = depLink.error; + else + // dynamic / declarative boundaries clear the "seen" list + // we just let cross format circular throw as would happen in real implementations + err = doEvaluate(loader, depLoad, depLink, registry, state, depLink.setters ? seen : []); + } + + if (err) + return link.error = LoaderError__Check_error_message_for_loader_stack(err, 'Evaluating ' + load.key); + } + } + + // link.execute won't exist for Module returns from instantiate on top-level load + if (link.execute) { + // ES System.register execute + // "this" is null in ES + if (link.setters) { + err = declarativeExecute(link.execute); + } + // System.registerDynamic execute + // "this" is "exports" in CJS + else { + var module = { id: load.key }; + var moduleObj = link.moduleObj; + Object.defineProperty(module, 'exports', { + configurable: true, + set: function (exports) { + moduleObj.default = exports; + }, + get: function () { + return moduleObj.default; + } + }); + + var require = makeDynamicRequire(loader, load.key, link.dependencies, link.dependencyInstantiations, registry, state, seen); + + // evaluate deps first + if (!link.executingRequire) + for (var i = 0; i < link.dependencies.length; i++) + require(link.dependencies[i]); + + err = dynamicExecute(link.execute, require, moduleObj.default, module); + + // pick up defineProperty calls to module.exports when we can + if (module.exports !== moduleObj.default) + moduleObj.default = module.exports; + + var moduleDefault = moduleObj.default; + + // __esModule flag extension support via lifting + if (moduleDefault && moduleDefault.__esModule) { + if (moduleObj.__useDefault) + delete moduleObj.__useDefault; + for (var p in moduleDefault) { + if (Object.hasOwnProperty.call(moduleDefault, p)) + moduleObj[p] = moduleDefault[p]; + } + moduleObj.__esModule = true; + } + } + } + + if (err) + return link.error = LoaderError__Check_error_message_for_loader_stack(err, 'Evaluating ' + load.key); + + registry[load.key] = load.module = new ModuleNamespace(link.moduleObj); + + // if not an esm module, run importer setters and clear them + // this allows dynamic modules to update themselves into es modules + // as soon as execution has completed + if (!link.setters) { + if (load.importerSetters) + for (var i = 0; i < load.importerSetters.length; i++) + load.importerSetters[i](load.module); + load.importerSetters = undefined; + } + + // dispose link record + load.linkRecord = undefined; +} + +// {} is the closest we can get to call(undefined) +var nullContext = {}; +if (Object.freeze) + Object.freeze(nullContext); + +function declarativeExecute (execute) { + try { + execute.call(nullContext); + } + catch (e) { + return e; + } +} + +function dynamicExecute (execute, require, exports, module) { + try { + var output = execute.call(envGlobal, require, exports, module); + if (output !== undefined) + module.exports = output; + } + catch (e) { + return e; + } +} + +var loader; + +// --> + + + + + + + + + @@ -320,12 +329,5 @@ - - - - - - - diff --git a/vnc_auto.html b/vnc_auto.html index e4fc4676..07eeeeba 100644 --- a/vnc_auto.html +++ b/vnc_auto.html @@ -22,18 +22,33 @@ Remove this if you use the .htaccess --> + + + + + + + + + + + + + + + + + + - - - - - - + + + + + @@ -42,52 +57,19 @@ --> - - - - - -
-
- - - -
- Loading -
- - - - - - -
-
- - Canvas not supported. - -
- - + + + })(); + + + + +
+
+ + + +
+ Loading +
+ + + + + + +
+
+ + Canvas not supported. + +