UNPKG

pxt-ev3

Version:

LEGO MINDSTORMS EV3 for Microsoft MakeCode

1,373 lines (1,282 loc) 111 kB
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ "use strict"; /// <reference path="../node_modules/pxt-core/localtypings/pxteditor.d.ts"/> /// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/> Object.defineProperty(exports, "__esModule", { value: true }); exports.deployCoreAsync = exports.enableWebSerialAsync = exports.canUseWebSerial = exports.initAsync = exports.debug = exports.ev3 = void 0; var HF2 = pxt.HF2; var UF2 = pxtc.UF2; const wrap_1 = require("./wrap"); const dialogs_1 = require("./dialogs"); function debug() { return initHidAsync() .then(w => w.downloadFileAsync("/tmp/dmesg.txt", v => console.log(pxt.Util.uint8ArrayToString(v)))); } exports.debug = debug; // Web Serial API https://wicg.github.io/serial/ // chromium bug https://bugs.chromium.org/p/chromium/issues/detail?id=884928 // Under experimental features in Chrome Desktop 77+ var ParityType; (function (ParityType) { ParityType[ParityType["none"] = 0] = "none"; ParityType[ParityType["even"] = 1] = "even"; ParityType[ParityType["odd"] = 2] = "odd"; ParityType[ParityType["mark"] = 3] = "mark"; ParityType[ParityType["space"] = 4] = "space"; })(ParityType || (ParityType = {})); class WebSerialPackageIO { constructor(port, options) { this.port = port; this.options = options; console.log(`serial: new io`); } async readSerialAsync() { this._reader = this.port.readable.getReader(); let buffer; const reader = this._reader; while (reader === this._reader) { // will change if we recycle the connection const { done, value } = await this._reader.read(); if (!buffer) buffer = value; else { // concat let tmp = new Uint8Array(buffer.length + value.byteLength); tmp.set(buffer, 0); tmp.set(value, buffer.length); buffer = tmp; } if (buffer) { let size = HF2.read16(buffer, 0); if (buffer.length == size + 2) { this.onData(new Uint8Array(buffer)); buffer = undefined; } else { console.warn("Incomplete command " + size); } } } } static isSupported() { return !!navigator.serial; } static async mkPacketIOAsync() { const serial = navigator.serial; if (serial) { try { const requestOptions = {}; const port = await serial.requestPort(requestOptions); let io = WebSerialPackageIO.portIos.filter(i => i.port == port)[0]; if (!io) { const options = { baudRate: 460800, buffersize: 4096 }; io = new WebSerialPackageIO(port, options); WebSerialPackageIO.portIos.push(io); } return io; } catch (e) { console.log(`connection error`, e); } } throw new Error("could not open serial port"); } error(msg) { console.error(msg); throw new Error(lf("error on brick ({0})", msg)); } openAsync() { console.log(`serial: opening port`); if (!!this._reader) return Promise.resolve(); this._reader = undefined; this._writer = undefined; return this.port.open(this.options) .then(() => { this.readSerialAsync(); return Promise.resolve(); }); } async closeAsync() { // don't close port return pxt.U.delay(500); } reconnectAsync() { return this.openAsync(); } disconnectAsync() { return this.closeAsync(); } sendPacketAsync(pkt) { if (!this._writer) this._writer = this.port.writable.getWriter(); return this._writer.write(pkt); } onDeviceConnectionChanged(connect) { throw new Error("onDeviceConnectionChanged not implemented"); } onConnectionChanged() { throw new Error("onConnectionChanged not implemented"); } isConnecting() { throw new Error("isConnecting not implemented"); return false; } isConnected() { throw new Error("isConnected not implemented"); return false; } disposeAsync() { return Promise.reject("disposeAsync not implemented"); } } WebSerialPackageIO.portIos = []; function hf2Async() { const pktIOAsync = useWebSerial ? WebSerialPackageIO.mkPacketIOAsync() : pxt.packetio.mkPacketIOAsync(); return pktIOAsync.then(h => { let w = new wrap_1.Ev3Wrapper(h); exports.ev3 = w; return w.reconnectAsync(true) .then(() => w); }); } let useHID = false; let useWebSerial = false; function initAsync() { if (pxt.U.isNodeJS) { // doesn't seem to work ATM useHID = false; } else { const nodehid = /nodehid/i.test(window.location.href); if (pxt.BrowserUtils.isLocalHost() && pxt.Cloud.localToken && nodehid) useHID = true; } if (WebSerialPackageIO.isSupported()) pxt.tickEvent("webserial.supported"); return Promise.resolve(); } exports.initAsync = initAsync; function canUseWebSerial() { return WebSerialPackageIO.isSupported(); } exports.canUseWebSerial = canUseWebSerial; function enableWebSerialAsync() { initPromise = undefined; useWebSerial = WebSerialPackageIO.isSupported(); useHID = useWebSerial; if (useWebSerial) return initHidAsync().then(() => { }); else return Promise.resolve(); } exports.enableWebSerialAsync = enableWebSerialAsync; async function cleanupAsync() { if (exports.ev3) { console.log('cleanup previous port'); try { await exports.ev3.disconnectAsync(); } catch (e) { } finally { exports.ev3 = undefined; } } } let initPromise; function initHidAsync() { if (initPromise) return initPromise; if (useHID) { initPromise = cleanupAsync() .then(() => hf2Async()) .catch((err) => { console.error(err); initPromise = null; useHID = false; useWebSerial = false; return Promise.reject(err); }); } else { useHID = false; useWebSerial = false; initPromise = Promise.reject(new Error("no HID")); } return initPromise; } // this comes from aux/pxt.lms const fspath = "../prjs/BrkProg_SAVE/"; const rbfTemplate = ` 4c45474f580000006d000100000000001c000000000000000e000000821b038405018130813e8053 74617274696e672e2e2e0084006080XX00448581644886488405018130813e80427965210084000a `; function deployCoreAsync(resp) { let filename = resp.downloadFileBaseName || "pxt"; filename = filename.replace(/^lego-/, ""); let elfPath = fspath + filename + ".elf"; let rbfPath = fspath + filename + ".rbf"; let rbfHex = rbfTemplate .replace(/\s+/g, "") .replace("XX", pxt.U.toHex(pxt.U.stringToUint8Array(elfPath))); let rbfBIN = pxt.U.fromHex(rbfHex); pxt.HF2.write16(rbfBIN, 4, rbfBIN.length); let origElfUF2 = UF2.parseFile(pxt.U.stringToUint8Array(ts.pxtc.decodeBase64(resp.outfiles[pxt.outputName()]))); let mkFile = (ext, data = null) => { let f = UF2.newBlockFile(); f.filename = "Projects/" + filename + ext; if (data) UF2.writeBytes(f, 0, data); return f; }; let elfUF2 = mkFile(".elf"); for (let b of origElfUF2) { UF2.writeBytes(elfUF2, b.targetAddr, b.data); } let r = UF2.concatFiles([elfUF2, mkFile(".rbf", rbfBIN)]); let data = UF2.serializeFile(r); resp.outfiles[pxtc.BINARY_UF2] = btoa(data); let saveUF2Async = () => { if (pxt.commands && pxt.commands.electronDeployAsync) { return pxt.commands.electronDeployAsync(resp); } if (pxt.commands && pxt.commands.saveOnlyAsync) { return pxt.commands.saveOnlyAsync(resp); } return Promise.resolve(); }; if (!useHID) return saveUF2Async(); pxt.tickEvent("webserial.flash"); let w; return initHidAsync() .then(w_ => { w = w_; if (w.isStreaming) pxt.U.userError("please stop the program first"); return w.reconnectAsync(false) .catch(e => { // user easily forgets to stop robot (0, dialogs_1.bluetoothTryAgainAsync)().then(() => w.disconnectAsync()) .then(() => pxt.U.delay(1000)) .then(() => w.reconnectAsync()); // nothing we can do return Promise.reject(e); }); }) .then(() => w.stopAsync()) .then(() => w.rmAsync(elfPath)) .then(() => w.flashAsync(elfPath, UF2.readBytes(origElfUF2, 0, origElfUF2.length * 256))) .then(() => w.flashAsync(rbfPath, rbfBIN)) .then(() => w.runAsync(rbfPath)) .then(() => pxt.U.delay(500)) .then(() => { pxt.tickEvent("webserial.success"); return w.disconnectAsync(); //return Promise.delay(1000).then(() => w.dmesgAsync()) }).catch(e => { pxt.tickEvent("webserial.fail"); useHID = false; useWebSerial = false; // if we failed to initalize, tell the user to retry return Promise.reject(e); }); } exports.deployCoreAsync = deployCoreAsync; },{"./dialogs":2,"./wrap":4}],2:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.showUploadDialogAsync = exports.bluetoothTryAgainAsync = void 0; const React = require("react"); const deploy_1 = require("./deploy"); const extension_1 = require("./extension"); let confirmAsync; function bluetoothTryAgainAsync() { return confirmAsync({ header: lf("Bluetooth download failed..."), jsx: React.createElement("ul", null, React.createElement("li", null, lf("Make sure to stop your program or exit portview on the EV3.")), React.createElement("li", null, lf("Check your battery level.")), React.createElement("li", null, lf("Close EV3 LabView or other MakeCode editor tabs."))), hasCloseIcon: false, hideCancel: true, hideAgree: false, agreeLbl: lf("Try again") }).then(r => { }); } exports.bluetoothTryAgainAsync = bluetoothTryAgainAsync; function enableWebSerialAndCompileAsync() { return (0, deploy_1.enableWebSerialAsync)() .then(() => pxt.U.delay(500)) .then(() => extension_1.projectView.compile()); } let bluetoothDialogShown = false; function explainWebSerialPairingAsync() { if (!confirmAsync || bluetoothDialogShown) return Promise.resolve(); bluetoothDialogShown = true; return confirmAsync({ header: lf("Bluetooth pairing"), hasCloseIcon: false, hideCancel: true, buttons: [{ label: lf("Help"), icon: "question circle", className: "lightgrey", url: "/bluetooth" }], jsx: React.createElement("p", null, lf("You will be prompted to select a serial port."), pxt.BrowserUtils.isWindows() ? lf("Look for 'Standard Serial over Bluetooth link'.") : lf("Loop for 'cu.EV3-SerialPort'."), lf("If you have paired multiple EV3, you might have to try out multiple ports until you find the correct one.")) }).then(() => { }); } function showUploadDialogAsync(fn, url, _confirmAsync) { confirmAsync = _confirmAsync; // https://msdn.microsoft.com/en-us/library/cc848897.aspx // "For security reasons, data URIs are restricted to downloaded resources. // Data URIs cannot be used for navigation, for scripting, or to populate frame or iframe elements" const downloadAgain = !pxt.BrowserUtils.isIE() && !pxt.BrowserUtils.isEdge(); const docUrl = (pxt.appTarget.appTheme.usbDocs ? pxt.appTarget.appTheme.usbDocs : false); const jsx = React.createElement("div", { className: "ui grid stackable" }, React.createElement("div", { className: "column five wide", style: { backgroundColor: "#E2E2E2" } }, React.createElement("div", { className: "ui header" }, lf("First time here?")), React.createElement("strong", { style: { fontSize: "small" } }, lf("You must have version 1.10E or above of the firmware")), React.createElement("div", { style: { justifyContent: "center", display: "flex", padding: "1rem" } }, React.createElement("img", { className: "ui image", src: "/static/download/firmware.png", style: { height: "100px" } })), React.createElement("a", { href: "/troubleshoot", target: "_blank" }, lf("Check your firmware version here and update if needed"))), React.createElement("div", { className: "column eleven wide" }, React.createElement("div", { className: "ui grid" }, React.createElement("div", { className: "row" }, React.createElement("div", { className: "column" }, React.createElement("div", { className: "ui two column grid padded" }, React.createElement("div", { className: "column" }, React.createElement("div", { className: "ui" }, React.createElement("div", { className: "image" }, React.createElement("img", { className: "ui medium rounded image", src: "/static/download/connect.svg", style: { height: "109px", width: "261px", marginBottom: "1rem" } })), React.createElement("div", { className: "content" }, React.createElement("div", { className: "description" }, React.createElement("span", { className: "ui yellow circular label" }, "1"), React.createElement("strong", null, lf("Connect the EV3 to your computer with a USB cable")), React.createElement("br", null), React.createElement("span", { style: { fontSize: "small" } }, lf("Use the miniUSB port on the top of the EV3 Brick")))))), React.createElement("div", { className: "column" }, React.createElement("div", { className: "ui" }, React.createElement("div", { className: "image" }, React.createElement("img", { className: "ui medium rounded image", src: "/static/download/transfer.svg", style: { height: "109px", width: "261px", marginBottom: "1rem" } })), React.createElement("div", { className: "content" }, React.createElement("div", { className: "description" }, React.createElement("span", { className: "ui yellow circular label" }, "2"), React.createElement("strong", null, lf("Move the .uf2 file to the EV3 Brick")), React.createElement("br", null), React.createElement("span", { style: { fontSize: "small" } }, lf("Locate the downloaded .uf2 file and drag it to the EV3 USB drive")))))))))))); return confirmAsync({ header: lf("Download to your EV3"), jsx, hasCloseIcon: true, hideCancel: true, hideAgree: false, agreeLbl: lf("I got it"), className: 'downloaddialog', buttons: [(0, deploy_1.canUseWebSerial)() && { label: lf("Bluetooth"), icon: "bluetooth", className: "bluetooth focused", onclick: () => { pxt.tickEvent("bluetooth.enable"); explainWebSerialPairingAsync() .then(() => enableWebSerialAndCompileAsync()); } }, downloadAgain && { label: fn, icon: "download", className: "lightgrey focused", url, fileName: fn }, docUrl && { label: lf("Help"), icon: "help", className: "lightgrey", url: docUrl }] //timeout: 20000 }).then(() => { }); } exports.showUploadDialogAsync = showUploadDialogAsync; },{"./deploy":1,"./extension":3,"react":12}],3:[function(require,module,exports){ "use strict"; /// <reference path="../node_modules/pxt-core/localtypings/pxtarget.d.ts" /> /// <reference path="../node_modules/pxt-core/built/pxtblocks.d.ts" /> /// <reference path="../node_modules/pxt-core/built/pxtcompiler.d.ts" /> /// <reference path="../node_modules/pxt-core/built/pxtlib.d.ts" /> /// <reference path="../node_modules/pxt-core/localtypings/pxteditor.d.ts"/> /// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/> Object.defineProperty(exports, "__esModule", { value: true }); exports.projectView = void 0; const deploy_1 = require("./deploy"); const dialogs_1 = require("./dialogs"); pxt.editor.initExtensionsAsync = function (opts) { pxt.debug('loading pxt-ev3 target extensions...'); exports.projectView = opts.projectView; const res = { deployAsync: deploy_1.deployCoreAsync, showUploadInstructionsAsync: dialogs_1.showUploadDialogAsync }; (0, deploy_1.initAsync)().catch(e => { // probably no HID - we'll try this again upon deployment }); return Promise.resolve(res); }; },{"./deploy":1,"./dialogs":2}],4:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Ev3Wrapper = void 0; /** * See https://www.lego.com/cdn/cs/set/assets/blt6879b00ae6951482/LEGO_MINDSTORMS_EV3_Communication_Developer_Kit.pdf * https://github.com/mindboards/ev3sources/blob/master/lms2012/lms2012/source/bytecodes.h#L146 */ var HF2 = pxt.HF2; var U = pxt.U; function log(msg) { pxt.log("serial: " + msg); } const runTemplate = "C00882010084XX0060640301606400"; const usbMagic = 0x3d3f; const DIRECT_COMMAND_NO_REPLY = 0x80; class Ev3Wrapper { constructor(io) { this.io = io; this.msgs = new U.PromiseBuffer(); this.cmdSeq = U.randomUint32() & 0xffff; this.lock = new U.PromiseQueue(); this.isStreaming = false; this.dataDump = /talkdbg=1/.test(window.location.href); io.onData = buf => { buf = buf.slice(0, HF2.read16(buf, 0) + 2); if (HF2.read16(buf, 4) == usbMagic) { let code = HF2.read16(buf, 6); let payload = buf.slice(8); if (code == 1) { let str = U.uint8ArrayToString(payload); if (U.isNodeJS) pxt.debug("SERIAL: " + str.replace(/\n+$/, "")); else window.postMessage({ type: 'serial', id: 'n/a', data: str }, "*"); } else pxt.debug("Magic: " + code + ": " + U.toHex(payload)); return; } if (this.dataDump) log("RECV: " + U.toHex(buf)); this.msgs.push(buf); }; } allocCore(addSize, replyType) { let len = 5 + addSize; let buf = new Uint8Array(len); HF2.write16(buf, 0, len - 2); // pktLen HF2.write16(buf, 2, this.cmdSeq++); // msgCount buf[4] = replyType; return buf; } allocSystem(addSize, cmd, replyType = 1) { let buf = this.allocCore(addSize + 1, replyType); buf[5] = cmd; return buf; } allocCustom(code, addSize = 0) { let buf = this.allocCore(1 + 2 + addSize, 0); HF2.write16(buf, 4, usbMagic); HF2.write16(buf, 6, code); return buf; } stopAsync() { return this.isVmAsync() .then(vm => { if (vm) return Promise.resolve(); log(`stopping PXT app`); let buf = this.allocCustom(2); return this.justSendAsync(buf) .then(() => pxt.U.delay(500)); }); } dmesgAsync() { log(`asking for DMESG buffer over serial`); let buf = this.allocCustom(3); return this.justSendAsync(buf); } runAsync(path) { let codeHex = runTemplate.replace("XX", U.toHex(U.stringToUint8Array(path))); let code = U.fromHex(codeHex); let pkt = this.allocCore(2 + code.length, DIRECT_COMMAND_NO_REPLY); HF2.write16(pkt, 5, 0x0800); U.memcpy(pkt, 7, code); log(`run ${path}`); return this.justSendAsync(pkt); } justSendAsync(buf) { return this.lock.enqueue("talk", () => { this.msgs.drain(); if (this.dataDump) log("SEND: " + U.toHex(buf)); return this.io.sendPacketAsync(buf); }); } talkAsync(buf, altResponse = 0) { return this.lock.enqueue("talk", () => { this.msgs.drain(); if (this.dataDump) log("TALK: " + U.toHex(buf)); return this.io.sendPacketAsync(buf) .then(() => this.msgs.shiftAsync(5000)) .then(resp => { if (resp[2] != buf[2] || resp[3] != buf[3]) U.userError("msg count de-sync"); if (buf[4] == 1) { if (altResponse != -1 && resp[5] != buf[5]) U.userError("cmd de-sync"); if (altResponse != -1 && resp[6] != 0 && resp[6] != altResponse) U.userError("cmd error: " + resp[6]); } return resp; }); }); } flashAsync(path, file) { log(`write ${file.length} bytes to ${path}`); let handle = -1; let loopAsync = (pos) => { if (pos >= file.length) return Promise.resolve(); let size = file.length - pos; if (size > 1000) size = 1000; let upl = this.allocSystem(1 + size, 0x93, 0x1); upl[6] = handle; U.memcpy(upl, 6 + 1, file, pos, size); return this.talkAsync(upl, 8) // 8=EOF .then(() => loopAsync(pos + size)); }; let begin = this.allocSystem(4 + path.length + 1, 0x92); HF2.write32(begin, 6, file.length); // fileSize U.memcpy(begin, 10, U.stringToUint8Array(path)); return this.lock.enqueue("file", () => this.talkAsync(begin) .then(resp => { handle = resp[7]; return loopAsync(0); })); } lsAsync(path) { let lsReq = this.allocSystem(2 + path.length + 1, 0x99); HF2.write16(lsReq, 6, 1024); // maxRead U.memcpy(lsReq, 8, U.stringToUint8Array(path)); return this.talkAsync(lsReq, 8) .then(resp => U.uint8ArrayToString(resp.slice(12)).split(/\n/).map(s => { if (!s) return null; let m = /^([A-F0-9]+) ([A-F0-9]+) ([^\/]*)$/.exec(s); if (m) return { md5: m[1], size: parseInt(m[2], 16), name: m[3] }; else return { name: s.replace(/\/$/, "") }; }).filter(v => !!v)); } rmAsync(path) { log(`rm ${path}`); let rmReq = this.allocSystem(path.length + 1, 0x9c); U.memcpy(rmReq, 6, U.stringToUint8Array(path)); return this.talkAsync(rmReq, 5) .then(resp => { }); } isVmAsync() { let path = "/no/such/dir"; let mkdirReq = this.allocSystem(path.length + 1, 0x9b); U.memcpy(mkdirReq, 6, U.stringToUint8Array(path)); return this.talkAsync(mkdirReq, -1) .then(resp => { let isVM = resp[6] == 0x05; log(`${isVM ? "PXT app" : "VM"} running`); return isVM; }); } streamFileOnceAsync(path, cb) { let fileSize = 0; let filePtr = 0; let handle = -1; let resp = (buf) => { if (buf[6] == 2) { // handle not ready - file is missing this.isStreaming = false; return Promise.resolve(); } if (buf[6] != 0 && buf[6] != 8) U.userError("bad response when streaming file: " + buf[6] + " " + U.toHex(buf)); this.isStreaming = true; fileSize = HF2.read32(buf, 7); if (handle == -1) { handle = buf[11]; log(`stream on, handle=${handle}`); } let data = buf.slice(12); filePtr += data.length; if (data.length > 0) cb(data); if (buf[6] == 8) { // end of file this.isStreaming = false; return this.rmAsync(path); } let contFileReq = this.allocSystem(1 + 2, 0x97); HF2.write16(contFileReq, 7, 1000); // maxRead contFileReq[6] = handle; return pxt.U.delay(data.length > 0 ? 0 : 500) .then(() => this.talkAsync(contFileReq, -1)) .then(resp); }; let getFileReq = this.allocSystem(2 + path.length + 1, 0x96); HF2.write16(getFileReq, 6, 1000); // maxRead U.memcpy(getFileReq, 8, U.stringToUint8Array(path)); return this.talkAsync(getFileReq, -1).then(resp); } streamFileAsync(path, cb) { let loop = () => this.lock.enqueue("file", () => this.streamFileOnceAsync(path, cb)) .then(() => pxt.U.delay(500)) .then(loop); return loop(); } downloadFileAsync(path, cb) { return this.lock.enqueue("file", () => this.streamFileOnceAsync(path, cb)); } initAsync() { return Promise.resolve(); } resetState() { } reconnectAsync(first = false) { this.resetState(); if (first) return this.initAsync(); log(`reconnect`); return this.io.reconnectAsync() .then(() => this.initAsync()); } disconnectAsync() { log(`disconnect`); return this.io.disconnectAsync(); } } exports.Ev3Wrapper = Ev3Wrapper; },{}],5:[function(require,module,exports){ /* object-assign (c) Sindre Sorhus @license MIT */ 'use strict'; /* eslint-disable no-unused-vars */ var getOwnPropertySymbols = Object.getOwnPropertySymbols; var hasOwnProperty = Object.prototype.hasOwnProperty; var propIsEnumerable = Object.prototype.propertyIsEnumerable; function toObject(val) { if (val === null || val === undefined) { throw new TypeError('Object.assign cannot be called with null or undefined'); } return Object(val); } function shouldUseNative() { try { if (!Object.assign) { return false; } // Detect buggy property enumeration order in older V8 versions. // https://bugs.chromium.org/p/v8/issues/detail?id=4118 var test1 = new String('abc'); // eslint-disable-line no-new-wrappers test1[5] = 'de'; if (Object.getOwnPropertyNames(test1)[0] === '5') { return false; } // https://bugs.chromium.org/p/v8/issues/detail?id=3056 var test2 = {}; for (var i = 0; i < 10; i++) { test2['_' + String.fromCharCode(i)] = i; } var order2 = Object.getOwnPropertyNames(test2).map(function (n) { return test2[n]; }); if (order2.join('') !== '0123456789') { return false; } // https://bugs.chromium.org/p/v8/issues/detail?id=3056 var test3 = {}; 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { test3[letter] = letter; }); if (Object.keys(Object.assign({}, test3)).join('') !== 'abcdefghijklmnopqrst') { return false; } return true; } catch (err) { // We don't expect any of the above to throw, but better to be safe. return false; } } module.exports = shouldUseNative() ? Object.assign : function (target, source) { var from; var to = toObject(target); var symbols; for (var s = 1; s < arguments.length; s++) { from = Object(arguments[s]); for (var key in from) { if (hasOwnProperty.call(from, key)) { to[key] = from[key]; } } if (getOwnPropertySymbols) { symbols = getOwnPropertySymbols(from); for (var i = 0; i < symbols.length; i++) { if (propIsEnumerable.call(from, symbols[i])) { to[symbols[i]] = from[symbols[i]]; } } } } return to; }; },{}],6:[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.prependListener = noop; process.prependOnceListener = noop; process.listeners = function (name) { return [] } 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; }; },{}],7:[function(require,module,exports){ (function (process){(function (){ /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; var printWarning = function() {}; if (process.env.NODE_ENV !== 'production') { var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret'); var loggedTypeFailures = {}; var has = require('./lib/has'); printWarning = function(text) { var message = 'Warning: ' + text; if (typeof console !== 'undefined') { console.error(message); } try { // --- Welcome to debugging React --- // This error was thrown as a convenience so that you can use this stack // to find the callsite that caused this warning to fire. throw new Error(message); } catch (x) { /**/ } }; } /** * Assert that the values match with the type specs. * Error messages are memorized and will only be shown once. * * @param {object} typeSpecs Map of name to a ReactPropType * @param {object} values Runtime values that need to be type-checked * @param {string} location e.g. "prop", "context", "child context" * @param {string} componentName Name of the component for error messages. * @param {?Function} getStack Returns the component stack. * @private */ function checkPropTypes(typeSpecs, values, location, componentName, getStack) { if (process.env.NODE_ENV !== 'production') { for (var typeSpecName in typeSpecs) { if (has(typeSpecs, typeSpecName)) { var error; // Prop type validation may throw. In case they do, we don't want to // fail the render phase where it didn't fail before. So we log it. // After these have been cleaned up, we'll let them throw. try { // This is intentionally an invariant that gets caught. It's the same // behavior as without this statement except with a better message. if (typeof typeSpecs[typeSpecName] !== 'function') { var err = Error( (componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.' ); err.name = 'Invariant Violation'; throw err; } error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret); } catch (ex) { error = ex; } if (error && !(error instanceof Error)) { printWarning( (componentName || 'React class') + ': type specification of ' + location + ' `' + typeSpecName + '` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a ' + typeof error + '. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).' ); } if (error instanceof Error && !(error.message in loggedTypeFailures)) { // Only monitor this failure once because there tends to be a lot of the // same error. loggedTypeFailures[error.message] = true; var stack = getStack ? getStack() : ''; printWarning( 'Failed ' + location + ' type: ' + error.message + (stack != null ? stack : '') ); } } } } } /** * Resets warning cache when testing. * * @private */ checkPropTypes.resetWarningCache = function() { if (process.env.NODE_ENV !== 'production') { loggedTypeFailures = {}; } } module.exports = checkPropTypes; }).call(this)}).call(this,require('_process')) },{"./lib/ReactPropTypesSecret":8,"./lib/has":9,"_process":6}],8:[function(require,module,exports){ /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; module.exports = ReactPropTypesSecret; },{}],9:[function(require,module,exports){ module.exports = Function.call.bind(Object.prototype.hasOwnProperty); },{}],10:[function(require,module,exports){ (function (process){(function (){ /** @license React v16.8.3 * react.development.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; if (process.env.NODE_ENV !== "production") { (function() { 'use strict'; var _assign = require('object-assign'); var checkPropTypes = require('prop-types/checkPropTypes'); // TODO: this is special because it gets imported during build. var ReactVersion = '16.8.3'; // The Symbol used to tag the ReactElement-like types. If there is no native Symbol // nor polyfill, then a plain number is used for performance. var hasSymbol = typeof Symbol === 'function' && Symbol.for; var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7; var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca; var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb; var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc; var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2; var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd; var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace; var REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf; var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0; var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for('react.suspense') : 0xead1; var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3; var REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4; var MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; var FAUX_ITERATOR_SYMBOL = '@@iterator'; function getIteratorFn(maybeIterable) { if (maybeIterable === null || typeof maybeIterable !== 'object') { return null; } var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]; if (typeof maybeIterator === 'function') { return maybeIterator; } return null; } /** * Use invariant() to assert state which your program assumes to be true. * * Provide sprintf-style format (only %s is supported) and arguments * to provide information about what broke and what you were * expecting. * * The invariant message will be stripped in production, but the invariant * will remain to ensure logic does not differ in production. */ var validateFormat = function () {}; { validateFormat = function (format) { if (format === undefined) { throw new Error('invariant requires an error message argument'); } }; } function invariant(condition, format, a, b, c, d, e, f) { validateFormat(format); if (!condition) { var error = void 0; if (format === undefined) { error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); } else { var args = [a, b, c, d, e, f]; var argIndex = 0; error = new Error(format.replace(/%s/g, function () { return args[argIndex++]; })); error.name = 'Invariant Violation'; } error.framesToPop = 1; // we don't care about invariant's own frame throw error; } } // Relying on the `invariant()` implementation lets us // preserve the format and params in the www builds. /** * Forked from fbjs/warning: * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js * * Only change is we use console.warn instead of console.error, * and do nothing when 'console' is not supported. * This really simplifies the code. * --- * Similar to invariant but only logs a warning if the condition is not met. * This can be used to log issues in development environments in critical * paths. Removing the logging code for production environments will keep the * same logic and follow the same code paths. */ var lowPriorityWarning = function () {}; { var printWarning = function (format) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } var argIndex = 0; var message = 'Warning: ' + format.replace(/%s/g, function () { return args[argIndex++]; }); if (typeof console !== 'undefined') { console.warn(message); } try { // --- Welcome to debugging React --- // This error was thrown as a convenience so that you can use this stack // to find the callsite that caused this warning to fire. throw new Error(message); } catch (x) {} }; lowPriorityWarning = function (condition, format) { if (format === undefined) { throw new Error('`lowPriorityWarning(condition, format, ...args)` requires a warning ' + 'message argument'); } if (!condition) { for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { args[_key2 - 2] = arguments[_key2]; } printWarning.apply(undefined, [format].concat(args)); } }; } var lowPriorityWarning$1 = lowPriorityWarning; /** * Similar to invariant but only logs a warning if the condition is not met. * This can be used to log issues in development environments in critical * paths. Removing the logging code for production environments will keep the * same logic and follow the same code paths. */ var warningWithoutStack = function () {}; { warningWithoutStack = function (condition, format) { for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; } if (format === undefined) { throw new Error('`warningWithoutStack(condition, format, ...args)` requires a warning ' + 'message argument'); } if (args.length > 8) { // Check before the condition to catch violations early. throw new Error('warningWithoutStack() currently supports at most 8 arguments.'); } if (condition) { return; } if (typeof console !== 'undefined') { var argsWithFormat = args.map(function (item) { return '' + item; }); argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it // breaks IE9: https://github.com/facebook/react/issues/13610 Function.prototype.apply.call(console.error, console, argsWithFormat); } try { // --- Welcome to debugging React --- // This error was thrown as a convenience so that you can use this stack // to find the callsite that caused this warning to fire. var argIndex = 0; var message = 'Warning: ' + format.replace(/%s/g, function () { return args[argIndex++]; }); throw new Error(message); } catch (x) {} }; } var warningWithoutStack$1 = warningWithoutStack; var didWarnStateUpdateForUnmountedComponent = {}; function warnNoop(publicInstance, callerName) { { var _constructor = publicInstance.constructor; var componentName = _constructor && (_constructor.displayName || _constructor.name) || 'ReactClass'; var warningKey = componentName + '.' + callerName; if (didWarnStateUpdateForUnmountedComponent[warningKey]) { return; } warningWithoutStack$1(false, "Can't call %s on a component that is not yet mounted. " + 'This is a no-op, but it might indicate a bug in your application. ' + 'Instead, assign to `this.state` directly or define a `state = {};` ' + 'class property with the desired state in the %s component.', callerName, componentName); didWarnStateUpdateForUnmountedComponent[warningKey] = true; } } /** * This is the abstract API for an update queue. */ var ReactNoopUpdateQueue = { /** * Checks whether or not this composite component is mounted. * @param {ReactClass} publicInstance The instance we want to test. * @return {boolean} True if mounted, false otherwise. * @protected * @final */ isMounted: function (publicInstance) { return false; }, /** * Forces an update. This should only be invoked when it is known with * certainty that we are **not** in a DOM transaction. * * You may want to call this when you know that some deeper aspect of the * component's state has changed but `setState` was not called. * * This will not invoke `shouldComponentUpdate`, but it will invoke * `componentWillUpdate` and `componentDidUpdate`. * * @param {ReactClass} publicInstance The instance that should rerender. * @param {?function} callback Called after component is updated. * @param {?string} callerName name of the calling function in the public API. * @internal */ enqueueForceUpdate: function (publicInstance, callback, callerName) { warnNoop(publicInstance, 'forceUpdate'); }, /** * Replaces all of the state. Always use this or `setState` to mutate state. * You should treat `this.state` as immutable. * * There is no guarantee that `this.state` will be immediately updated, so * accessing `this.state` after calling this method may return the old value. * * @param {ReactClass} publicInstance The instance that should rerender. * @param {object} completeState Next state. * @param {?function} callback Called after component is updated. * @param {?string} callerName name of the calling function in the public API. * @internal */ enqueueReplaceState: function (publicInstance, completeState, callback, callerName) { warnNoop(publicInstance, 'replaceState'); }, /** * Sets a subset of the state. This only exists because _pendingState is * internal. This provides a merging strategy that is not available to deep * properties which is confusing. TODO: Expose pendingState or don't use it * during the merge. * * @param {ReactClass} publicInstance The instance that should rerender. * @param {object} partialState Next partial state to be merged with state. * @param {?function} callback Called after component is updated. * @param {?string} Name of the calling function in the publ