Switch to use @commaai/pandajs for webusb communications
Squashed commit of the following: commit c5d1f64a7072d1eeee6cd52b02aed69515275e22 Author: Chris Vickery <chrisinajar@gmail.com> Date: Sun Mar 18 17:45:14 2018 -0700 Change to scoped pandajs commit 4ebc842bfc957b32eb694b74517bf3aedf5194c7 Author: Chris Vickery <chrisinajar@gmail.com> Date: Sun Mar 18 17:37:09 2018 -0700 Use pandajs lib to communicate with panda modulesmain
parent
f028c332f3
commit
e8c8b901c1
|
@ -0,0 +1,12 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
|
@ -4,6 +4,7 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"homepage": "https://community.comma.ai/cabana",
|
"homepage": "https://community.comma.ai/cabana",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@commaai/pandajs": "^0.1.0",
|
||||||
"aphrodite": "^1.2.1",
|
"aphrodite": "^1.2.1",
|
||||||
"babel-preset-stage-0": "^6.24.1",
|
"babel-preset-stage-0": "^6.24.1",
|
||||||
"base64-inline-loader": "^1.1.0",
|
"base64-inline-loader": "^1.1.0",
|
||||||
|
@ -46,7 +47,8 @@
|
||||||
"socket.io-client": "^2.0.3",
|
"socket.io-client": "^2.0.3",
|
||||||
"streamsaver": "^1.0.1",
|
"streamsaver": "^1.0.1",
|
||||||
"vega": "3.0.0",
|
"vega": "3.0.0",
|
||||||
"vega-tooltip": "^0.4.0"
|
"vega-tooltip": "^0.4.0",
|
||||||
|
"xtend": "^4.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"connect-history-api-fallback": "1.3.0",
|
"connect-history-api-fallback": "1.3.0",
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import Moment from "moment";
|
import Moment from "moment";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
|
import cx from "classnames";
|
||||||
|
import { createWriteStream } from "streamsaver";
|
||||||
|
import Panda from "@commaai/pandajs";
|
||||||
|
|
||||||
import { USE_UNLOGGER, PART_SEGMENT_LENGTH, STREAMING_WINDOW } from "./config";
|
import { USE_UNLOGGER, PART_SEGMENT_LENGTH, STREAMING_WINDOW } from "./config";
|
||||||
import * as GithubAuth from "./api/github-auth";
|
import * as GithubAuth from "./api/github-auth";
|
||||||
import cx from "classnames";
|
|
||||||
import { createWriteStream } from "streamsaver";
|
|
||||||
|
|
||||||
import auth from "./api/comma-auth";
|
import auth from "./api/comma-auth";
|
||||||
import DBC from "./models/can/dbc";
|
import DBC from "./models/can/dbc";
|
||||||
|
@ -25,7 +26,6 @@ import {
|
||||||
} from "./api/localstorage";
|
} from "./api/localstorage";
|
||||||
import OpenDbc from "./api/OpenDbc";
|
import OpenDbc from "./api/OpenDbc";
|
||||||
import UnloggerClient from "./api/unlogger";
|
import UnloggerClient from "./api/unlogger";
|
||||||
import PandaReader from "./api/panda-reader";
|
|
||||||
import * as ObjectUtils from "./utils/object";
|
import * as ObjectUtils from "./utils/object";
|
||||||
import { hash } from "./utils/string";
|
import { hash } from "./utils/string";
|
||||||
|
|
||||||
|
@ -86,8 +86,6 @@ export default class CanExplorer extends Component {
|
||||||
this.unloggerClient = new UnloggerClient();
|
this.unloggerClient = new UnloggerClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pandaReader = new PandaReader();
|
|
||||||
|
|
||||||
this.showOnboarding = this.showOnboarding.bind(this);
|
this.showOnboarding = this.showOnboarding.bind(this);
|
||||||
this.hideOnboarding = this.hideOnboarding.bind(this);
|
this.hideOnboarding = this.hideOnboarding.bind(this);
|
||||||
this.showLoadDbc = this.showLoadDbc.bind(this);
|
this.showLoadDbc = this.showLoadDbc.bind(this);
|
||||||
|
@ -118,6 +116,9 @@ export default class CanExplorer extends Component {
|
||||||
this.lastMessageEntriesById = this.lastMessageEntriesById.bind(this);
|
this.lastMessageEntriesById = this.lastMessageEntriesById.bind(this);
|
||||||
this.githubSignOut = this.githubSignOut.bind(this);
|
this.githubSignOut = this.githubSignOut.bind(this);
|
||||||
this.downloadLogAsCSV = this.downloadLogAsCSV.bind(this);
|
this.downloadLogAsCSV = this.downloadLogAsCSV.bind(this);
|
||||||
|
|
||||||
|
this.pandaReader = new Panda();
|
||||||
|
this.pandaReader.onMessage(this.processStreamedCanMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
|
@ -754,34 +755,33 @@ export default class CanExplorer extends Component {
|
||||||
this._onStreamedCanMessagesProcessed(e.data);
|
this._onStreamedCanMessagesProcessed(e.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePandaConnect(e) {
|
async handlePandaConnect(e) {
|
||||||
this.setState({ attemptingPandaConnection: true, live: true });
|
this.setState({ attemptingPandaConnection: true, live: true });
|
||||||
|
|
||||||
const persistedDbc = fetchPersistedDbc("live");
|
const persistedDbc = fetchPersistedDbc("live");
|
||||||
if (persistedDbc) {
|
if (persistedDbc) {
|
||||||
const { dbc, dbcText } = persistedDbc;
|
let { dbc, dbcText } = persistedDbc;
|
||||||
this.setState({ dbc, dbcText });
|
this.setState({ dbc, dbcText });
|
||||||
}
|
}
|
||||||
this.canStreamerWorker = new CanStreamerWorker();
|
this.canStreamerWorker = new CanStreamerWorker();
|
||||||
this.canStreamerWorker.onmessage = this.onStreamedCanMessagesProcessed;
|
this.canStreamerWorker.onmessage = this.onStreamedCanMessagesProcessed;
|
||||||
this.pandaReader.setOnMessagesReceivedCallback(
|
|
||||||
this.processStreamedCanMessages
|
// if any errors go off during connection, mark as not trying to connect anymore...
|
||||||
|
let unlisten = this.pandaReader.onError(err =>
|
||||||
|
this.setState({ attemptingPandaConnection: false })
|
||||||
);
|
);
|
||||||
this.pandaReader
|
try {
|
||||||
.connect()
|
await this.pandaReader.start();
|
||||||
.then(() => {
|
this.setState({
|
||||||
this.pandaReader.readLoop();
|
showOnboarding: false,
|
||||||
this.setState({ attemptingPandaConnection: false });
|
showLoadDbc: true
|
||||||
this.setState({ showOnboarding: false });
|
|
||||||
this.setState({ showLoadDbc: true });
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log(err);
|
|
||||||
this.setState({ attemptingPandaConnection: false });
|
|
||||||
});
|
});
|
||||||
|
} catch (e) {}
|
||||||
|
this.setState({ attemptingPandaConnection: false });
|
||||||
|
unlisten();
|
||||||
}
|
}
|
||||||
|
|
||||||
githubSignOut(e) {
|
githubSignOut(e, dataArray) {
|
||||||
unpersistGithubAuthToken();
|
unpersistGithubAuthToken();
|
||||||
this.setState({ isGithubAuthenticated: false });
|
this.setState({ isGithubAuthenticated: false });
|
||||||
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
import Panda from "../../api/panda";
|
|
||||||
|
|
||||||
function arrayBufferFromHex(hex) {
|
|
||||||
const buffer = Buffer.from(hex, "hex");
|
|
||||||
const arrayBuffer = new ArrayBuffer(buffer.length);
|
|
||||||
const view = new Uint8Array(arrayBuffer);
|
|
||||||
for (let i = 0; i < buffer.length; i++) {
|
|
||||||
view[i] = buffer[i];
|
|
||||||
}
|
|
||||||
return arrayBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
test("parseCanBuffer correctly parses a message", () => {
|
|
||||||
const panda = new Panda();
|
|
||||||
// 16 byte buffer
|
|
||||||
|
|
||||||
const arrayBuffer = arrayBufferFromHex("abababababababababababababababab");
|
|
||||||
|
|
||||||
const messages = panda.parseCanBuffer(arrayBuffer);
|
|
||||||
expect(messages.length).toEqual(1);
|
|
||||||
expect(messages[0]).toEqual([1373, 43947, "abababababababab", 10]);
|
|
||||||
});
|
|
|
@ -1,10 +1,16 @@
|
||||||
import Panda from "./panda";
|
import CloudLog from "../logging/CloudLog";
|
||||||
|
import Panda from "pandajs";
|
||||||
|
|
||||||
|
///@TODO move this file into pandajs and fix up the API
|
||||||
|
// it should handle read loops, event management, pausing, unpausing, etc...
|
||||||
|
|
||||||
export default class PandaReader {
|
export default class PandaReader {
|
||||||
static ERROR_NO_DEVICE_SELECTED = 8;
|
static ERROR_NO_DEVICE_SELECTED = 8;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.panda = new Panda();
|
this.panda = new Panda();
|
||||||
|
this.panda.onError(CloudLog.error.bind(CloudLog));
|
||||||
|
|
||||||
this.isReading = false;
|
this.isReading = false;
|
||||||
this.onMessagesReceived = () => {};
|
this.onMessagesReceived = () => {};
|
||||||
this.callbackQueue = [];
|
this.callbackQueue = [];
|
||||||
|
|
110
src/api/panda.js
110
src/api/panda.js
|
@ -1,110 +0,0 @@
|
||||||
import CloudLog from "../logging/CloudLog";
|
|
||||||
|
|
||||||
const PANDA_VENDOR_ID = 0xbbaa;
|
|
||||||
//const PANDA_PRODUCT_ID = 0xddcc;
|
|
||||||
|
|
||||||
const BUFFER_SIZE = 0x10 * 256;
|
|
||||||
|
|
||||||
export default class Panda {
|
|
||||||
constructor() {
|
|
||||||
this.device = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
connect() {
|
|
||||||
// Must be called via a mouse click handler, per Chrome restrictions.
|
|
||||||
return navigator.usb
|
|
||||||
.requestDevice({ filters: [{ vendorId: PANDA_VENDOR_ID }] })
|
|
||||||
.then(device => {
|
|
||||||
this.device = device;
|
|
||||||
return device.open();
|
|
||||||
})
|
|
||||||
.then(() => this.device.selectConfiguration(1))
|
|
||||||
.then(() => this.device.claimInterface(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
async health() {
|
|
||||||
const controlParams = {
|
|
||||||
requestType: "vendor",
|
|
||||||
recipient: "device",
|
|
||||||
request: 0xd2,
|
|
||||||
value: 0,
|
|
||||||
index: 0
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
return await this.device.controlTransferIn(controlParams, 13);
|
|
||||||
} catch (err) {
|
|
||||||
CloudLog.error({ event: "Panda.health failed", error: err });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parseCanBuffer(buffer) {
|
|
||||||
const messages = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < buffer.byteLength; i += 0x10) {
|
|
||||||
const dat = buffer.slice(i, i + 0x10);
|
|
||||||
|
|
||||||
const datView = Buffer.from(dat);
|
|
||||||
const f1 = datView.readInt32LE(0),
|
|
||||||
f2 = datView.readInt32LE(4);
|
|
||||||
|
|
||||||
const address = f1 >>> 21;
|
|
||||||
|
|
||||||
const busTime = f2 >>> 16;
|
|
||||||
const data = new Buffer(dat.slice(8, 8 + (f2 & 0xf)));
|
|
||||||
const source = (f2 >> 4) & 0xf & 0xff;
|
|
||||||
|
|
||||||
messages.push([
|
|
||||||
address,
|
|
||||||
busTime,
|
|
||||||
data.toString("hex").padEnd(16, "0"),
|
|
||||||
source
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
async mockCanRecv() {
|
|
||||||
const promise = new Promise(resolve =>
|
|
||||||
setTimeout(
|
|
||||||
() =>
|
|
||||||
resolve({
|
|
||||||
time: performance.now() / 1000,
|
|
||||||
canMessages: [[0, Math.random() * 65000, "".padEnd(16, "0"), 0]]
|
|
||||||
}),
|
|
||||||
100
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return await promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
async canRecv() {
|
|
||||||
let result = null,
|
|
||||||
receiptTime = null,
|
|
||||||
attempts = 0;
|
|
||||||
|
|
||||||
while (result === null) {
|
|
||||||
try {
|
|
||||||
result = await this.device.transferIn(1, BUFFER_SIZE);
|
|
||||||
receiptTime = performance.now() / 1000;
|
|
||||||
} catch (err) {
|
|
||||||
console.warn("can_recv failed, retrying");
|
|
||||||
attempts = Math.min(++attempts, 10);
|
|
||||||
await wait(attempts * 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await wait(0);
|
|
||||||
|
|
||||||
return {
|
|
||||||
time: receiptTime,
|
|
||||||
canMessages: this.parseCanBuffer(result.data.buffer)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function wait(ms) {
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
setTimeout(resolve, ms);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -6,17 +6,18 @@ function findMaxByteStateChangeCount(messages) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function addCanMessage(
|
function addCanMessage(
|
||||||
[address, busTime, data, source],
|
canMessage,
|
||||||
dbc,
|
dbc,
|
||||||
canStartTime,
|
canStartTime,
|
||||||
messages,
|
messages,
|
||||||
prevMsgEntries,
|
prevMsgEntries,
|
||||||
byteStateChangeCountsByMessage
|
byteStateChangeCountsByMessage
|
||||||
) {
|
) {
|
||||||
var id = source + ":" + address.toString(16);
|
var { address, busTime, data, bus } = canMessage;
|
||||||
|
var id = bus + ":" + address.toString(16);
|
||||||
|
|
||||||
if (messages[id] === undefined)
|
if (messages[id] === undefined)
|
||||||
messages[id] = createMessageSpec(dbc, address, id, source);
|
messages[id] = createMessageSpec(dbc, address, id, bus);
|
||||||
|
|
||||||
const prevMsgEntry =
|
const prevMsgEntry =
|
||||||
messages[id].entries.length > 0
|
messages[id].entries.length > 0
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
/* eslint-disable no-restricted-globals */
|
/* eslint-disable no-restricted-globals */
|
||||||
import DBC from "../models/can/dbc";
|
import DBC from "../models/can/dbc";
|
||||||
import DbcUtils from "../utils/dbc";
|
import DbcUtils from "../utils/dbc";
|
||||||
|
import extend from "xtend";
|
||||||
|
|
||||||
function processStreamedCanMessages(
|
function processStreamedCanMessages(
|
||||||
newCanMessages,
|
newCanMessages,
|
||||||
|
@ -30,7 +31,8 @@ function processStreamedCanMessages(
|
||||||
let busTimeSum = 0;
|
let busTimeSum = 0;
|
||||||
|
|
||||||
for (let i = 0; i < canMessages.length; i++) {
|
for (let i = 0; i < canMessages.length; i++) {
|
||||||
let [address, busTime, data, source] = canMessages[i];
|
let { address, busTime, data, bus } = canMessages[i];
|
||||||
|
|
||||||
let prevBusTime;
|
let prevBusTime;
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
if (lastBusTime === null) {
|
if (lastBusTime === null) {
|
||||||
|
@ -39,7 +41,7 @@ function processStreamedCanMessages(
|
||||||
prevBusTime = lastBusTime;
|
prevBusTime = lastBusTime;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
prevBusTime = canMessages[i - 1][1];
|
prevBusTime = canMessages[i - 1].busTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (busTime >= prevBusTime) {
|
if (busTime >= prevBusTime) {
|
||||||
|
@ -47,11 +49,11 @@ function processStreamedCanMessages(
|
||||||
} else {
|
} else {
|
||||||
busTimeSum += 0x10000 - prevBusTime + busTime;
|
busTimeSum += 0x10000 - prevBusTime + busTime;
|
||||||
}
|
}
|
||||||
const message = [...canMessages[i]];
|
const message = extend(canMessages[i]);
|
||||||
message[1] = time + busTimeSum / 500000.0;
|
message.busTime = time + busTimeSum / 500000.0;
|
||||||
|
|
||||||
if (firstCanTime === 0) {
|
if (firstCanTime === 0) {
|
||||||
firstCanTime = message[1];
|
firstCanTime = message.busTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
const msgEntry = DbcUtils.addCanMessage(
|
const msgEntry = DbcUtils.addCanMessage(
|
||||||
|
@ -67,7 +69,7 @@ function processStreamedCanMessages(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastBusTime = canMessages[canMessages.length - 1][1];
|
lastBusTime = canMessages[canMessages.length - 1].busTime;
|
||||||
const newMaxByteStateChangeCount = DbcUtils.findMaxByteStateChangeCount(
|
const newMaxByteStateChangeCount = DbcUtils.findMaxByteStateChangeCount(
|
||||||
messages
|
messages
|
||||||
);
|
);
|
||||||
|
|
64
yarn.lock
64
yarn.lock
|
@ -17,6 +17,18 @@
|
||||||
lodash "^4.2.0"
|
lodash "^4.2.0"
|
||||||
to-fast-properties "^2.0.0"
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
|
"@commaai/pandajs@^0.1.0":
|
||||||
|
version "0.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@commaai/pandajs/-/pandajs-0.1.0.tgz#55e7fcb880f22f2f2d814dd2437cddb88f4d69ce"
|
||||||
|
dependencies:
|
||||||
|
ap "^0.2.0"
|
||||||
|
can-message "^0.1.0"
|
||||||
|
is-browser "^2.0.1"
|
||||||
|
performance-now "^2.1.0"
|
||||||
|
raf "^3.4.0"
|
||||||
|
thyming "^0.1.1"
|
||||||
|
weakmap-event "^2.0.7"
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/node@*":
|
||||||
version "8.5.1"
|
version "8.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.5.1.tgz#4ec3020bcdfe2abffeef9ba3fbf26fca097514b5"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.5.1.tgz#4ec3020bcdfe2abffeef9ba3fbf26fca097514b5"
|
||||||
|
@ -157,6 +169,10 @@ anymatch@^1.3.0:
|
||||||
micromatch "^2.1.5"
|
micromatch "^2.1.5"
|
||||||
normalize-path "^2.0.0"
|
normalize-path "^2.0.0"
|
||||||
|
|
||||||
|
ap@^0.2.0:
|
||||||
|
version "0.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110"
|
||||||
|
|
||||||
aphrodite@^1.2.1:
|
aphrodite@^1.2.1:
|
||||||
version "1.2.5"
|
version "1.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/aphrodite/-/aphrodite-1.2.5.tgz#8358c36c80bb03aee9b97165aaa70186225b4983"
|
resolved "https://registry.yarnpkg.com/aphrodite/-/aphrodite-1.2.5.tgz#8358c36c80bb03aee9b97165aaa70186225b4983"
|
||||||
|
@ -208,6 +224,10 @@ arr-flatten@^1.0.1:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
|
resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
|
||||||
|
|
||||||
|
array-differ@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031"
|
||||||
|
|
||||||
array-equal@^1.0.0:
|
array-equal@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
|
resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
|
||||||
|
@ -281,6 +301,10 @@ asn1@~0.2.3:
|
||||||
version "0.2.3"
|
version "0.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
|
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
|
||||||
|
|
||||||
|
assert-function@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/assert-function/-/assert-function-1.0.0.tgz#aeb2ad0fe00888b41254a8e3934a562968d77905"
|
||||||
|
|
||||||
assert-plus@1.0.0, assert-plus@^1.0.0:
|
assert-plus@1.0.0, assert-plus@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
|
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
|
||||||
|
@ -1462,6 +1486,10 @@ camelcase@^4.1.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
||||||
|
|
||||||
|
can-message@^0.1.0:
|
||||||
|
version "0.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/can-message/-/can-message-0.1.0.tgz#288862d67a0dbd85dbc56da0a44f6e2bf1dfb030"
|
||||||
|
|
||||||
caniuse-api@^1.5.2:
|
caniuse-api@^1.5.2:
|
||||||
version "1.6.1"
|
version "1.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c"
|
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c"
|
||||||
|
@ -3395,6 +3423,10 @@ getpass@^0.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "^1.0.0"
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
|
geval@~2.2.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/geval/-/geval-2.2.0.tgz#5622b10a28028284198afe351f6b417042c33dda"
|
||||||
|
|
||||||
github-api@^3.0.0:
|
github-api@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/github-api/-/github-api-3.0.0.tgz#2832f98d0d3a83f1485e2db32c9259e4b9c40a75"
|
resolved "https://registry.yarnpkg.com/github-api/-/github-api-3.0.0.tgz#2832f98d0d3a83f1485e2db32c9259e4b9c40a75"
|
||||||
|
@ -3978,6 +4010,10 @@ is-binary-path@^1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
binary-extensions "^1.0.0"
|
binary-extensions "^1.0.0"
|
||||||
|
|
||||||
|
is-browser@^2.0.1:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-browser/-/is-browser-2.0.1.tgz#8bf0baf799a9c62fd9de5bcee4cf3397c3e7529a"
|
||||||
|
|
||||||
is-buffer@^1.1.5:
|
is-buffer@^1.1.5:
|
||||||
version "1.1.6"
|
version "1.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||||
|
@ -4648,6 +4684,13 @@ jsx-ast-utils@^2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
array-includes "^3.0.3"
|
array-includes "^3.0.3"
|
||||||
|
|
||||||
|
key-difference@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/key-difference/-/key-difference-1.0.0.tgz#7ede6f69bfff08010b5612885303b688a30008cc"
|
||||||
|
dependencies:
|
||||||
|
array-differ "~1.0.0"
|
||||||
|
xtend "~4.0.0"
|
||||||
|
|
||||||
killable@^1.0.0:
|
killable@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.0.tgz#da8b84bd47de5395878f95d64d02f2449fe05e6b"
|
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.0.tgz#da8b84bd47de5395878f95d64d02f2449fe05e6b"
|
||||||
|
@ -7437,6 +7480,12 @@ thunky@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/thunky/-/thunky-0.1.0.tgz#bf30146824e2b6e67b0f2d7a4ac8beb26908684e"
|
resolved "https://registry.yarnpkg.com/thunky/-/thunky-0.1.0.tgz#bf30146824e2b6e67b0f2d7a4ac8beb26908684e"
|
||||||
|
|
||||||
|
thyming@^0.1.1:
|
||||||
|
version "0.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/thyming/-/thyming-0.1.1.tgz#1c30f4fe168e6aae59b4c4cc23385accf4199205"
|
||||||
|
dependencies:
|
||||||
|
assert-function "^1.0.0"
|
||||||
|
|
||||||
time-stamp@^2.0.0:
|
time-stamp@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-2.0.0.tgz#95c6a44530e15ba8d6f4a3ecb8c3a3fac46da357"
|
resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-2.0.0.tgz#95c6a44530e15ba8d6f4a3ecb8c3a3fac46da357"
|
||||||
|
@ -8038,6 +8087,19 @@ wbuf@^1.1.0, wbuf@^1.7.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
minimalistic-assert "^1.0.0"
|
minimalistic-assert "^1.0.0"
|
||||||
|
|
||||||
|
weakmap-event@^2.0.7:
|
||||||
|
version "2.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/weakmap-event/-/weakmap-event-2.0.7.tgz#3f65318aba89e022981e8249bfae339a4ad6945a"
|
||||||
|
dependencies:
|
||||||
|
geval "~2.2.0"
|
||||||
|
key-difference "~1.0.0"
|
||||||
|
weakmap-shim "~1.1.0"
|
||||||
|
xtend "~4.0.0"
|
||||||
|
|
||||||
|
weakmap-shim@~1.1.0:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/weakmap-shim/-/weakmap-shim-1.1.1.tgz#d65afd784109b2166e00ff571c33150ec2a40b49"
|
||||||
|
|
||||||
webidl-conversions@^3.0.0:
|
webidl-conversions@^3.0.0:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||||
|
@ -8287,7 +8349,7 @@ xmlhttprequest@1:
|
||||||
version "1.8.0"
|
version "1.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
|
resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
|
||||||
|
|
||||||
xtend@^4.0.0, xtend@^4.0.1:
|
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
|
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue