diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..1521c8b --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +dist diff --git a/Makefile b/Makefile index df45454..0c752a0 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ endif WEBPACK=npx webpack WEBPACK_DEV_SERVER=npx webpack-dev-server -WASM_FILES=src/waforth.wasm tests/benchmarks/sieve-vanilla/sieve-vanilla.wasm +WASM_FILES=src/waforth.wasm tests/benchmarks/sieve-vanilla.wasm all: $(WASM_FILES) $(WEBPACK) --mode=production @@ -20,7 +20,7 @@ src/waforth.wasm: src/waforth.wat dist racket -f $< > src/waforth.wat.tmp $(WAT2WASM) $(WAT2WASM_FLAGS) -o $@ src/waforth.wat.tmp -tests/benchmarks/sieve-vanilla/sieve-vanilla.wasm: tests/benchmarks/sieve-vanilla/sieve-vanilla.wat +tests/benchmarks/sieve-vanilla.wasm: tests/benchmarks/sieve-vanilla.wat $(WAT2WASM) $(WAT2WASM_FLAGS) -o $@ $< dist: diff --git a/package.json b/package.json index 522e088..dcdcc66 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,22 @@ { "private": true, "dependencies": { + "immutability-helper": "^2.7.0", "jq-console": "^2.13.2", "jquery": "^3.3.1", + "preact": "^8.2.9", "promise-polyfill": "^7.1.2" }, "devDependencies": { "babel-core": "^6.26.3", "babel-loader": "^7.1.4", + "babel-plugin-transform-react-jsx": "^6.24.1", "babel-preset-env": "^1.7.0", "bin-loader": "^0.1.0", "chai": "^4.1.2", "css-loader": "^0.28.11", "eslint": "4.13.1", + "eslint-plugin-react": "^7.8.2", "html-webpack-plugin": "^3.2.0", "mocha": "^5.2.0", "style-loader": "^0.21.0", diff --git a/tests/benchmarks/.eslintrc b/tests/benchmarks/.eslintrc new file mode 100644 index 0000000..acb1395 --- /dev/null +++ b/tests/benchmarks/.eslintrc @@ -0,0 +1,5 @@ +extends: + - plugin:react/recommended +rules: + react/react-in-jsx-scope: 0 + no-unused-vars: [2, { "varsIgnorePattern": "^h$" }] diff --git a/tests/benchmarks/index.css b/tests/benchmarks/index.css new file mode 100644 index 0000000..40a7a34 --- /dev/null +++ b/tests/benchmarks/index.css @@ -0,0 +1,16 @@ +table { + text-align: center; + border-collapse: collapse; +} + +table thead th { + min-width: 4em; + border-bottom: thin solid grey; +} + +pre.output { + margin: 0; + font-size: .5em; + text-align: left; +} + diff --git a/tests/benchmarks/index.js b/tests/benchmarks/index.js new file mode 100644 index 0000000..40f18f6 --- /dev/null +++ b/tests/benchmarks/index.js @@ -0,0 +1,161 @@ +import WAForth from "../../src/shell/WAForth"; +import sieve from "../../src/shell/sieve"; +import sieveVanillaModule from "./sieve-vanilla.wasm"; +import { Component, render, h } from "preact"; +import update from "immutability-helper"; +import "./index.css"; + +//////////////////////////////////////////////////////////////////////////////// +// Initial setup +//////////////////////////////////////////////////////////////////////////////// + +const setup = []; + +const forth = new WAForth(); +let outputBuffer = []; +forth.onEmit = c => { + outputBuffer.push(String.fromCharCode(c)); +}; +setup.push( + forth.start().then(() => { + forth.run(sieve); + }) +); + +let sieveVanilla; +setup.push( + WebAssembly.instantiate(sieveVanillaModule, { + js: { + print: x => console.log(x) + } + }).then(instance => { + sieveVanilla = instance.instance.exports.sieve; + }) +); + +//////////////////////////////////////////////////////////////////////////////// + +const ITERATIONS = 5; +const LIMIT = 50000000; +const benchmarks = [ + { + name: "sieve", + fn: () => { + outputBuffer = []; + forth.run(`${LIMIT} sieve`); + return outputBuffer.join(""); + } + }, + { + name: "sieve-vanilla", + fn: () => { + return sieveVanilla(LIMIT); + } + } +]; + +//////////////////////////////////////////////////////////////////////////////// + +const iterations = Array.from(Array(ITERATIONS).keys()); + +class Benchmarks extends Component { + constructor(props) { + super(props); + const results = {}; + benchmarks.forEach(({ name }) => (results[name] = [])); + this.state = { + initialized: false, + done: false, + results + }; + } + + componentDidMount() { + Promise.all(setup).then(() => { + this.setState({ initialized: true }); + let benchmarkIndex = 0; + let benchmarkIteration = 0; + const runNext = () => { + const t1 = performance.now(); + const output = benchmarks[benchmarkIndex].fn(); + const t2 = performance.now(); + this.setState({ + results: update(this.state.results, { + [benchmarks[benchmarkIndex].name]: { + [benchmarkIteration]: { + $set: { time: (t2 - t1) / 1000.0, output } + } + } + }) + }); + if (benchmarkIteration < ITERATIONS - 1) { + benchmarkIteration += 1; + window.setTimeout(runNext, 500); + } else if (benchmarkIndex < benchmarks.length - 1) { + benchmarkIndex += 1; + benchmarkIteration = 0; + window.setTimeout(runNext, 500); + } else { + this.setState({ done: true }); + } + }; + window.setTimeout(runNext, 500); + }); + } + + render() { + const { initialized, results } = this.state; + if (!initialized) { + return
Loading
; + } + return ( +
+ + + + )} + + + + + {benchmarks.map(({ name }) => { + const benchmark = results[name]; + const sum = benchmark.reduce((acc, { time }) => acc + time, 0); + return [ + + + {iterations.map(i => ( + + ))} + + , + + + ))} + + ]; + })} + +
+ {iterations.map(i => {i}Avg
{name} + {benchmark[i] == null ? null : ( + {benchmark[i].time.toFixed(2)}s + )} + + {benchmark.length === ITERATIONS ? ( + {(sum / benchmark.length).toFixed(2)}s + ) : ( + "⌛" + )} +
+ {iterations.map(i => ( + +
+                        {benchmark[i] == null ? null : benchmark[i].output}
+                      
+
+
+ ); + } +} +render(, document.body); diff --git a/tests/benchmarks/sieve-vanilla/sieve-vanilla.wat b/tests/benchmarks/sieve-vanilla.wat similarity index 100% rename from tests/benchmarks/sieve-vanilla/sieve-vanilla.wat rename to tests/benchmarks/sieve-vanilla.wat diff --git a/tests/benchmarks/sieve-vanilla/index.html b/tests/benchmarks/sieve-vanilla/index.html deleted file mode 100644 index 2469aff..0000000 --- a/tests/benchmarks/sieve-vanilla/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Sieve (Vanilla) - - - - - diff --git a/tests/benchmarks/sieve-vanilla/index.js b/tests/benchmarks/sieve-vanilla/index.js deleted file mode 100644 index dc1ae43..0000000 --- a/tests/benchmarks/sieve-vanilla/index.js +++ /dev/null @@ -1,12 +0,0 @@ -fetch("sieve-vanilla.wasm") - .then(resp => resp.arrayBuffer()) - .then(module => - WebAssembly.instantiate(module, { - js: { - print: x => console.log(x) - } - }) - ) - .then(instance => { - window.sieve = instance.instance.exports.sieve; - }); diff --git a/tests/benchmarks/sieve/index.html b/tests/benchmarks/sieve/index.html deleted file mode 100644 index 486da04..0000000 --- a/tests/benchmarks/sieve/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/tests/benchmarks/sieve/index.js b/tests/benchmarks/sieve/index.js deleted file mode 100644 index 94f7520..0000000 --- a/tests/benchmarks/sieve/index.js +++ /dev/null @@ -1,42 +0,0 @@ -import WAForth from "../../../src/shell/WAForth"; -import sieve from "../../../src/shell/sieve"; - -const ITERATIONS = 3; -const LIMIT = 50000000; - -const forth = new WAForth(); -let outputBuffer = []; -forth.onEmit = c => { - outputBuffer.push(String.fromCharCode(c)); -}; -document.body.innerHTML = "Loading..."; -forth.start().then( - () => { - document.body.innerHTML = "
Running...
"; - forth.run(sieve); - let i = 0; - const run = () => { - if (i < ITERATIONS) { - outputBuffer = []; - const t1 = performance.now(); - outputBuffer = [77, 88]; - forth.run(`${LIMIT} sieve`); - const t2 = performance.now(); - document.body.innerHTML = - document.body.innerHTML + - `
${outputBuffer.join(
-            ""
-          )}
${(t2 - t1) / 1000.0}
`; - i += 1; - window.setTimeout(run, 0); - } else { - document.body.innerHTML = document.body.innerHTML + "
Done
"; - } - }; - window.setTimeout(run, 10); - }, - err => { - console.error(err); - document.body.innerHTML = "Error"; - } -); diff --git a/webpack.config.js b/webpack.config.js index c07f054..8c90461 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -22,7 +22,8 @@ function config({ entry, outputDir, title, template, mode }) { use: { loader: "babel-loader", options: { - presets: ["es2015"] + presets: ["es2015"], + plugins: [["transform-react-jsx", { pragma: "h" }]] } } }, @@ -80,9 +81,9 @@ module.exports = (env, argv) => [ mode: argv.mode }), config({ - title: "Sieve Benchmark", - entry: "./tests/benchmarks/sieve/index.js", - outputDir: "sieve", + title: "Benchmarks", + entry: "./tests/benchmarks/index.js", + outputDir: "benchmarks", mode: argv.mode }) ]; diff --git a/yarn.lock b/yarn.lock index 8fb2fb6..3f291ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -332,6 +332,10 @@ arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -452,6 +456,14 @@ babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: babel-runtime "^6.22.0" babel-types "^6.24.1" +babel-helper-builder-react-jsx@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + esutils "^2.0.2" + babel-helper-call-delegate@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" @@ -610,6 +622,10 @@ babel-plugin-syntax-flow@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" +babel-plugin-syntax-jsx@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" + babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" @@ -858,6 +874,14 @@ babel-plugin-transform-object-rest-spread@^6.22.0: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.26.0" +babel-plugin-transform-react-jsx@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" + dependencies: + babel-helper-builder-react-jsx "^6.24.1" + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" @@ -1680,6 +1704,10 @@ copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" +core-js@^1.0.0: + version "1.2.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" + core-js@^2.4.0, core-js@^2.5.0: version "2.5.6" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.6.tgz#0fe6d45bf3cac3ac364a9d72de7576f4eb221b9d" @@ -2163,6 +2191,12 @@ encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + dependencies: + iconv-lite "~0.4.13" + end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" @@ -2253,6 +2287,15 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" +eslint-plugin-react@^7.8.2: + version "7.8.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.8.2.tgz#e95c9c47fece55d2303d1a67c9d01b930b88a51d" + dependencies: + doctrine "^2.0.2" + has "^1.0.1" + jsx-ast-utils "^2.0.1" + prop-types "^15.6.0" + eslint-scope@^3.7.1: version "3.7.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" @@ -2526,6 +2569,18 @@ faye-websocket@~0.11.0: dependencies: websocket-driver ">=0.5.1" +fbjs@^0.8.16: + version "0.8.16" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" + dependencies: + core-js "^1.0.0" + isomorphic-fetch "^2.1.1" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.9" + figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" @@ -3130,7 +3185,7 @@ iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" -iconv-lite@^0.4.17, iconv-lite@^0.4.4: +iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" dependencies: @@ -3164,6 +3219,12 @@ ignore@^3.3.3, ignore@^3.3.5: version "3.3.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.8.tgz#3f8e9c35d38708a3a7e0e9abb6c73e7ee7707b2b" +immutability-helper@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/immutability-helper/-/immutability-helper-2.7.0.tgz#4ea9916cc8f45142ec3e3f0fce75fa5d66fa1b38" + dependencies: + invariant "^2.2.0" + import-local@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc" @@ -3266,7 +3327,7 @@ into-stream@^3.1.0: from2 "^2.1.1" p-is-promise "^1.1.0" -invariant@^2.2.2: +invariant@^2.2.0, invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" dependencies: @@ -3508,7 +3569,7 @@ is-scoped@^1.0.0: dependencies: scoped-regex "^1.0.0" -is-stream@^1.0.0, is-stream@^1.1.0: +is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -3560,6 +3621,13 @@ isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" +isomorphic-fetch@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + dependencies: + node-fetch "^1.0.1" + whatwg-fetch ">=0.10.0" + istextorbinary@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-2.2.1.tgz#a5231a08ef6dd22b268d0895084cf8d58b5bec53" @@ -3677,6 +3745,12 @@ json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" +jsx-ast-utils@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f" + dependencies: + array-includes "^3.0.3" + keyv@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" @@ -3868,7 +3942,7 @@ long@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" -loose-envify@^1.0.0: +loose-envify@^1.0.0, loose-envify@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" dependencies: @@ -4257,6 +4331,13 @@ node-dir@0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.8.tgz#55fb8deb699070707fb67f91a460f0448294c77d" +node-fetch@^1.0.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + node-forge@0.7.5: version "0.7.5" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df" @@ -5009,6 +5090,10 @@ postcss@^6.0.1: source-map "^0.6.1" supports-color "^5.4.0" +preact@^8.2.9: + version "8.2.9" + resolved "https://registry.yarnpkg.com/preact/-/preact-8.2.9.tgz#813ba9dd45e5d97c5ea0d6c86d375b3be711cc40" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -5064,6 +5149,20 @@ promise-polyfill@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-7.1.2.tgz#ab05301d8c28536301622d69227632269a70ca3b" +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + dependencies: + asap "~2.0.3" + +prop-types@^15.6.0: + version "15.6.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.3.1" + object-assign "^4.1.1" + proxy-addr@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341" @@ -5643,7 +5742,7 @@ set-value@^2.0.0: is-plain-object "^2.0.3" split-string "^3.0.1" -setimmediate@^1.0.4: +setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -6162,6 +6261,10 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" +ua-parser-js@^0.7.9: + version "0.7.18" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed" + uglify-es@^3.3.4: version "3.3.9" resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" @@ -6535,6 +6638,10 @@ websocket-extensions@>=0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" +whatwg-fetch@>=0.10.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + whet.extend@~0.9.9: version "0.9.9" resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1"