pxt-ev3
Version:
LEGO MINDSTORMS EV3 for Microsoft MakeCode
1,373 lines (1,282 loc) • 111 kB
JavaScript
(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