diff --git a/crates/node-bindings/src/lib.rs b/crates/node-bindings/src/lib.rs index f7e9219920c..0388f007385 100644 --- a/crates/node-bindings/src/lib.rs +++ b/crates/node-bindings/src/lib.rs @@ -39,15 +39,20 @@ pub extern "C" fn napi_wasm_malloc(size: usize) -> *mut u8 { #[cfg(target_arch = "wasm32")] mod wasm { - use core::num::NonZeroU32; - use getrandom::register_custom_getrandom; - use getrandom::Error; - - // TODO - pub fn always_fail(buf: &mut [u8]) -> Result<(), Error> { - let code = NonZeroU32::new(Error::CUSTOM_START + 42).unwrap(); - Err(Error::from(code)) + use napi_derive::napi; + + #[link(wasm_import_module = "env")] + extern "C" { + fn log(ptr: *const u8, len: usize); } - register_custom_getrandom!(always_fail); + #[napi] + pub fn init_panic_hook() { + std::panic::set_hook(Box::new(|p| { + let s = p.to_string(); + unsafe { + log(s.as_ptr(), s.len()); + } + })); + } } diff --git a/package.json b/package.json index 8ec21939966..85da0a1d69f 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "build-ts": "lerna run build-ts && lerna run check-ts", "build-native": "node scripts/build-native.js", "build-native-release": "node scripts/build-native.js --release", + "build-native-wasm": "node scripts/build-native.js --release --wasm", "clean-test": "rimraf packages/core/integration-tests/.parcel-cache && rimraf packages/core/integration-tests/dist", "clean": "yarn clean-test && lerna clean --yes && lerna exec -- rimraf ./lib && yarn", "format": "prettier --write \"./packages/*/*/{src,bin,test}/**/*.{js,json,md}\" && cargo fmt --all", diff --git a/packages/core/core/package.json b/packages/core/core/package.json index f0458acbbd1..8a8a2e52b6e 100644 --- a/packages/core/core/package.json +++ b/packages/core/core/package.json @@ -46,7 +46,7 @@ "dotenv": "^7.0.0", "dotenv-expand": "^5.1.0", "json5": "^2.2.0", - "msgpackr": "^1.5.4", + "msgpackr": "^1.9.9", "nullthrows": "^1.1.1", "semver": "^7.5.2" }, diff --git a/packages/core/core/src/Parcel.js b/packages/core/core/src/Parcel.js index bf3beda11b2..6aad0bab6d7 100644 --- a/packages/core/core/src/Parcel.js +++ b/packages/core/core/src/Parcel.js @@ -544,6 +544,9 @@ export function createWorkerFarm( ): WorkerFarm { return new WorkerFarm({ ...options, - workerPath: require.resolve('./worker'), + // $FlowFixMe + workerPath: process.browser + ? '@parcel/core/src/worker.js' + : require.resolve('./worker'), }); } diff --git a/packages/core/core/src/requests/PathRequest.js b/packages/core/core/src/requests/PathRequest.js index 782355b073c..9d02c7616d4 100644 --- a/packages/core/core/src/requests/PathRequest.js +++ b/packages/core/core/src/requests/PathRequest.js @@ -190,7 +190,9 @@ export class ResolverRunner { diagnostic.codeFrames = [ { filePath, - code: await this.options.inputFS.readFile(filePath, 'utf8'), + code: await this.options.inputFS + .readFile(filePath, 'utf8') + .catch(() => ''), codeHighlights: dependency.loc ? [convertSourceLocationToHighlight(dependency.loc)] : [], diff --git a/packages/core/fs/src/MemoryFS.js b/packages/core/fs/src/MemoryFS.js index 176047c0e7d..7b5569a4ed8 100644 --- a/packages/core/fs/src/MemoryFS.js +++ b/packages/core/fs/src/MemoryFS.js @@ -918,13 +918,26 @@ function makeShared(contents: Buffer | string): Buffer { return contents; } - let length = Buffer.byteLength(contents); + let contentsBuffer: Buffer | string = contents; + // $FlowFixMe + if (process.browser) { + // For the polyfilled buffer module, it's faster to always convert once so that the subsequent + // operations are fast (.byteLength and using .set instead of .write) + contentsBuffer = + contentsBuffer instanceof Buffer + ? contentsBuffer + : Buffer.from(contentsBuffer); + } + + let length = Buffer.byteLength(contentsBuffer); let shared = new SharedBuffer(length); let buffer = Buffer.from(shared); - if (typeof contents === 'string') { - buffer.write(contents); - } else { - buffer.set(contents); + if (length > 0) { + if (typeof contentsBuffer === 'string') { + buffer.write(contentsBuffer); + } else { + buffer.set(contentsBuffer); + } } return buffer; diff --git a/packages/core/package-manager/src/utils.js b/packages/core/package-manager/src/utils.js index 27a752cb67f..acdecd07c4d 100644 --- a/packages/core/package-manager/src/utils.js +++ b/packages/core/package-manager/src/utils.js @@ -13,8 +13,10 @@ import {promisify} from 'util'; export const exec: ( command: string, options?: child_process$execOpts, -) => Promise<{|stdout: string | Buffer, stderr: string | Buffer|}> = - promisify(_exec); +) => Promise<{|stdout: string | Buffer, stderr: string | Buffer|}> = _exec + ? promisify(_exec) + : // _exec is undefined in browser builds + _exec; export function npmSpecifierFromModuleRequest( moduleRequest: ModuleRequest, diff --git a/packages/core/rust/browser.js b/packages/core/rust/browser.js index 268630a8d4c..110aeffb57d 100644 --- a/packages/core/rust/browser.js +++ b/packages/core/rust/browser.js @@ -1,30 +1,56 @@ -/* eslint-disable no-undef */ +/* global WebAssembly, crypto */ + const {Environment, napi} = require('napi-wasm'); -module.exports.Resolver = undefined; +let env; module.exports.init = async function init(input) { - if (module.exports.Resolver == null) { - // input = input ?? new URL('parcel_resolver_node.wasm', import.meta.url); - // const {instance} = await WebAssembly.instantiateStreaming(fetch(input), { - // env: napi, - // }); - - input = - input ?? require('path').join(__dirname, 'parcel_node_bindings.wasm'); - const {instance} = await WebAssembly.instantiate( - require('fs').readFileSync(input), - { - env: napi, + if (env) return; + + input = input ?? new URL('parcel_node_bindings.wasm', import.meta.url); + const {instance} = await WebAssembly.instantiateStreaming(fetch(input), { + env: { + ...napi, + __getrandom_custom: (ptr, len) => { + let buf = env.memory.subarray(ptr, ptr + len); + crypto.getRandomValues(buf); }, - ); + log: (ptr, len) => { + // eslint-disable-next-line no-console + console.log(env.getString(ptr, len)); + }, + }, + }); + + // input = + // input ?? require('path').join(__dirname, 'parcel_node_bindings.wasm'); + // const {instance} = await WebAssembly.instantiate( + // require('fs').readFileSync(input), + // { + // env: napi, + // }, + // ); - for (let key in instance.exports) { - if (key.startsWith('__napi_register__')) { - instance.exports[key](); - } + for (let key in instance.exports) { + if (key.startsWith('__napi_register__')) { + instance.exports[key](); } + } + + env = new Environment(instance); - let env = new Environment(instance); - Object.assign(module.exports, env.exports); + for (let key in env.exports) { + if (key !== 'transform') { + module.exports[key] = env.exports[key]; + } } + module.exports.transform = function (config) { + let result = env.exports.transform(config); + return { + ...result, + // Hydrate Uint8Array into Buffer + code: Buffer.from(result.code), + }; + }; + + env.exports.initPanicHook(); }; diff --git a/packages/core/rust/package.json b/packages/core/rust/package.json index cdf578404d6..aa7d71612ca 100644 --- a/packages/core/rust/package.json +++ b/packages/core/rust/package.json @@ -22,7 +22,7 @@ "node": ">= 12.0.0" }, "files": [ - "native-browser.js", + "browser.js", "index.d.ts", "index.js", "index.js.flow", @@ -37,6 +37,6 @@ "build": "napi build --platform --cargo-cwd ../../../crates/node-bindings", "build-release": "napi build --platform --release --cargo-cwd ../../../crates/node-bindings", "wasm:build": "cargo build -p parcel-node-bindings --target wasm32-unknown-unknown && cp ../../../target/wasm32-unknown-unknown/debug/parcel_node_bindings.wasm .", - "wasm:build-release": "CARGO_PROFILE_RELEASE_LTO=true cargo build --target wasm32-unknown-unknown --release && wasm-opt --strip-debug -O ../../target/wasm32-unknown-unknown/release/parcel_node_bindings.wasm -o ../../packages/core/rust/parcel_node_bindings.wasm" + "wasm:build-release": "CARGO_PROFILE_RELEASE_LTO=true cargo build -p parcel-node-bindings --target wasm32-unknown-unknown --release && wasm-opt --strip-debug -O ../../../target/wasm32-unknown-unknown/release/parcel_node_bindings.wasm -o parcel_node_bindings.wasm" } } diff --git a/packages/core/utils/package.json b/packages/core/utils/package.json index 1068d4b2da4..abee69f9087 100644 --- a/packages/core/utils/package.json +++ b/packages/core/utils/package.json @@ -57,12 +57,14 @@ "nullthrows": "^1.1.1", "open": "^7.0.3", "random-int": "^1.0.0", + "snarkdown": "^2.0.0", "strip-ansi": "^6.0.0", "terminal-link": "^2.1.1" }, "browser": { "./src/generateCertificate.js": false, "./src/http-server.js": false, - "./src/openInBrowser.js": false + "./src/openInBrowser.js": false, + "@parcel/markdown-ansi": false } } diff --git a/packages/core/utils/src/prettyDiagnostic.js b/packages/core/utils/src/prettyDiagnostic.js index 7df23d501cc..2eec732e316 100644 --- a/packages/core/utils/src/prettyDiagnostic.js +++ b/packages/core/utils/src/prettyDiagnostic.js @@ -3,11 +3,16 @@ import type {Diagnostic} from '@parcel/diagnostic'; import type {PluginOptions} from '@parcel/types'; import formatCodeFrame from '@parcel/codeframe'; -import mdAnsi from '@parcel/markdown-ansi'; -import chalk from 'chalk'; +import _mdAnsi from '@parcel/markdown-ansi'; +import _chalk from 'chalk'; import path from 'path'; // $FlowFixMe -import terminalLink from 'terminal-link'; +import _terminalLink from 'terminal-link'; + +/* eslint-disable import/no-extraneous-dependencies */ +// $FlowFixMe +import snarkdown from 'snarkdown'; +/* eslint-enable import/no-extraneous-dependencies */ export type FormattedCodeFrame = {| location: string, @@ -29,6 +34,7 @@ export default async function prettyDiagnostic( diagnostic: Diagnostic, options?: PluginOptions, terminalWidth?: number, + format: 'ansi' | 'html' = 'ansi', ): Promise { let { origin, @@ -40,10 +46,26 @@ export default async function prettyDiagnostic( documentationURL, } = diagnostic; + const md = format === 'ansi' ? _mdAnsi : snarkdown; + const terminalLink = + format === 'ansi' + ? _terminalLink + : // eslint-disable-next-line no-unused-vars + (text, url, _) => `${text}`; + const chalk = + format === 'ansi' + ? _chalk + : { + gray: { + underline: v => + `${v}`, + }, + }; + let result = { message: - mdAnsi(`**${origin ?? 'unknown'}**: `) + - (skipFormatting ? message : mdAnsi(message)), + md(`**${origin ?? 'unknown'}**: `) + + (skipFormatting ? message : md(message)), stack: '', codeframe: '', frames: [], @@ -104,7 +126,7 @@ export default async function prettyDiagnostic( if (Array.isArray(hints) && hints.length) { result.hints = hints.map(h => { - return mdAnsi(h); + return md(h); }); } diff --git a/packages/core/workers/package.json b/packages/core/workers/package.json index d6b1e6953ae..7ca27d03d8e 100644 --- a/packages/core/workers/package.json +++ b/packages/core/workers/package.json @@ -32,8 +32,8 @@ "@parcel/core": "^2.10.2" }, "browser": { - "./src/cpuCount.js": false, "./src/process/ProcessWorker.js": false, - "./src/threads/ThreadsWorker.js": false + "./src/threads/ThreadsWorker.js": false, + "./src/core-worker.js": "./src/core-worker.browser.js" } } diff --git a/packages/core/workers/src/Worker.js b/packages/core/workers/src/Worker.js index 996b4053a99..d5f7efcde9e 100644 --- a/packages/core/workers/src/Worker.js +++ b/packages/core/workers/src/Worker.js @@ -48,19 +48,22 @@ export default class Worker extends EventEmitter { } async fork(forkModule: FilePath) { - let filteredArgs = process.execArgv.filter( - v => !/^--(debug|inspect|no-opt|max-old-space-size=)/.test(v), - ); - - for (let i = 0; i < filteredArgs.length; i++) { - let arg = filteredArgs[i]; - let isArgWithParam = - ((arg === '-r' || arg === '--require') && - filteredArgs[i + 1] === '@parcel/register') || - arg === '--title'; - if (isArgWithParam) { - filteredArgs.splice(i, 2); - i--; + let filteredArgs = []; + if (process.execArgv) { + filteredArgs = process.execArgv.filter( + v => !/^--(debug|inspect|no-opt|max-old-space-size=)/.test(v), + ); + + for (let i = 0; i < filteredArgs.length; i++) { + let arg = filteredArgs[i]; + let isArgWithParam = + ((arg === '-r' || arg === '--require') && + filteredArgs[i + 1] === '@parcel/register') || + arg === '--title'; + if (isArgWithParam) { + filteredArgs.splice(i, 2); + i--; + } } } diff --git a/packages/core/workers/src/WorkerFarm.js b/packages/core/workers/src/WorkerFarm.js index 463502b9033..9ca1e928080 100644 --- a/packages/core/workers/src/WorkerFarm.js +++ b/packages/core/workers/src/WorkerFarm.js @@ -11,6 +11,8 @@ import type { } from './types'; import type {HandleFunction} from './Handle'; +import * as coreWorker from './core-worker'; +import * as bus from './bus'; import invariant from 'assert'; import nullthrows from 'nullthrows'; import EventEmitter from 'events'; @@ -46,9 +48,10 @@ export type FarmOptions = {| shouldTrace?: boolean, |}; -type WorkerModule = {| +type WorkerModule = { +[string]: (...args: Array) => Promise, -|}; + ... +}; export type WorkerApi = {| callMaster(CallRequest, ?boolean): Promise, @@ -74,6 +77,7 @@ export default class WorkerFarm extends EventEmitter { options: FarmOptions; run: HandleFunction; warmWorkers: number = 0; + readyWorkers: number = 0; workers: Map = new Map(); handles: Map = new Map(); sharedReferences: Map = new Map(); @@ -99,10 +103,23 @@ export default class WorkerFarm extends EventEmitter { throw new Error('Please provide a worker path!'); } - // $FlowFixMe this must be dynamic - this.localWorker = require(this.options.workerPath); + // $FlowFixMe + if (process.browser) { + if (this.options.workerPath === '@parcel/core/src/worker.js') { + this.localWorker = coreWorker; + } else { + throw new Error( + 'No dynamic require possible: ' + this.options.workerPath, + ); + } + } else { + // $FlowFixMe this must be dynamic + this.localWorker = require(this.options.workerPath); + } + this.localWorkerInit = this.localWorker.childInit != null ? this.localWorker.childInit() : null; + this.run = this.createHandle('run'); // Worker thread stdout is by default piped into the process stdout, if there are enough worker @@ -113,7 +130,7 @@ export default class WorkerFarm extends EventEmitter { // Note this can't be fixed easily where other things pipe into stdout - even after starting > 10 worker // threads `process.stdout.getMaxListeners()` will still return 10, however adding another pipe into `stdout` // will give the warning with `` as the number of listeners. - process.stdout.setMaxListeners( + process.stdout?.setMaxListeners( Math.max( process.stdout.getMaxListeners(), WorkerFarm.getNumWorkers() + 1, @@ -251,7 +268,13 @@ export default class WorkerFarm extends EventEmitter { worker.on('request', data => this.processRequest(data, worker)); - worker.on('ready', () => this.processQueue()); + worker.on('ready', () => { + this.readyWorkers++; + if (this.readyWorkers === this.options.maxConcurrentWorkers) { + this.emit('ready'); + } + this.processQueue(); + }); worker.on('response', () => this.processQueue()); worker.on('error', err => this.onError(err, worker)); @@ -332,8 +355,17 @@ export default class WorkerFarm extends EventEmitter { if (handleId != null) { mod = nullthrows(this.handles.get(handleId)?.fn); } else if (location) { - // $FlowFixMe this must be dynamic - mod = require(location); + // $FlowFixMe + if (process.browser) { + if (location === '@parcel/workers/src/bus.js') { + mod = (bus: any); + } else { + throw new Error('No dynamic require possible: ' + location); + } + } else { + // $FlowFixMe this must be dynamic + mod = require(location); + } } else { throw new Error('Unknown request'); } diff --git a/packages/core/workers/src/backend.js b/packages/core/workers/src/backend.js index 800e0e59282..1e28c2ca65d 100644 --- a/packages/core/workers/src/backend.js +++ b/packages/core/workers/src/backend.js @@ -2,6 +2,9 @@ import type {BackendType, WorkerImpl} from './types'; export function detectBackend(): BackendType { + // $FlowFixMe + if (process.browser) return 'web'; + switch (process.env.PARCEL_WORKER_BACKEND) { case 'threads': case 'process': @@ -22,6 +25,8 @@ export function getWorkerBackend(backend: BackendType): Class { return require('./threads/ThreadsWorker').default; case 'process': return require('./process/ProcessWorker').default; + case 'web': + return require('./web/WebWorker').default; default: throw new Error(`Invalid backend: ${backend}`); } diff --git a/packages/core/workers/src/bus.js b/packages/core/workers/src/bus.js index fe194521768..9f9c20377c8 100644 --- a/packages/core/workers/src/bus.js +++ b/packages/core/workers/src/bus.js @@ -7,7 +7,8 @@ class Bus extends EventEmitter { if (child) { child.workerApi.callMaster( { - location: __filename, + // $FlowFixMe + location: process.browser ? '@parcel/workers/src/bus.js' : __filename, method: 'emit', args: [event, ...args], }, diff --git a/packages/core/workers/src/child.js b/packages/core/workers/src/child.js index 2e276dad752..f300c03b9a1 100644 --- a/packages/core/workers/src/child.js +++ b/packages/core/workers/src/child.js @@ -12,6 +12,7 @@ import type { import type {Async, IDisposable} from '@parcel/types'; import type {SharedReference} from './WorkerFarm'; +import * as coreWorker from './core-worker'; import invariant from 'assert'; import nullthrows from 'nullthrows'; import Logger, {patchConsole, unpatchConsole} from '@parcel/logger'; @@ -100,8 +101,17 @@ export class Child { } async childInit(module: string, childId: number): Promise { - // $FlowFixMe this must be dynamic - this.module = require(module); + // $FlowFixMe + if (process.browser) { + if (module === '@parcel/core/src/worker.js') { + this.module = coreWorker; + } else { + throw new Error('No dynamic require possible: ' + module); + } + } else { + // $FlowFixMe this must be dynamic + this.module = require(module); + } this.childId = childId; if (this.module.childInit != null) { diff --git a/packages/core/workers/src/core-worker.browser.js b/packages/core/workers/src/core-worker.browser.js new file mode 100644 index 00000000000..54ba8ad7882 --- /dev/null +++ b/packages/core/workers/src/core-worker.browser.js @@ -0,0 +1,3 @@ +// @flow +// eslint-disable-next-line monorepo/no-internal-import +module.exports = require('@parcel/core/src/worker.js'); diff --git a/packages/core/workers/src/core-worker.js b/packages/core/workers/src/core-worker.js new file mode 100644 index 00000000000..a5d54f720ea --- /dev/null +++ b/packages/core/workers/src/core-worker.js @@ -0,0 +1,2 @@ +// This is used only in browser builds +module.exports = {}; diff --git a/packages/core/workers/src/cpuCount.js b/packages/core/workers/src/cpuCount.js index 2f09e6d110f..7893b8ea8bf 100644 --- a/packages/core/workers/src/cpuCount.js +++ b/packages/core/workers/src/cpuCount.js @@ -47,15 +47,23 @@ export default function getCores(bypassCache?: boolean = false): number { return cores; } - try { - cores = detectRealCores(); - } catch (e) { - // Guess the amount of real cores - cores = os - .cpus() - .filter( - (cpu, index) => !cpu.model.includes('Intel') || index % 2 === 1, - ).length; + // $FlowFixMe + if (process.browser) { + // eslint-disable-next-line no-undef + cores = navigator.hardwareConcurrency / 2; + } + + if (!cores) { + try { + cores = detectRealCores(); + } catch (e) { + // Guess the amount of real cores + cores = os + .cpus() + .filter( + (cpu, index) => !cpu.model.includes('Intel') || index % 2 === 1, + ).length; + } } // Another fallback diff --git a/packages/core/workers/src/types.js b/packages/core/workers/src/types.js index 172f16f6ad4..0f3fd242670 100644 --- a/packages/core/workers/src/types.js +++ b/packages/core/workers/src/types.js @@ -65,4 +65,4 @@ export interface ChildImpl { send(data: WorkerMessage): void; } -export type BackendType = 'threads' | 'process'; +export type BackendType = 'threads' | 'process' | 'web'; diff --git a/packages/core/workers/src/web/WebChild.js b/packages/core/workers/src/web/WebChild.js new file mode 100644 index 00000000000..920511a6a8c --- /dev/null +++ b/packages/core/workers/src/web/WebChild.js @@ -0,0 +1,50 @@ +// @flow +/* eslint-env worker*/ + +import type { + ChildImpl, + MessageHandler, + ExitHandler, + WorkerMessage, +} from '../types'; +import {setChild} from '../childState'; +import {Child} from '../child'; +import {prepareForSerialization, restoreDeserializedObject} from '@parcel/core'; + +export default class WebChild implements ChildImpl { + onMessage: MessageHandler; + onExit: ExitHandler; + + constructor(onMessage: MessageHandler, onExit: ExitHandler) { + if ( + !( + typeof WorkerGlobalScope !== 'undefined' && + self instanceof WorkerGlobalScope + ) + ) { + throw new Error('Only create WebChild instances in a worker!'); + } + + this.onMessage = onMessage; + this.onExit = onExit; + self.addEventListener('message', ({data}: MessageEvent) => { + if (data === 'stop') { + this.onExit(0); + self.postMessage('stopped'); + } + // $FlowFixMe assume WorkerMessage as data + this.handleMessage(data); + }); + self.postMessage('online'); + } + + handleMessage(data: WorkerMessage) { + this.onMessage(restoreDeserializedObject(data)); + } + + send(data: WorkerMessage) { + self.postMessage(prepareForSerialization(data)); + } +} + +setChild(new Child(WebChild)); diff --git a/packages/core/workers/src/web/WebWorker.js b/packages/core/workers/src/web/WebWorker.js new file mode 100644 index 00000000000..1e001da12b1 --- /dev/null +++ b/packages/core/workers/src/web/WebWorker.js @@ -0,0 +1,85 @@ +// @flow + +import type { + WorkerImpl, + MessageHandler, + ErrorHandler, + ExitHandler, + WorkerMessage, +} from '../types'; +import {prepareForSerialization, restoreDeserializedObject} from '@parcel/core'; +import {makeDeferredWithPromise} from '@parcel/utils'; + +let id = 0; + +export default class WebWorker implements WorkerImpl { + execArgv: Object; + onMessage: MessageHandler; + onError: ErrorHandler; + onExit: ExitHandler; + worker: Worker; + stopping: ?Promise; + + constructor( + execArgv: Object, + onMessage: MessageHandler, + onError: ErrorHandler, + onExit: ExitHandler, + ) { + this.execArgv = execArgv; + this.onMessage = onMessage; + this.onError = onError; + this.onExit = onExit; + } + + start(): Promise { + // $FlowFixMe[incompatible-call] + this.worker = new Worker(new URL('./WebChild.js', import.meta.url), { + name: `Parcel Worker ${id++}`, + type: 'module', + }); + + let {deferred, promise} = makeDeferredWithPromise(); + + this.worker.onmessage = ({data}) => { + if (data === 'online') { + deferred.resolve(); + return; + } + + // $FlowFixMe assume WorkerMessage as data + this.handleMessage(data); + }; + this.worker.onerror = this.onError; + // Web workers can't crash or intentionally stop on their own, apart from stop() below + // this.worker.on('exit', this.onExit); + + return promise; + } + + stop(): Promise { + if (!this.stopping) { + this.stopping = (async () => { + this.worker.postMessage('stop'); + let {deferred, promise} = makeDeferredWithPromise(); + this.worker.addEventListener('message', ({data}: MessageEvent) => { + if (data === 'stopped') { + deferred.resolve(); + } + }); + await promise; + this.worker.terminate(); + this.onExit(0); + })(); + } + return this.stopping; + } + + handleMessage(data: WorkerMessage) { + this.onMessage(restoreDeserializedObject(data)); + } + + send(data: WorkerMessage) { + this.worker.postMessage(prepareForSerialization(data)); + } +} diff --git a/packages/dev/query/src/cli.js b/packages/dev/query/src/cli.js index 32665480f09..ad86308082a 100644 --- a/packages/dev/query/src/cli.js +++ b/packages/dev/query/src/cli.js @@ -10,6 +10,7 @@ import repl from 'repl'; import os from 'os'; import nullthrows from 'nullthrows'; import invariant from 'assert'; +import {serialize} from 'v8'; // $FlowFixMe import {table} from 'table'; @@ -37,9 +38,8 @@ export async function run(input: string[]) { } console.log('Loading graphs...'); - let {assetGraph, bundleGraph, bundleInfo, requestTracker} = await loadGraphs( - cacheDir, - ); + let {assetGraph, bundleGraph, bundleInfo, requestTracker, cacheInfo} = + await loadGraphs(cacheDir); if (requestTracker == null) { console.error('Request Graph could not be found'); @@ -591,7 +591,54 @@ export async function run(input: string[]) { return entryBundleGroup; } + // eslint-disable-next-line no-unused-vars + function inspectCache(_) { + // displays sizing of various entries of the cache + let table: Array> = []; + table.push([ + 'Graphs', + 'Size (bytes)', + 'Deserialize (ms)', + 'Serialize (ms)', + ]); + let serialized: Map = new Map(); + serialized.set('RequestGraph', timeSerialize(requestTracker)); + serialized.set('bundle_graph_request', timeSerialize(bundleGraph)); + serialized.set('asset_graph_request', timeSerialize(assetGraph)); + for (let [k, v] of nullthrows(cacheInfo).entries()) { + let s = serialized.get(k); + invariant(s != null); + let name = k.includes('_request') ? k.split('_request')[0] : k; + table.push([name, ...v, s]); + } + function getColumnSum(t: Array>, col: number) { + if (t == null) { + return ''; + } + const initialValue = 0; + let column = t.map(r => r[col]); + column.shift(); + invariant(column != null); + return column.reduce( + (accumulator, currentValue) => accumulator + currentValue, + initialValue, + ); + } + table.push([ + 'Totals', + getColumnSum(table, 1), + getColumnSum(table, 2), + getColumnSum(table, 3), + ]); + _printStatsTable('Cache Info', table); + } + function timeSerialize(graph) { + let date = Date.now(); + serialize(graph); + date = Date.now() - date; + return date; + } function _printStatsTable(header, data) { const config = { columnDefault: { @@ -738,7 +785,8 @@ export async function run(input: string[]) { server.context.assetGraph = assetGraph; // $FlowFixMe[prop-missing] server.context.requestTracker = requestTracker; - + // $FlowFixMe[prop-missing] + server.context.cacheInfo = cacheInfo; for (let [name, cmd] of new Map([ [ 'getAsset', @@ -887,6 +935,13 @@ export async function run(input: string[]) { action: findAsset, }, ], + [ + 'inspectCache', + { + help: 'Cache Information', + action: inspectCache, + }, + ], [ 'findAssetWithSymbol', { diff --git a/packages/dev/query/src/index.js b/packages/dev/query/src/index.js index 1746fd010db..2875c909bce 100644 --- a/packages/dev/query/src/index.js +++ b/packages/dev/query/src/index.js @@ -25,6 +25,7 @@ export async function loadGraphs(cacheDir: string): Promise<{| bundleGraph: ?BundleGraph, requestTracker: ?RequestTracker, bundleInfo: ?Map, + cacheInfo: ?Map>, |}> { function filesBySizeAndModifiedTime() { let files = fs.readdirSync(cacheDir).map(f => { @@ -38,21 +39,32 @@ export async function loadGraphs(cacheDir: string): Promise<{| return files.map(([f]) => f); } + let cacheInfo: Map> = new Map(); + let timeToDeserialize = 0; + let requestTracker; const cache = new LMDBCache(cacheDir); for (let f of filesBySizeAndModifiedTime()) { // Empty filename or not the first chunk if (path.extname(f) !== '' && !f.endsWith('-0')) continue; try { - let obj = v8.deserialize( - await cache.getLargeBlob(path.basename(f).slice(0, -'-0'.length)), + let file = await cache.getLargeBlob( + path.basename(f).slice(0, -'-0'.length), ); + + cacheInfo.set('RequestGraph', [Buffer.byteLength(file)]); + + timeToDeserialize = Date.now(); + let obj = v8.deserialize(file); + timeToDeserialize = Date.now() - timeToDeserialize; + /* if (obj.assetGraph != null && obj.assetGraph.value.hash != null) { assetGraph = AssetGraph.deserialize(obj.assetGraph.value); } else if (obj.bundleGraph != null) { bundleGraph = BundleGraph.deserialize(obj.bundleGraph.value); } else */ if (obj['$$type']?.endsWith('RequestGraph')) { + let date = Date.now(); requestTracker = new RequestTracker({ graph: RequestGraph.deserialize(obj.value), // $FlowFixMe @@ -60,6 +72,7 @@ export async function loadGraphs(cacheDir: string): Promise<{| // $FlowFixMe options: null, }); + timeToDeserialize += Date.now() - date; break; } } catch (e) { @@ -75,7 +88,8 @@ export async function loadGraphs(cacheDir: string): Promise<{| // Load graphs by finding the main subrequests and loading their results let assetGraph, bundleGraph, bundleInfo; - + cacheInfo.set('bundle_graph_request', []); + cacheInfo.set('asset_graph_request', []); invariant(requestTracker); let buildRequestId = requestTracker.graph.getNodeIdByContentKey( 'parcel_build_request', @@ -94,8 +108,13 @@ export async function loadGraphs(cacheDir: string): Promise<{| ); if (bundleGraphRequestNode != null) { bundleGraph = BundleGraph.deserialize( - (await loadLargeBlobRequestRequest(cache, bundleGraphRequestNode)) - .bundleGraph.value, + ( + await loadLargeBlobRequestRequest( + cache, + bundleGraphRequestNode, + cacheInfo, + ) + ).bundleGraph.value, ); let assetGraphRequest = getSubRequests( @@ -103,12 +122,12 @@ export async function loadGraphs(cacheDir: string): Promise<{| ).find(n => n.type === 'request' && n.value.type === 'asset_graph_request'); if (assetGraphRequest != null) { assetGraph = AssetGraph.deserialize( - (await loadLargeBlobRequestRequest(cache, assetGraphRequest)).assetGraph - .value, + (await loadLargeBlobRequestRequest(cache, assetGraphRequest, cacheInfo)) + .assetGraph.value, ); } } - + cacheInfo.get('RequestGraph')?.push(timeToDeserialize); let writeBundlesRequest = buildRequestSubRequests.find( n => n.type === 'request' && n.value.type === 'write_bundles_request', ); @@ -121,12 +140,21 @@ export async function loadGraphs(cacheDir: string): Promise<{| >); } - return {assetGraph, bundleGraph, requestTracker, bundleInfo}; + return {assetGraph, bundleGraph, requestTracker, bundleInfo, cacheInfo}; } -async function loadLargeBlobRequestRequest(cache, node) { +async function loadLargeBlobRequestRequest(cache, node, cacheInfo) { invariant(node.type === 'request'); - return v8.deserialize( - await cache.getLargeBlob(nullthrows(node.value.resultCacheKey)), + + let cachedFile = await cache.getLargeBlob( + nullthrows(node.value.resultCacheKey), ); + cacheInfo.get(node.value.type)?.push(cachedFile.byteLength); //Add size + + let TTD = Date.now(); + let result = v8.deserialize(cachedFile); + TTD = Date.now() - TTD; + cacheInfo.get(node.value.type)?.push(TTD); + + return result; } diff --git a/packages/namers/default/src/DefaultNamer.js b/packages/namers/default/src/DefaultNamer.js index 45ce2002e6e..d98c718fc5a 100644 --- a/packages/namers/default/src/DefaultNamer.js +++ b/packages/namers/default/src/DefaultNamer.js @@ -136,7 +136,7 @@ function nameFromContent( } } - return name; + return name || 'bundle'; } } diff --git a/packages/optimizers/image/package.json b/packages/optimizers/image/package.json index 45e8ba122bc..76ffd910dbb 100644 --- a/packages/optimizers/image/package.json +++ b/packages/optimizers/image/package.json @@ -20,9 +20,7 @@ "parcel": "^2.10.2" }, "files": [ - "lib", - "native.js", - "*.node" + "lib" ], "dependencies": { "@parcel/diagnostic": "2.10.2", diff --git a/packages/transformers/css/package.json b/packages/transformers/css/package.json index 663d691642c..7accdc48ae4 100644 --- a/packages/transformers/css/package.json +++ b/packages/transformers/css/package.json @@ -27,5 +27,11 @@ "browserslist": "^4.6.6", "lightningcss": "^1.16.1", "nullthrows": "^1.1.1" + }, + "devDependencies": { + "lightningcss-wasm": "^1.16.1" + }, + "browser": { + "lightningcss": "./wasm-wrapper.js" } } diff --git a/packages/transformers/css/src/CSSTransformer.js b/packages/transformers/css/src/CSSTransformer.js index 7f2b2c6e7ee..71b79e358d9 100644 --- a/packages/transformers/css/src/CSSTransformer.js +++ b/packages/transformers/css/src/CSSTransformer.js @@ -5,22 +5,20 @@ import type {SourceLocation} from '@parcel/types'; import path from 'path'; import SourceMap from '@parcel/source-map'; import {Transformer} from '@parcel/plugin'; -import { - transform, - transformStyleAttribute, - browserslistToTargets, - type SourceLocation as LightningSourceLocation, -} from 'lightningcss'; import { remapSourceLocation, relativePath, globToRegex, normalizeSeparators, } from '@parcel/utils'; +import {type SourceLocation as LightningSourceLocation} from 'lightningcss'; +import * as native from 'lightningcss'; import browserslist from 'browserslist'; import nullthrows from 'nullthrows'; import ThrowableDiagnostic, {errorToDiagnostic} from '@parcel/diagnostic'; +const {transform, transformStyleAttribute, browserslistToTargets} = native; + export default (new Transformer({ async loadConfig({config, options}) { let conf = await config.getConfigFrom(options.projectRoot + '/index', [], { @@ -60,6 +58,8 @@ export default (new Transformer({ let [code, originalMap] = await Promise.all([ asset.getBuffer(), asset.getMap(), + // $FlowFixMe native.default is the init function only when bundled for the browser build + process.browser && native.default(), ]); let targets = getTargets(asset.env.engines.browsers); diff --git a/packages/transformers/css/wasm-wrapper.js b/packages/transformers/css/wasm-wrapper.js new file mode 100644 index 00000000000..6650fb596e2 --- /dev/null +++ b/packages/transformers/css/wasm-wrapper.js @@ -0,0 +1,26 @@ +import {transform, transformStyleAttribute} from 'lightningcss-wasm'; + +export {default, browserslistToTargets} from 'lightningcss-wasm'; + +// Hydrate Uint8Array into Buffer + +function transformWrapper(config) { + let result = transform(config); + return { + ...result, + code: Buffer.from(result.code), + map: result.map ? Buffer.from(result.map) : result.map, + }; +} +function transformStyleAttributeWrapper(config) { + let result = transformStyleAttribute(config); + return { + ...result, + code: Buffer.from(result.code), + }; +} + +export { + transformWrapper as transform, + transformStyleAttributeWrapper as transformStyleAttribute, +}; diff --git a/packages/transformers/js/package.json b/packages/transformers/js/package.json index 705ed9d5807..0ea03a39171 100644 --- a/packages/transformers/js/package.json +++ b/packages/transformers/js/package.json @@ -21,10 +21,7 @@ }, "files": [ "lib", - "native-browser.js", - "native.js", - "src", - "*.node" + "src" ], "dependencies": { "@parcel/diagnostic": "2.10.2", diff --git a/packages/utils/node-resolver-core/package.json b/packages/utils/node-resolver-core/package.json index 04cc90a2f64..5d90911e5b0 100644 --- a/packages/utils/node-resolver-core/package.json +++ b/packages/utils/node-resolver-core/package.json @@ -22,9 +22,7 @@ "test": "mocha test" }, "files": [ - "lib", - "native.js", - "*.node" + "lib" ], "dependencies": { "@mischnic/json-sourcemap": "^0.1.0", @@ -61,6 +59,6 @@ "vm-browserify": "^1.1.2" }, "browser": { - "./native.js": "./native-wasm-browser.js" + "./src/builtins.js": "./src/builtins.browser.js" } } diff --git a/packages/utils/node-resolver-core/src/builtins.browser.js b/packages/utils/node-resolver-core/src/builtins.browser.js new file mode 100644 index 00000000000..370b1d9ee94 --- /dev/null +++ b/packages/utils/node-resolver-core/src/builtins.browser.js @@ -0,0 +1,81 @@ +// @flow strict-local +const builtinModules = [ + '_http_agent', + '_http_client', + '_http_common', + '_http_incoming', + '_http_outgoing', + '_http_server', + '_stream_duplex', + '_stream_passthrough', + '_stream_readable', + '_stream_transform', + '_stream_wrap', + '_stream_writable', + '_tls_common', + '_tls_wrap', + 'assert', + 'assert/strict', + 'async_hooks', + 'buffer', + 'child_process', + 'cluster', + 'console', + 'constants', + 'crypto', + 'dgram', + 'diagnostics_channel', + 'dns', + 'dns/promises', + 'domain', + 'events', + 'fs', + 'fs/promises', + 'http', + 'http2', + 'https', + 'inspector', + 'module', + 'net', + 'os', + 'path', + 'path/posix', + 'path/win32', + 'perf_hooks', + 'process', + 'punycode', + 'querystring', + 'readline', + 'repl', + 'stream', + 'stream/consumers', + 'stream/promises', + 'stream/web', + 'string_decoder', + 'sys', + 'timers', + 'timers/promises', + 'tls', + 'trace_events', + 'tty', + 'url', + 'util', + 'util/types', + 'v8', + 'vm', + 'worker_threads', + 'zlib', +]; + +export const empty: string = '/_empty.js'; + +let builtins: {[string]: {|name: string, range: ?string|}, ...} = + // $FlowFixMe + Object.create(null); + +// use definite (current) list of Node builtins +for (let key of builtinModules) { + builtins[key] = {name: empty, range: null}; +} + +export default builtins; diff --git a/scripts/build-native.js b/scripts/build-native.js index a498e9f57af..417dceea6e3 100644 --- a/scripts/build-native.js +++ b/scripts/build-native.js @@ -5,6 +5,7 @@ const path = require('path'); const {spawn, execSync} = require('child_process'); let release = process.argv.includes('--release'); +let wasm = process.argv.includes('--wasm'); build(); async function build() { @@ -16,14 +17,17 @@ async function build() { for (let pkg of packages) { try { let pkgJSON = JSON.parse(fs.readFileSync(path.join(pkg, 'package.json'))); - if (!pkgJSON.napi) continue; + if (!wasm && !pkgJSON.napi) continue; + if (wasm && !pkgJSON.scripts?.['wasm:build-release']) continue; } catch (err) { continue; } console.log(`Building ${pkg}...`); await new Promise((resolve, reject) => { - let args = [release ? 'build-release' : 'build']; + let args = [ + (wasm ? 'wasm:' : '') + (release ? 'build-release' : 'build'), + ]; if (process.env.RUST_TARGET) { args.push('--target', process.env.RUST_TARGET); } diff --git a/yarn.lock b/yarn.lock index 3ed75981850..a969dcbda1b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,7 +17,7 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.22.10", "@babel/code-frame@^7.22.5": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.22.10", "@babel/code-frame@^7.22.13": version "7.22.13" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== @@ -82,12 +82,12 @@ eslint-visitor-keys "^2.1.0" semver "^6.3.1" -"@babel/generator@^7.12.5", "@babel/generator@^7.22.10": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.10.tgz#c92254361f398e160645ac58831069707382b722" - integrity sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A== +"@babel/generator@^7.12.5", "@babel/generator@^7.22.10", "@babel/generator@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" + integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g== dependencies: - "@babel/types" "^7.22.10" + "@babel/types" "^7.23.0" "@jridgewell/gen-mapping" "^0.3.2" "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" @@ -152,18 +152,18 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" -"@babel/helper-environment-visitor@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" - integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q== +"@babel/helper-environment-visitor@^7.22.20", "@babel/helper-environment-visitor@^7.22.5": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== -"@babel/helper-function-name@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be" - integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ== +"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== dependencies: - "@babel/template" "^7.22.5" - "@babel/types" "^7.22.5" + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" @@ -258,10 +258,10 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== -"@babel/helper-validator-identifier@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" - integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== +"@babel/helper-validator-identifier@^7.22.20", "@babel/helper-validator-identifier@^7.22.5": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== "@babel/helper-validator-option@^7.22.5": version "7.22.5" @@ -295,10 +295,10 @@ chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/parser@^7.12.7", "@babel/parser@^7.16.4", "@babel/parser@^7.22.11", "@babel/parser@^7.22.5", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6": - version "7.22.14" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.14.tgz#c7de58e8de106e88efca42ce17f0033209dfd245" - integrity sha512-1KucTHgOvaw/LzCVrEOAyXkr9rQlp0A1HiHRYnSUE9dmb8PvPW7o5sscg+5169r54n3vGlbx6GevTE/Iw/P3AQ== +"@babel/parser@^7.12.7", "@babel/parser@^7.16.4", "@babel/parser@^7.22.11", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" + integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5": version "7.22.5" @@ -1125,38 +1125,38 @@ dependencies: regenerator-runtime "^0.13.11" -"@babel/template@^7.12.7", "@babel/template@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" - integrity sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw== +"@babel/template@^7.12.7", "@babel/template@^7.22.15", "@babel/template@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== dependencies: - "@babel/code-frame" "^7.22.5" - "@babel/parser" "^7.22.5" - "@babel/types" "^7.22.5" + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" "@babel/traverse@^7.12.9", "@babel/traverse@^7.22.11": - version "7.22.11" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.11.tgz#71ebb3af7a05ff97280b83f05f8865ac94b2027c" - integrity sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ== - dependencies: - "@babel/code-frame" "^7.22.10" - "@babel/generator" "^7.22.10" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" + integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.22.11" - "@babel/types" "^7.22.11" + "@babel/parser" "^7.23.0" + "@babel/types" "^7.23.0" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.12.7", "@babel/types@^7.20.0", "@babel/types@^7.22.10", "@babel/types@^7.22.11", "@babel/types@^7.22.5", "@babel/types@^7.4.4", "@babel/types@^7.6.1", "@babel/types@^7.9.6": - version "7.22.11" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.11.tgz#0e65a6a1d4d9cbaa892b2213f6159485fe632ea2" - integrity sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg== +"@babel/types@^7.12.7", "@babel/types@^7.20.0", "@babel/types@^7.22.10", "@babel/types@^7.22.11", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.4.4", "@babel/types@^7.6.1", "@babel/types@^7.9.6": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" + integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== dependencies: "@babel/helper-string-parser" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" "@choojs/findup@^0.2.0": @@ -2811,9 +2811,9 @@ acorn-globals@^6.0.0: acorn-walk "^7.1.1" acorn-jsx@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" - integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-node@^1.6.1: version "1.8.2" @@ -3216,14 +3216,15 @@ asap@^2.0.0, asap@~2.0.3: resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== dependencies: bn.js "^4.0.0" inherits "^2.0.1" minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" asn1@~0.2.3: version "0.2.4" @@ -3528,11 +3529,16 @@ bluebird@~3.4.1: resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" integrity sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM= -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.9: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== +bn.js@^5.0.0, bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -3615,26 +3621,28 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= +browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== dependencies: - bn.js "^4.1.0" + bn.js "^5.0.0" randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= - dependencies: - bn.js "^4.1.1" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.2" - elliptic "^6.0.0" - inherits "^2.0.1" - parse-asn1 "^5.0.0" + version "4.2.2" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.2.tgz#e78d4b69816d6e3dd1c747e64e9947f9ad79bc7e" + integrity sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg== + dependencies: + bn.js "^5.2.1" + browserify-rsa "^4.1.0" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.4" + inherits "^2.0.4" + parse-asn1 "^5.1.6" + readable-stream "^3.6.2" + safe-buffer "^5.2.1" browserify-zlib@^0.2.0: version "0.2.0" @@ -4572,7 +4580,7 @@ create-ecdh@^4.0.0: bn.js "^4.1.0" elliptic "^6.0.0" -create-hash@^1.1.0, create-hash@^1.1.2: +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== @@ -4583,7 +4591,7 @@ create-hash@^1.1.0, create-hash@^1.1.2: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== @@ -4920,10 +4928,10 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debug@*, debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== +debug@*, debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4: + version "4.3.4" + resolved "https://packages.atlassian.com/api/npm/npm-remote/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" @@ -4955,13 +4963,6 @@ debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.3.4: - version "4.3.4" - resolved "https://packages.atlassian.com/api/npm/npm-remote/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -5368,7 +5369,7 @@ electron-to-chromium@^1.4.477: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.508.tgz#5641ff2f5ba11df4bd960fe6a2f9f70aa8b9af96" integrity sha512-FFa8QKjQK/A5QuFr2167myhMesGrhlOBD+3cYNxO9/S4XzHEXesyTD/1/xF644gC8buFPz3ca6G1LOQD0tZrrg== -elliptic@^6.0.0: +elliptic@^6.0.0, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -5936,9 +5937,9 @@ esprima@^4.0.0, esprima@^4.0.1: integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== dependencies: estraverse "^5.1.0" @@ -8590,6 +8591,13 @@ lightningcss-linux-x64-musl@1.16.1: resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.16.1.tgz#20b51081679dd6b7271ce11df825dc536a0c617c" integrity sha512-VZf76GxW+8mk238tpw0u9R66gBi/m0YB0TvD54oeGiOqvTZ/mabkBkbsuXTSWcKYj8DSrLW+A42qu+6PLRsIgA== +lightningcss-wasm@^1.16.1: + version "1.20.0" + resolved "https://registry.yarnpkg.com/lightningcss-wasm/-/lightningcss-wasm-1.20.0.tgz#863d8d92f950a22e13106ccda0e4a652fa72e87f" + integrity sha512-P3DhoMO+sI3iuGzXOeuXp91PPulL6O1KOmS5/gXwAAO/ZPyfBAO1mj29lIl+IDXg5jdKPvna+W2KckU/XQ2NOQ== + dependencies: + napi-wasm "^1.0.1" + lightningcss-win32-x64-msvc@1.16.1: version "1.16.1" resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.16.1.tgz#7546b4dca78314b1d2701ed220cb6e50b8c6b5ca" @@ -9423,7 +9431,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@^1.5.4, msgpackr@^1.9.5: +msgpackr@^1.9.5, msgpackr@^1.9.9: version "1.9.9" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.9.9.tgz#ec71e37beb8729280847f683cb0a340eb35ce70f" integrity sha512-sbn6mioS2w0lq1O6PpGtsv6Gy8roWM+o3o4Sqjd6DudrL/nOugY+KyJUimoWzHnf9OkO0T6broHFnYE/R05t9A== @@ -10226,14 +10234,13 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-asn1@^5.0.0: - version "5.1.5" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" - integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== +parse-asn1@^5.0.0, parse-asn1@^5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== dependencies: - asn1.js "^4.0.0" + asn1.js "^5.2.0" browserify-aes "^1.0.0" - create-hash "^1.1.0" evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" safe-buffer "^5.1.1" @@ -11454,10 +11461,10 @@ read@1, read@^1.0.7, read@~1.0.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" -"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== +"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -12229,6 +12236,11 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +snarkdown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/snarkdown/-/snarkdown-2.0.0.tgz#b1feb4db91b9f94a8ebbd7a50f3e99aee18b1e03" + integrity sha512-MgL/7k/AZdXCTJiNgrO7chgDqaB9FGM/1Tvlcenenb7div6obaDATzs16JhFyHHBGodHT3B7RzRc5qk8pFhg3A== + socks-proxy-agent@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386"